• 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 Graphics pipeline for SPIR-V assembly tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSpvAsmGraphicsShaderTestUtil.hpp"
25 
26 #include "tcuFloat.hpp"
27 #include "tcuStringTemplate.hpp"
28 #include "tcuTextureUtil.hpp"
29 
30 #include "vkDefs.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkPlatform.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkCmdUtil.hpp"
38 
39 #include "deRandom.hpp"
40 
41 namespace vkt
42 {
43 namespace SpirVAssembly
44 {
45 
46 using namespace vk;
47 using std::map;
48 using std::string;
49 using std::vector;
50 using tcu::Float16;
51 using tcu::Float32;
52 using tcu::Float64;
53 using tcu::IVec3;
54 using tcu::IVec4;
55 using tcu::RGBA;
56 using tcu::TestLog;
57 using tcu::TestStatus;
58 using tcu::Vec4;
59 using de::UniquePtr;
60 using tcu::StringTemplate;
61 using tcu::Vec4;
62 
getElementNumBytes(void) const63 deUint32 IFDataType::getElementNumBytes (void) const
64 {
65 	if (elementType < NUMBERTYPE_END32)
66 		return 4;
67 
68 	if (elementType < NUMBERTYPE_END16)
69 		return 2;
70 
71 	return 8;
72 }
73 
getVkFormat(void) const74 VkFormat IFDataType::getVkFormat (void) const
75 {
76 	if (numElements == 1)
77 	{
78 		switch (elementType)
79 		{
80 			case NUMBERTYPE_FLOAT64:	return VK_FORMAT_R64_SFLOAT;
81 			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32_SFLOAT;
82 			case NUMBERTYPE_INT32:		return VK_FORMAT_R32_SINT;
83 			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32_UINT;
84 			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16_SFLOAT;
85 			case NUMBERTYPE_INT16:		return VK_FORMAT_R16_SINT;
86 			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16_UINT;
87 			default:					break;
88 		}
89 	}
90 	else if (numElements == 2)
91 	{
92 		switch (elementType)
93 		{
94 			case NUMBERTYPE_FLOAT64:	return VK_FORMAT_R64G64_SFLOAT;
95 			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32G32_SFLOAT;
96 			case NUMBERTYPE_INT32:		return VK_FORMAT_R32G32_SINT;
97 			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32G32_UINT;
98 			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16G16_SFLOAT;
99 			case NUMBERTYPE_INT16:		return VK_FORMAT_R16G16_SINT;
100 			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16G16_UINT;
101 			default:					break;
102 		}
103 	}
104 	else if (numElements == 3)
105 	{
106 		switch (elementType)
107 		{
108 			case NUMBERTYPE_FLOAT64:	return VK_FORMAT_R64G64B64_SFLOAT;
109 			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32G32B32_SFLOAT;
110 			case NUMBERTYPE_INT32:		return VK_FORMAT_R32G32B32_SINT;
111 			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32G32B32_UINT;
112 			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16G16B16_SFLOAT;
113 			case NUMBERTYPE_INT16:		return VK_FORMAT_R16G16B16_SINT;
114 			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16G16B16_UINT;
115 			default:					break;
116 		}
117 	}
118 	else if (numElements == 4)
119 	{
120 		switch (elementType)
121 		{
122 			case NUMBERTYPE_FLOAT64:	return VK_FORMAT_R64G64B64A64_SFLOAT;
123 			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32G32B32A32_SFLOAT;
124 			case NUMBERTYPE_INT32:		return VK_FORMAT_R32G32B32A32_SINT;
125 			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32G32B32A32_UINT;
126 			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16G16B16A16_SFLOAT;
127 			case NUMBERTYPE_INT16:		return VK_FORMAT_R16G16B16A16_SINT;
128 			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16G16B16A16_UINT;
129 			default:					break;
130 		}
131 	}
132 
133 	DE_ASSERT(false);
134 	return VK_FORMAT_UNDEFINED;
135 }
136 
getTextureFormat(void) const137 tcu::TextureFormat IFDataType::getTextureFormat (void) const
138 {
139 	tcu::TextureFormat::ChannelType		ct	= tcu::TextureFormat::CHANNELTYPE_LAST;
140 	tcu::TextureFormat::ChannelOrder	co	= tcu::TextureFormat::CHANNELORDER_LAST;
141 
142 	switch (elementType)
143 	{
144 		case NUMBERTYPE_FLOAT64:	ct = tcu::TextureFormat::FLOAT64;			break;
145 		case NUMBERTYPE_FLOAT32:	ct = tcu::TextureFormat::FLOAT;				break;
146 		case NUMBERTYPE_INT32:		ct = tcu::TextureFormat::SIGNED_INT32;		break;
147 		case NUMBERTYPE_UINT32:		ct = tcu::TextureFormat::UNSIGNED_INT32;	break;
148 		case NUMBERTYPE_FLOAT16:	ct = tcu::TextureFormat::HALF_FLOAT;		break;
149 		case NUMBERTYPE_INT16:		ct = tcu::TextureFormat::SIGNED_INT16;		break;
150 		case NUMBERTYPE_UINT16:		ct = tcu::TextureFormat::UNSIGNED_INT16;	break;
151 		default:					DE_ASSERT(false);
152 	}
153 
154 	switch (numElements)
155 	{
156 		case 1:				co = tcu::TextureFormat::R;					break;
157 		case 2:				co = tcu::TextureFormat::RG;				break;
158 		case 3:				co = tcu::TextureFormat::RGB;				break;
159 		case 4:				co = tcu::TextureFormat::RGBA;				break;
160 		default:			DE_ASSERT(false);
161 	}
162 
163 	return tcu::TextureFormat(co, ct);
164 }
165 
str(void) const166 string IFDataType::str (void) const
167 {
168 	string	ret;
169 
170 	switch (elementType)
171 	{
172 		case NUMBERTYPE_FLOAT64:	ret = "f64"; break;
173 		case NUMBERTYPE_FLOAT32:	ret = "f32"; break;
174 		case NUMBERTYPE_INT32:		ret = "i32"; break;
175 		case NUMBERTYPE_UINT32:		ret = "u32"; break;
176 		case NUMBERTYPE_FLOAT16:	ret = "f16"; break;
177 		case NUMBERTYPE_INT16:		ret = "i16"; break;
178 		case NUMBERTYPE_UINT16:		ret = "u16"; break;
179 		default:					DE_ASSERT(false);
180 	}
181 
182 	if (numElements == 1)
183 		return ret;
184 
185 	return string("v") + numberToString(numElements) + ret;
186 }
187 
getMatchingBufferUsageFlagBit(VkDescriptorType dType)188 VkBufferUsageFlagBits getMatchingBufferUsageFlagBit (VkDescriptorType dType)
189 {
190 	switch (dType)
191 	{
192 		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:			return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
193 		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:			return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
194 		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:			return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
195 		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:			return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
196 		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:	return VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
197 		default:										DE_ASSERT(0 && "not implemented");
198 	}
199 	return (VkBufferUsageFlagBits)0;
200 }
201 
getMatchingImageUsageFlags(VkDescriptorType dType)202 VkImageUsageFlags getMatchingImageUsageFlags (VkDescriptorType dType)
203 {
204 	switch (dType)
205 	{
206 		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:			return VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
207 		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:			return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
208 		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:	return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
209 		default:										DE_FATAL("Not implemented");
210 	}
211 	return (VkImageUsageFlags)0;
212 }
213 
requireFormatUsageSupport(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,VkFormat format,VkImageTiling imageTiling,VkImageUsageFlags requiredUsageFlags)214 static void requireFormatUsageSupport (const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkFormat format, VkImageTiling imageTiling, VkImageUsageFlags requiredUsageFlags)
215 {
216 	VkFormatProperties		properties;
217 	VkFormatFeatureFlags	tilingFeatures	= 0;
218 
219 	vki.getPhysicalDeviceFormatProperties(physicalDevice, format, &properties);
220 
221 	switch (imageTiling)
222 	{
223 		case VK_IMAGE_TILING_LINEAR:
224 			tilingFeatures = properties.linearTilingFeatures;
225 			break;
226 
227 		case VK_IMAGE_TILING_OPTIMAL:
228 			tilingFeatures = properties.optimalTilingFeatures;
229 			break;
230 
231 		default:
232 			DE_ASSERT(false);
233 			break;
234 	}
235 
236 	if ((requiredUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0)
237 	{
238 		if ((tilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
239 			TCU_THROW(NotSupportedError, "Image format cannot be used as color attachment");
240 		requiredUsageFlags ^= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
241 	}
242 
243 
244 	if ((requiredUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) != 0)
245 	{
246 		if ((tilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0)
247 			TCU_THROW(NotSupportedError, "Image format cannot be used as transfer source");
248 		requiredUsageFlags ^= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
249 	}
250 
251 
252 	DE_ASSERT(!requiredUsageFlags && "checking other image usage bits not supported yet");
253 }
254 
InstanceContext(const RGBA (& inputs)[4],const RGBA (& outputs)[4],const map<string,string> & testCodeFragments_,const StageToSpecConstantMap & specConstants_,const PushConstants & pushConsants_,const GraphicsResources & resources_,const GraphicsInterfaces & interfaces_,const vector<string> & extensions_,VulkanFeatures vulkanFeatures_,VkShaderStageFlags customizedStages_)255 InstanceContext::InstanceContext (const RGBA						(&inputs)[4],
256 								  const RGBA						(&outputs)[4],
257 								  const map<string, string>&		testCodeFragments_,
258 								  const StageToSpecConstantMap&		specConstants_,
259 								  const PushConstants&				pushConsants_,
260 								  const GraphicsResources&			resources_,
261 								  const GraphicsInterfaces&			interfaces_,
262 								  const vector<string>&				extensions_,
263 								  VulkanFeatures					vulkanFeatures_,
264 								  VkShaderStageFlags				customizedStages_)
265 	: testCodeFragments				(testCodeFragments_)
266 	, specConstants					(specConstants_)
267 	, hasTessellation				(false)
268 	, requiredStages				(static_cast<VkShaderStageFlagBits>(0))
269 	, requiredDeviceExtensions		(extensions_)
270 	, requestedFeatures				(vulkanFeatures_)
271 	, pushConstants					(pushConsants_)
272 	, customizedStages				(customizedStages_)
273 	, resources						(resources_)
274 	, interfaces					(interfaces_)
275 	, failResult					(QP_TEST_RESULT_FAIL)
276 	, failMessageTemplate			("${reason}")
277 	, renderFullSquare				(false)
278 	, splitRenderArea				(false)
279 {
280 	inputColors[0]		= inputs[0];
281 	inputColors[1]		= inputs[1];
282 	inputColors[2]		= inputs[2];
283 	inputColors[3]		= inputs[3];
284 
285 	outputColors[0]		= outputs[0];
286 	outputColors[1]		= outputs[1];
287 	outputColors[2]		= outputs[2];
288 	outputColors[3]		= outputs[3];
289 }
290 
InstanceContext(const InstanceContext & other)291 InstanceContext::InstanceContext (const InstanceContext& other)
292 	: moduleMap						(other.moduleMap)
293 	, testCodeFragments				(other.testCodeFragments)
294 	, specConstants					(other.specConstants)
295 	, hasTessellation				(other.hasTessellation)
296 	, requiredStages				(other.requiredStages)
297 	, requiredDeviceExtensions		(other.requiredDeviceExtensions)
298 	, requestedFeatures				(other.requestedFeatures)
299 	, pushConstants					(other.pushConstants)
300 	, customizedStages				(other.customizedStages)
301 	, resources						(other.resources)
302 	, interfaces					(other.interfaces)
303 	, failResult					(other.failResult)
304 	, failMessageTemplate			(other.failMessageTemplate)
305 	, renderFullSquare				(other.renderFullSquare)
306 	, splitRenderArea				(other.splitRenderArea)
307 {
308 	inputColors[0]		= other.inputColors[0];
309 	inputColors[1]		= other.inputColors[1];
310 	inputColors[2]		= other.inputColors[2];
311 	inputColors[3]		= other.inputColors[3];
312 
313 	outputColors[0]		= other.outputColors[0];
314 	outputColors[1]		= other.outputColors[1];
315 	outputColors[2]		= other.outputColors[2];
316 	outputColors[3]		= other.outputColors[3];
317 }
318 
getSpecializedFailMessage(const string & failureReason)319 string InstanceContext::getSpecializedFailMessage (const string& failureReason)
320 {
321 	map<string, string>		parameters;
322 	parameters["reason"]	= failureReason;
323 	return StringTemplate(failMessageTemplate).specialize(parameters);
324 }
325 
createInstanceContext(const std::vector<ShaderElement> & elements,const tcu::RGBA (& inputColors)[4],const tcu::RGBA (& outputColors)[4],const std::map<std::string,std::string> & testCodeFragments,const StageToSpecConstantMap & specConstants,const PushConstants & pushConstants,const GraphicsResources & resources,const GraphicsInterfaces & interfaces,const std::vector<std::string> & extensions,VulkanFeatures vulkanFeatures,VkShaderStageFlags customizedStages,const qpTestResult failResult,const std::string & failMessageTemplate)326 InstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
327 									   const tcu::RGBA								(&inputColors)[4],
328 									   const tcu::RGBA								(&outputColors)[4],
329 									   const std::map<std::string, std::string>&	testCodeFragments,
330 									   const StageToSpecConstantMap&				specConstants,
331 									   const PushConstants&							pushConstants,
332 									   const GraphicsResources&						resources,
333 									   const GraphicsInterfaces&					interfaces,
334 									   const std::vector<std::string>&				extensions,
335 									   VulkanFeatures								vulkanFeatures,
336 									   VkShaderStageFlags							customizedStages,
337 									   const qpTestResult							failResult,
338 									   const std::string&							failMessageTemplate)
339 {
340 	InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources, interfaces, extensions, vulkanFeatures, customizedStages);
341 	for (size_t i = 0; i < elements.size(); ++i)
342 	{
343 		ctx.moduleMap[elements[i].moduleName].push_back(std::make_pair(elements[i].entryName, elements[i].stage));
344 		ctx.requiredStages = static_cast<VkShaderStageFlagBits>(ctx.requiredStages | elements[i].stage);
345 	}
346 	ctx.failResult				= failResult;
347 	if (!failMessageTemplate.empty())
348 		ctx.failMessageTemplate	= failMessageTemplate;
349 	return ctx;
350 }
351 
createInstanceContext(const std::vector<ShaderElement> & elements,tcu::RGBA (& inputColors)[4],const tcu::RGBA (& outputColors)[4],const std::map<std::string,std::string> & testCodeFragments)352 InstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
353 									   tcu::RGBA									(&inputColors)[4],
354 									   const tcu::RGBA								(&outputColors)[4],
355 									   const std::map<std::string, std::string>&	testCodeFragments)
356 {
357 	return createInstanceContext(elements, inputColors, outputColors, testCodeFragments,
358 								 StageToSpecConstantMap(), PushConstants(), GraphicsResources(),
359 								 GraphicsInterfaces(), std::vector<std::string>(),
360 								 VulkanFeatures(), vk::VK_SHADER_STAGE_ALL);
361 }
362 
createInstanceContext(const std::vector<ShaderElement> & elements,const std::map<std::string,std::string> & testCodeFragments)363 InstanceContext createInstanceContext (const std::vector<ShaderElement>&			elements,
364 									   const std::map<std::string, std::string>&	testCodeFragments)
365 {
366 	tcu::RGBA defaultColors[4];
367 	getDefaultColors(defaultColors);
368 	return createInstanceContext(elements, defaultColors, defaultColors, testCodeFragments);
369 }
370 
createUnusedVariableContext(const ShaderTaskArray & shaderTasks,const VariableLocation & location)371 UnusedVariableContext createUnusedVariableContext(const ShaderTaskArray& shaderTasks, const VariableLocation& location)
372 {
373 	for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(shaderTasks); ++i)
374 	{
375 		DE_ASSERT(shaderTasks[i] >= 0 && shaderTasks[i] < SHADER_TASK_LAST);
376 	}
377 
378 	std::vector<ShaderElement> elements;
379 
380 	DE_ASSERT(shaderTasks[SHADER_TASK_INDEX_VERTEX]		!= SHADER_TASK_NONE);
381 	DE_ASSERT(shaderTasks[SHADER_TASK_INDEX_FRAGMENT]	!= SHADER_TASK_NONE);
382 	elements.push_back(ShaderElement("vert", "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
383 	elements.push_back(ShaderElement("frag", "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
384 
385 	if (shaderTasks[SHADER_TASK_INDEX_GEOMETRY] != SHADER_TASK_NONE)
386 		elements.push_back(ShaderElement("geom", "main", vk::VK_SHADER_STAGE_GEOMETRY_BIT));
387 
388 	if (shaderTasks[SHADER_TASK_INDEX_TESS_CONTROL] != SHADER_TASK_NONE)
389 		elements.push_back(ShaderElement("tessc", "main", vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
390 
391 	if (shaderTasks[SHADER_TASK_INDEX_TESS_EVAL] != SHADER_TASK_NONE)
392 		elements.push_back(ShaderElement("tesse", "main", vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
393 
394 	return UnusedVariableContext(
395 		createInstanceContext(elements, map<string, string>()),
396 		shaderTasks,
397 		location);
398 }
399 
ShaderElement(const string & moduleName_,const string & entryPoint_,VkShaderStageFlagBits shaderStage_)400 ShaderElement::ShaderElement (const string&				moduleName_,
401 							  const string&				entryPoint_,
402 							  VkShaderStageFlagBits		shaderStage_)
403 		: moduleName(moduleName_)
404 		, entryName(entryPoint_)
405 		, stage(shaderStage_)
406 {
407 }
408 
getDefaultColors(RGBA (& colors)[4])409 void getDefaultColors (RGBA (&colors)[4])
410 {
411 	colors[0] = RGBA::white();
412 	colors[1] = RGBA::red();
413 	colors[2] = RGBA::green();
414 	colors[3] = RGBA::blue();
415 }
416 
getHalfColorsFullAlpha(RGBA (& colors)[4])417 void getHalfColorsFullAlpha (RGBA (&colors)[4])
418 {
419 	colors[0] = RGBA(127, 127, 127, 255);
420 	colors[1] = RGBA(127, 0,   0,	255);
421 	colors[2] = RGBA(0,	  127, 0,	255);
422 	colors[3] = RGBA(0,	  0,   127, 255);
423 }
424 
getInvertedDefaultColors(RGBA (& colors)[4])425 void getInvertedDefaultColors (RGBA (&colors)[4])
426 {
427 	colors[0] = RGBA(0,		0,		0,		255);
428 	colors[1] = RGBA(0,		255,	255,	255);
429 	colors[2] = RGBA(255,	0,		255,	255);
430 	colors[3] = RGBA(255,	255,	0,		255);
431 }
432 
433 // For the current InstanceContext, constructs the required modules and shader stage create infos.
createPipelineShaderStages(const DeviceInterface & vk,const VkDevice vkDevice,InstanceContext & instance,Context & context,vector<ModuleHandleSp> & modules,vector<VkPipelineShaderStageCreateInfo> & createInfos)434 void createPipelineShaderStages (const DeviceInterface&						vk,
435 								 const VkDevice								vkDevice,
436 								 InstanceContext&							instance,
437 								 Context&									context,
438 								 vector<ModuleHandleSp>&					modules,
439 								 vector<VkPipelineShaderStageCreateInfo>&	createInfos)
440 {
441 	for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx)
442 	{
443 		const ModuleHandleSp mod(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, context.getBinaryCollection().get(moduleNdx->first), 0)));
444 		modules.push_back(ModuleHandleSp(mod));
445 		for (vector<EntryToStage>::const_iterator shaderNdx = moduleNdx->second.begin(); shaderNdx != moduleNdx->second.end(); ++shaderNdx)
446 		{
447 			const EntryToStage&						stage			= *shaderNdx;
448 			const VkPipelineShaderStageCreateInfo	shaderParam		=
449 			{
450 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType			sType;
451 				DE_NULL,												//	const void*				pNext;
452 				(VkPipelineShaderStageCreateFlags)0,
453 				stage.second,											//	VkShaderStageFlagBits	stage;
454 				**modules.back(),										//	VkShaderModule			module;
455 				stage.first.c_str(),									//	const char*				pName;
456 				(const VkSpecializationInfo*)DE_NULL,
457 			};
458 			createInfos.push_back(shaderParam);
459 		}
460 	}
461 }
462 
463 // Creates vertex-shader assembly by specializing a boilerplate StringTemplate
464 // on fragments, which must (at least) map "testfun" to an OpFunction definition
465 // for %test_code that takes and returns a %v4f32.  Boilerplate IDs are prefixed
466 // with "BP_" to avoid collisions with fragments.
467 //
468 // It corresponds roughly to this GLSL:
469 //;
470 // layout(location = 0) in vec4 position;
471 // layout(location = 1) in vec4 color;
472 // layout(location = 1) out highp vec4 vtxColor;
473 // void main (void) { gl_Position = position; vtxColor = test_func(color); }
makeVertexShaderAssembly(const map<string,string> & fragments)474 string makeVertexShaderAssembly (const map<string, string>& fragments)
475 {
476 	static const char vertexShaderBoilerplate[] =
477 		"OpCapability Shader\n"
478 		"${capability:opt}\n"
479 		"${extension:opt}\n"
480 		"OpMemoryModel Logical GLSL450\n"
481 		"OpEntryPoint Vertex %BP_main \"main\" %BP_stream %BP_position %BP_vtx_color %BP_color %BP_gl_VertexIndex %BP_gl_InstanceIndex ${IF_entrypoint:opt} \n"
482 		"${execution_mode:opt}\n"
483 		"${debug:opt}\n"
484 		"${moduleprocessed:opt}\n"
485 		"OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n"
486 		"OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n"
487 		"OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n"
488 		"OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n"
489 		"OpDecorate %BP_gl_PerVertex Block\n"
490 		"OpDecorate %BP_position Location 0\n"
491 		"OpDecorate %BP_vtx_color Location 1\n"
492 		"OpDecorate %BP_color Location 1\n"
493 		"OpDecorate %BP_gl_VertexIndex BuiltIn VertexIndex\n"
494 		"OpDecorate %BP_gl_InstanceIndex BuiltIn InstanceIndex\n"
495 		"${IF_decoration:opt}\n"
496 		"${decoration:opt}\n"
497 		SPIRV_ASSEMBLY_TYPES
498 		SPIRV_ASSEMBLY_CONSTANTS
499 		SPIRV_ASSEMBLY_ARRAYS
500 		"%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
501 		"%BP_op_gl_PerVertex = OpTypePointer Output %BP_gl_PerVertex\n"
502 		"%BP_stream = OpVariable %BP_op_gl_PerVertex Output\n"
503 		"%BP_position = OpVariable %ip_v4f32 Input\n"
504 		"%BP_vtx_color = OpVariable %op_v4f32 Output\n"
505 		"%BP_color = OpVariable %ip_v4f32 Input\n"
506 		"%BP_gl_VertexIndex = OpVariable %ip_i32 Input\n"
507 		"%BP_gl_InstanceIndex = OpVariable %ip_i32 Input\n"
508 		"${pre_main:opt}\n"
509 		"${IF_variable:opt}\n"
510 		"%BP_main = OpFunction %void None %voidf\n"
511 		"%BP_label = OpLabel\n"
512 		"${IF_carryforward:opt}\n"
513 		"${post_interface_op_vert:opt}\n"
514 		"%BP_pos = OpLoad %v4f32 %BP_position\n"
515 		"%BP_gl_pos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
516 		"OpStore %BP_gl_pos %BP_pos\n"
517 		"%BP_col = OpLoad %v4f32 %BP_color\n"
518 		"%BP_col_transformed = OpFunctionCall %v4f32 %test_code %BP_col\n"
519 		"OpStore %BP_vtx_color %BP_col_transformed\n"
520 		"OpReturn\n"
521 		"OpFunctionEnd\n"
522 		"${interface_op_func:opt}\n"
523 
524 		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
525 		"%getId_label = OpLabel\n"
526 		"%vert_id = OpLoad %i32 %BP_gl_VertexIndex\n"
527 		"%is_id_0 = OpIEqual %bool %vert_id %c_i32_0\n"
528 		"OpReturnValue %is_id_0\n"
529 		"OpFunctionEnd\n"
530 
531 		"${testfun}\n";
532 	return tcu::StringTemplate(vertexShaderBoilerplate).specialize(fragments);
533 }
534 
535 // Creates tess-control-shader assembly by specializing a boilerplate
536 // StringTemplate on fragments, which must (at least) map "testfun" to an
537 // OpFunction definition for %test_code that takes and returns a %v4f32.
538 // Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments.
539 //
540 // It roughly corresponds to the following GLSL.
541 //
542 // #version 450
543 // layout(vertices = 3) out;
544 // layout(location = 1) in vec4 in_color[];
545 // layout(location = 1) out vec4 out_color[];
546 //
547 // void main() {
548 //   out_color[gl_InvocationID] = testfun(in_color[gl_InvocationID]);
549 //   gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
550 //   if (gl_InvocationID == 0) {
551 //     gl_TessLevelOuter[0] = 1.0;
552 //     gl_TessLevelOuter[1] = 1.0;
553 //     gl_TessLevelOuter[2] = 1.0;
554 //     gl_TessLevelInner[0] = 1.0;
555 //   }
556 // }
makeTessControlShaderAssembly(const map<string,string> & fragments)557 string makeTessControlShaderAssembly (const map<string, string>& fragments)
558 {
559 	static const char tessControlShaderBoilerplate[] =
560 		"OpCapability Tessellation\n"
561 		"${capability:opt}\n"
562 		"${extension:opt}\n"
563 		"OpMemoryModel Logical GLSL450\n"
564 		"OpEntryPoint TessellationControl %BP_main \"main\" %BP_out_color %BP_gl_InvocationID %BP_gl_PrimitiveID %BP_in_color %BP_gl_out %BP_gl_in %BP_gl_TessLevelOuter %BP_gl_TessLevelInner ${IF_entrypoint:opt} \n"
565 		"OpExecutionMode %BP_main OutputVertices 3\n"
566 		"${execution_mode:opt}\n"
567 		"${debug:opt}\n"
568 		"${moduleprocessed:opt}\n"
569 		"OpDecorate %BP_out_color Location 1\n"
570 		"OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n"
571 		"OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n"
572 		"OpDecorate %BP_in_color Location 1\n"
573 		"OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n"
574 		"OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n"
575 		"OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n"
576 		"OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n"
577 		"OpDecorate %BP_gl_PerVertex Block\n"
578 		"OpMemberDecorate %BP_gl_PVOut 0 BuiltIn Position\n"
579 		"OpMemberDecorate %BP_gl_PVOut 1 BuiltIn PointSize\n"
580 		"OpMemberDecorate %BP_gl_PVOut 2 BuiltIn ClipDistance\n"
581 		"OpMemberDecorate %BP_gl_PVOut 3 BuiltIn CullDistance\n"
582 		"OpDecorate %BP_gl_PVOut Block\n"
583 		"OpDecorate %BP_gl_TessLevelOuter Patch\n"
584 		"OpDecorate %BP_gl_TessLevelOuter BuiltIn TessLevelOuter\n"
585 		"OpDecorate %BP_gl_TessLevelInner Patch\n"
586 		"OpDecorate %BP_gl_TessLevelInner BuiltIn TessLevelInner\n"
587 		"${IF_decoration:opt}\n"
588 		"${decoration:opt}\n"
589 		"${decoration_tessc:opt}\n"
590 		SPIRV_ASSEMBLY_TYPES
591 		SPIRV_ASSEMBLY_CONSTANTS
592 		SPIRV_ASSEMBLY_ARRAYS
593 		"%BP_out_color = OpVariable %op_a3v4f32 Output\n"
594 		"%BP_gl_InvocationID = OpVariable %ip_i32 Input\n"
595 		"%BP_gl_PrimitiveID = OpVariable %ip_i32 Input\n"
596 		"%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
597 		"%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
598 		"%BP_a3_gl_PerVertex = OpTypeArray %BP_gl_PerVertex %c_u32_3\n"
599 		"%BP_op_a3_gl_PerVertex = OpTypePointer Output %BP_a3_gl_PerVertex\n"
600 		"%BP_gl_out = OpVariable %BP_op_a3_gl_PerVertex Output\n"
601 		"%BP_gl_PVOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
602 		"%BP_a32_gl_PVOut = OpTypeArray %BP_gl_PVOut %c_u32_32\n"
603 		"%BP_ip_a32_gl_PVOut = OpTypePointer Input %BP_a32_gl_PVOut\n"
604 		"%BP_gl_in = OpVariable %BP_ip_a32_gl_PVOut Input\n"
605 		"%BP_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
606 		"%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
607 		"${pre_main:opt}\n"
608 		"${IF_variable:opt}\n"
609 
610 		"%BP_main = OpFunction %void None %voidf\n"
611 		"%BP_label = OpLabel\n"
612 		"%BP_gl_Invoc = OpLoad %i32 %BP_gl_InvocationID\n"
613 		"${IF_carryforward:opt}\n"
614 		"${post_interface_op_tessc:opt}\n"
615 		"%BP_in_col_loc = OpAccessChain %ip_v4f32 %BP_in_color %BP_gl_Invoc\n"
616 		"%BP_out_col_loc = OpAccessChain %op_v4f32 %BP_out_color %BP_gl_Invoc\n"
617 		"%BP_in_col_val = OpLoad %v4f32 %BP_in_col_loc\n"
618 		"%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_col_val\n"
619 		"OpStore %BP_out_col_loc %BP_clr_transformed\n"
620 
621 		"%BP_in_pos_loc = OpAccessChain %ip_v4f32 %BP_gl_in %BP_gl_Invoc %c_i32_0\n"
622 		"%BP_out_pos_loc = OpAccessChain %op_v4f32 %BP_gl_out %BP_gl_Invoc %c_i32_0\n"
623 		"%BP_in_pos_val = OpLoad %v4f32 %BP_in_pos_loc\n"
624 		"OpStore %BP_out_pos_loc %BP_in_pos_val\n"
625 
626 		"%BP_cmp = OpIEqual %bool %BP_gl_Invoc %c_i32_0\n"
627 		"OpSelectionMerge %BP_merge_label None\n"
628 		"OpBranchConditional %BP_cmp %BP_if_label %BP_merge_label\n"
629 		"%BP_if_label = OpLabel\n"
630 		"%BP_gl_TessLevelOuterPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_0\n"
631 		"%BP_gl_TessLevelOuterPos_1 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_1\n"
632 		"%BP_gl_TessLevelOuterPos_2 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_2\n"
633 		"%BP_gl_TessLevelInnerPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelInner %c_i32_0\n"
634 		"OpStore %BP_gl_TessLevelOuterPos_0 %c_f32_1\n"
635 		"OpStore %BP_gl_TessLevelOuterPos_1 %c_f32_1\n"
636 		"OpStore %BP_gl_TessLevelOuterPos_2 %c_f32_1\n"
637 		"OpStore %BP_gl_TessLevelInnerPos_0 %c_f32_1\n"
638 		"OpBranch %BP_merge_label\n"
639 		"%BP_merge_label = OpLabel\n"
640 		"OpReturn\n"
641 		"OpFunctionEnd\n"
642 		"${interface_op_func:opt}\n"
643 
644 		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
645 		"%getId_label = OpLabel\n"
646 		"%invocation_id = OpLoad %i32 %BP_gl_InvocationID\n"
647 		"%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n"
648 		"%is_invocation_0 = OpIEqual %bool %invocation_id %c_i32_0\n"
649 		"%is_primitive_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
650 		"%is_id_0 = OpLogicalAnd %bool %is_invocation_0 %is_primitive_0\n"
651 		"OpReturnValue %is_id_0\n"
652 		"OpFunctionEnd\n"
653 
654 		"${testfun}\n";
655 	return tcu::StringTemplate(tessControlShaderBoilerplate).specialize(fragments);
656 }
657 
658 // Creates tess-evaluation-shader assembly by specializing a boilerplate
659 // StringTemplate on fragments, which must (at least) map "testfun" to an
660 // OpFunction definition for %test_code that takes and returns a %v4f32.
661 // Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments.
662 //
663 // It roughly corresponds to the following glsl.
664 //
665 // #version 450
666 //
667 // layout(triangles, equal_spacing, ccw) in;
668 // layout(location = 1) in vec4 in_color[];
669 // layout(location = 1) out vec4 out_color;
670 //
671 // #define interpolate(val)
672 //   vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] +
673 //          vec4(gl_TessCoord.z) * val[2]
674 //
675 // void main() {
676 //   gl_Position = vec4(gl_TessCoord.x) * gl_in[0].gl_Position +
677 //                  vec4(gl_TessCoord.y) * gl_in[1].gl_Position +
678 //                  vec4(gl_TessCoord.z) * gl_in[2].gl_Position;
679 //   out_color = testfun(interpolate(in_color));
680 // }
makeTessEvalShaderAssembly(const map<string,string> & fragments)681 string makeTessEvalShaderAssembly (const map<string, string>& fragments)
682 {
683 	static const char tessEvalBoilerplate[] =
684 		"OpCapability Tessellation\n"
685 		"${capability:opt}\n"
686 		"${extension:opt}\n"
687 		"OpMemoryModel Logical GLSL450\n"
688 		"OpEntryPoint TessellationEvaluation %BP_main \"main\" %BP_stream %BP_gl_TessCoord %BP_gl_PrimitiveID %BP_gl_in %BP_out_color %BP_in_color ${IF_entrypoint:opt} \n"
689 		"OpExecutionMode %BP_main Triangles\n"
690 		"OpExecutionMode %BP_main SpacingEqual\n"
691 		"OpExecutionMode %BP_main VertexOrderCcw\n"
692 		"${execution_mode:opt}\n"
693 		"${debug:opt}\n"
694 		"${moduleprocessed:opt}\n"
695 		"OpMemberDecorate %BP_gl_PerVertexOut 0 BuiltIn Position\n"
696 		"OpMemberDecorate %BP_gl_PerVertexOut 1 BuiltIn PointSize\n"
697 		"OpMemberDecorate %BP_gl_PerVertexOut 2 BuiltIn ClipDistance\n"
698 		"OpMemberDecorate %BP_gl_PerVertexOut 3 BuiltIn CullDistance\n"
699 		"OpDecorate %BP_gl_PerVertexOut Block\n"
700 		"OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n"
701 		"OpDecorate %BP_gl_TessCoord BuiltIn TessCoord\n"
702 		"OpMemberDecorate %BP_gl_PerVertexIn 0 BuiltIn Position\n"
703 		"OpMemberDecorate %BP_gl_PerVertexIn 1 BuiltIn PointSize\n"
704 		"OpMemberDecorate %BP_gl_PerVertexIn 2 BuiltIn ClipDistance\n"
705 		"OpMemberDecorate %BP_gl_PerVertexIn 3 BuiltIn CullDistance\n"
706 		"OpDecorate %BP_gl_PerVertexIn Block\n"
707 		"OpDecorate %BP_out_color Location 1\n"
708 		"OpDecorate %BP_in_color Location 1\n"
709 		"${IF_decoration:opt}\n"
710 		"${decoration:opt}\n"
711 		SPIRV_ASSEMBLY_TYPES
712 		SPIRV_ASSEMBLY_CONSTANTS
713 		SPIRV_ASSEMBLY_ARRAYS
714 		"%BP_gl_PerVertexOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
715 		"%BP_op_gl_PerVertexOut = OpTypePointer Output %BP_gl_PerVertexOut\n"
716 		"%BP_stream = OpVariable %BP_op_gl_PerVertexOut Output\n"
717 		"%BP_gl_TessCoord = OpVariable %ip_v3f32 Input\n"
718 		"%BP_gl_PrimitiveID = OpVariable %ip_i32 Input\n"
719 		"%BP_gl_PerVertexIn = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
720 		"%BP_a32_gl_PerVertexIn = OpTypeArray %BP_gl_PerVertexIn %c_u32_32\n"
721 		"%BP_ip_a32_gl_PerVertexIn = OpTypePointer Input %BP_a32_gl_PerVertexIn\n"
722 		"%BP_gl_in = OpVariable %BP_ip_a32_gl_PerVertexIn Input\n"
723 		"%BP_out_color = OpVariable %op_v4f32 Output\n"
724 		"%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
725 		"${pre_main:opt}\n"
726 		"${IF_variable:opt}\n"
727 		"%BP_main = OpFunction %void None %voidf\n"
728 		"%BP_label = OpLabel\n"
729 		"${IF_carryforward:opt}\n"
730 		"${post_interface_op_tesse:opt}\n"
731 		"%BP_gl_TC_0 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n"
732 		"%BP_gl_TC_1 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n"
733 		"%BP_gl_TC_2 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n"
734 		"%BP_gl_in_gl_Pos_0 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n"
735 		"%BP_gl_in_gl_Pos_1 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n"
736 		"%BP_gl_in_gl_Pos_2 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n"
737 
738 		"%BP_gl_OPos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
739 		"%BP_in_color_0 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
740 		"%BP_in_color_1 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
741 		"%BP_in_color_2 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
742 
743 		"%BP_TC_W_0 = OpLoad %f32 %BP_gl_TC_0\n"
744 		"%BP_TC_W_1 = OpLoad %f32 %BP_gl_TC_1\n"
745 		"%BP_TC_W_2 = OpLoad %f32 %BP_gl_TC_2\n"
746 		"%BP_v4f32_TC_0 = OpCompositeConstruct %v4f32 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0\n"
747 		"%BP_v4f32_TC_1 = OpCompositeConstruct %v4f32 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1\n"
748 		"%BP_v4f32_TC_2 = OpCompositeConstruct %v4f32 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2\n"
749 
750 		"%BP_gl_IP_0 = OpLoad %v4f32 %BP_gl_in_gl_Pos_0\n"
751 		"%BP_gl_IP_1 = OpLoad %v4f32 %BP_gl_in_gl_Pos_1\n"
752 		"%BP_gl_IP_2 = OpLoad %v4f32 %BP_gl_in_gl_Pos_2\n"
753 
754 		"%BP_IP_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_gl_IP_0\n"
755 		"%BP_IP_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_gl_IP_1\n"
756 		"%BP_IP_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_gl_IP_2\n"
757 
758 		"%BP_pos_sum_0 = OpFAdd %v4f32 %BP_IP_W_0 %BP_IP_W_1\n"
759 		"%BP_pos_sum_1 = OpFAdd %v4f32 %BP_pos_sum_0 %BP_IP_W_2\n"
760 
761 		"OpStore %BP_gl_OPos %BP_pos_sum_1\n"
762 
763 		"%BP_IC_0 = OpLoad %v4f32 %BP_in_color_0\n"
764 		"%BP_IC_1 = OpLoad %v4f32 %BP_in_color_1\n"
765 		"%BP_IC_2 = OpLoad %v4f32 %BP_in_color_2\n"
766 
767 		"%BP_IC_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_IC_0\n"
768 		"%BP_IC_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_IC_1\n"
769 		"%BP_IC_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_IC_2\n"
770 
771 		"%BP_col_sum_0 = OpFAdd %v4f32 %BP_IC_W_0 %BP_IC_W_1\n"
772 		"%BP_col_sum_1 = OpFAdd %v4f32 %BP_col_sum_0 %BP_IC_W_2\n"
773 
774 		"%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_col_sum_1\n"
775 
776 		"OpStore %BP_out_color %BP_clr_transformed\n"
777 		"OpReturn\n"
778 		"OpFunctionEnd\n"
779 		"${interface_op_func:opt}\n"
780 
781 		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
782 		"%getId_label = OpLabel\n"
783 		"%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n"
784 		"%is_primitive_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
785 		"%TC_0_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n"
786 		"%TC_1_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n"
787 		"%TC_2_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n"
788 		"%TC_W_0 = OpLoad %f32 %TC_0_loc\n"
789 		"%TC_W_1 = OpLoad %f32 %TC_1_loc\n"
790 		"%TC_W_2 = OpLoad %f32 %TC_2_loc\n"
791 		"%is_W_0_1 = OpFOrdEqual %bool %TC_W_0 %c_f32_1\n"
792 		"%is_W_1_0 = OpFOrdEqual %bool %TC_W_1 %c_f32_0\n"
793 		"%is_W_2_0 = OpFOrdEqual %bool %TC_W_2 %c_f32_0\n"
794 		"%is_tessCoord_1_0 = OpLogicalAnd %bool %is_W_0_1 %is_W_1_0\n"
795 		"%is_tessCoord_1_0_0 = OpLogicalAnd %bool %is_tessCoord_1_0 %is_W_2_0\n"
796 		"%is_unique_id_0 = OpLogicalAnd %bool %is_tessCoord_1_0_0 %is_primitive_0\n"
797 		"OpReturnValue %is_unique_id_0\n"
798 		"OpFunctionEnd\n"
799 
800 		"${testfun}\n";
801 	return tcu::StringTemplate(tessEvalBoilerplate).specialize(fragments);
802 }
803 
804 // Creates geometry-shader assembly by specializing a boilerplate StringTemplate
805 // on fragments, which must (at least) map "testfun" to an OpFunction definition
806 // for %test_code that takes and returns a %v4f32.  Boilerplate IDs are prefixed
807 // with "BP_" to avoid collisions with fragments.
808 //
809 // Derived from this GLSL:
810 //
811 // #version 450
812 // layout(triangles) in;
813 // layout(triangle_strip, max_vertices = 3) out;
814 //
815 // layout(location = 1) in vec4 in_color[];
816 // layout(location = 1) out vec4 out_color;
817 //
818 // void main() {
819 //   gl_Position = gl_in[0].gl_Position;
820 //   out_color = test_fun(in_color[0]);
821 //   EmitVertex();
822 //   gl_Position = gl_in[1].gl_Position;
823 //   out_color = test_fun(in_color[1]);
824 //   EmitVertex();
825 //   gl_Position = gl_in[2].gl_Position;
826 //   out_color = test_fun(in_color[2]);
827 //   EmitVertex();
828 //   EndPrimitive();
829 // }
makeGeometryShaderAssembly(const map<string,string> & fragments)830 string makeGeometryShaderAssembly (const map<string, string>& fragments)
831 {
832 	static const char geometryShaderBoilerplate[] =
833 		"OpCapability Geometry\n"
834 		"${capability:opt}\n"
835 		"${extension:opt}\n"
836 		"OpMemoryModel Logical GLSL450\n"
837 		"OpEntryPoint Geometry %BP_main \"main\" %BP_out_gl_position %BP_gl_PrimitiveID %BP_gl_in %BP_out_color %BP_in_color ${IF_entrypoint:opt} ${GL_entrypoint:opt} \n"
838 		"OpExecutionMode %BP_main Triangles\n"
839 		"OpExecutionMode %BP_main Invocations 1\n"
840 		"OpExecutionMode %BP_main OutputTriangleStrip\n"
841 		"OpExecutionMode %BP_main OutputVertices 3\n"
842 		"${execution_mode:opt}\n"
843 		"${debug:opt}\n"
844 		"${moduleprocessed:opt}\n"
845 		"OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n"
846 		"OpDecorate %BP_out_gl_position BuiltIn Position\n"
847 		"OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n"
848 		"OpMemberDecorate %BP_per_vertex_in 1 BuiltIn PointSize\n"
849 		"OpMemberDecorate %BP_per_vertex_in 2 BuiltIn ClipDistance\n"
850 		"OpMemberDecorate %BP_per_vertex_in 3 BuiltIn CullDistance\n"
851 		"OpDecorate %BP_per_vertex_in Block\n"
852 		"OpDecorate %BP_out_color Location 1\n"
853 		"OpDecorate %BP_in_color Location 1\n"
854 		"${IF_decoration:opt}\n"
855 		"${decoration:opt}\n"
856 		SPIRV_ASSEMBLY_TYPES
857 		SPIRV_ASSEMBLY_CONSTANTS
858 		SPIRV_ASSEMBLY_ARRAYS
859 		"%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
860 		"%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n"
861 		"%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n"
862 		"%BP_pp_i32 = OpTypePointer Private %i32\n"
863 		"%BP_pp_v4i32 = OpTypePointer Private %v4i32\n"
864 
865 		"%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n"
866 		"%BP_out_color = OpVariable %op_v4f32 Output\n"
867 		"%BP_in_color = OpVariable %ip_a3v4f32 Input\n"
868 		"%BP_gl_PrimitiveID = OpVariable %ip_i32 Input\n"
869 		"%BP_out_gl_position = OpVariable %op_v4f32 Output\n"
870 		"%BP_vertexIdInCurrentPatch = OpVariable %BP_pp_v4i32 Private\n"
871 		"${pre_main:opt}\n"
872 		"${IF_variable:opt}\n"
873 
874 		"%BP_main = OpFunction %void None %voidf\n"
875 		"%BP_label = OpLabel\n"
876 
877 		"${IF_carryforward:opt}\n"
878 		"${post_interface_op_geom:opt}\n"
879 
880 		"%BP_primitiveId = OpLoad %i32 %BP_gl_PrimitiveID\n"
881 		"%BP_addr_vertexIdInCurrentPatch = OpAccessChain %BP_pp_i32 %BP_vertexIdInCurrentPatch %BP_primitiveId\n"
882 
883 		"%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n"
884 		"%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n"
885 		"%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n"
886 
887 		"%BP_in_position_0 = OpLoad %v4f32 %BP_gl_in_0_gl_position\n"
888 		"%BP_in_position_1 = OpLoad %v4f32 %BP_gl_in_1_gl_position\n"
889 		"%BP_in_position_2 = OpLoad %v4f32 %BP_gl_in_2_gl_position \n"
890 
891 		"%BP_in_color_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
892 		"%BP_in_color_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
893 		"%BP_in_color_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
894 
895 		"%BP_in_color_0 = OpLoad %v4f32 %BP_in_color_0_ptr\n"
896 		"%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n"
897 		"%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n"
898 
899 		"OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_0\n"
900 		"%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n"
901 		"OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_1\n"
902 		"%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n"
903 		"OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_2\n"
904 		"%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n"
905 
906 
907 		"OpStore %BP_out_gl_position %BP_in_position_0\n"
908 		"OpStore %BP_out_color %BP_transformed_in_color_0\n"
909 		"OpEmitVertex\n"
910 
911 		"OpStore %BP_out_gl_position %BP_in_position_1\n"
912 		"OpStore %BP_out_color %BP_transformed_in_color_1\n"
913 		"OpEmitVertex\n"
914 
915 		"OpStore %BP_out_gl_position %BP_in_position_2\n"
916 		"OpStore %BP_out_color %BP_transformed_in_color_2\n"
917 		"OpEmitVertex\n"
918 
919 		"OpEndPrimitive\n"
920 		"OpReturn\n"
921 		"OpFunctionEnd\n"
922 		"${interface_op_func:opt}\n"
923 
924 		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
925 		"%getId_label = OpLabel\n"
926 		"%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n"
927 		"%addr_vertexIdInCurrentPatch = OpAccessChain %BP_pp_i32 %BP_vertexIdInCurrentPatch %primitive_id\n"
928 		"%vertexIdInCurrentPatch = OpLoad %i32 %addr_vertexIdInCurrentPatch\n"
929 		"%is_primitive_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
930 		"%is_vertex_0 = OpIEqual %bool %vertexIdInCurrentPatch %c_i32_0\n"
931 		"%is_unique_id_0 = OpLogicalAnd %bool %is_primitive_0 %is_vertex_0\n"
932 		"OpReturnValue %is_unique_id_0\n"
933 		"OpFunctionEnd\n"
934 
935 		"${testfun}\n";
936 	return tcu::StringTemplate(geometryShaderBoilerplate).specialize(fragments);
937 }
938 
939 // Creates fragment-shader assembly by specializing a boilerplate StringTemplate
940 // on fragments, which must (at least) map "testfun" to an OpFunction definition
941 // for %test_code that takes and returns a %v4f32.  Boilerplate IDs are prefixed
942 // with "BP_" to avoid collisions with fragments.
943 //
944 // Derived from this GLSL:
945 //
946 // layout(location = 1) in highp vec4 vtxColor;
947 // layout(location = 0) out highp vec4 fragColor;
948 // highp vec4 testfun(highp vec4 x) { return x; }
949 // void main(void) { fragColor = testfun(vtxColor); }
950 //
951 // with modifications including passing vtxColor by value and ripping out
952 // testfun() definition.
makeFragmentShaderAssembly(const map<string,string> & fragments)953 string makeFragmentShaderAssembly (const map<string, string>& fragments)
954 {
955 	static const char fragmentShaderBoilerplate[] =
956 		"OpCapability Shader\n"
957 		"${capability:opt}\n"
958 		"${extension:opt}\n"
959 		"OpMemoryModel Logical GLSL450\n"
960 		"OpEntryPoint Fragment %BP_main \"main\" %BP_vtxColor %BP_fragColor %BP_gl_FragCoord ${IF_entrypoint:opt} \n"
961 		"OpExecutionMode %BP_main OriginUpperLeft\n"
962 		"${execution_mode:opt}\n"
963 		"${debug:opt}\n"
964 		"${moduleprocessed:opt}\n"
965 		"OpDecorate %BP_fragColor Location 0\n"
966 		"OpDecorate %BP_vtxColor Location 1\n"
967 		"OpDecorate %BP_gl_FragCoord BuiltIn FragCoord\n"
968 		"${IF_decoration:opt}\n"
969 		"${decoration:opt}\n"
970 		SPIRV_ASSEMBLY_TYPES
971 		SPIRV_ASSEMBLY_CONSTANTS
972 		SPIRV_ASSEMBLY_ARRAYS
973 		"%BP_gl_FragCoord = OpVariable %ip_v4f32 Input\n"
974 		"%BP_fragColor = OpVariable %op_v4f32 Output\n"
975 		"%BP_vtxColor = OpVariable %ip_v4f32 Input\n"
976 		"${pre_main:opt}\n"
977 		"${IF_variable:opt}\n"
978 		"%BP_main = OpFunction %void None %voidf\n"
979 		"%BP_label_main = OpLabel\n"
980 		"${IF_carryforward:opt}\n"
981 		"${post_interface_op_frag:opt}\n"
982 		"%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n"
983 		"%BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1\n"
984 		"OpStore %BP_fragColor %BP_tmp2\n"
985 		"OpReturn\n"
986 		"OpFunctionEnd\n"
987 		"${interface_op_func:opt}\n"
988 
989 		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
990 		"%getId_label = OpLabel\n"
991 		"%loc_x_coord = OpAccessChain %ip_f32 %BP_gl_FragCoord %c_i32_0\n"
992 		"%loc_y_coord = OpAccessChain %ip_f32 %BP_gl_FragCoord %c_i32_1\n"
993 		"%x_coord = OpLoad %f32 %loc_x_coord\n"
994 		"%y_coord = OpLoad %f32 %loc_y_coord\n"
995 		"%is_x_idx0 = OpFOrdEqual %bool %x_coord %c_f32_0_5\n"
996 		"%is_y_idx0 = OpFOrdEqual %bool %y_coord %c_f32_0_5\n"
997 		"%is_frag_0 = OpLogicalAnd %bool %is_x_idx0 %is_y_idx0\n"
998 		"OpReturnValue %is_frag_0\n"
999 		"OpFunctionEnd\n"
1000 
1001 		"${testfun}\n";
1002 	return tcu::StringTemplate(fragmentShaderBoilerplate).specialize(fragments);
1003 }
1004 
1005 // Creates mappings from placeholders to pass-through shader code which copies
1006 // the input to the output faithfully.
passthruInterface(const IFDataType & data_type)1007 map<string, string> passthruInterface (const IFDataType& data_type)
1008 {
1009 	const string		var_type	= data_type.str();
1010 	map<string, string>	fragments	= passthruFragments();
1011 	const string		functype	= string("%") + var_type + "_" + var_type + "_function";
1012 
1013 	fragments["interface_op_call"]  = "OpCopyObject %" + var_type;
1014 	fragments["interface_op_func"]	= "";
1015 	fragments["input_type"]			= var_type;
1016 	fragments["output_type"]		= var_type;
1017 	fragments["pre_main"]			= "";
1018 
1019 	if (!data_type.elementIs32bit())
1020 	{
1021 		if (data_type.elementType == NUMBERTYPE_FLOAT64)
1022 		{
1023 			fragments["capability"]		= "OpCapability Float64\n\n";
1024 			fragments["pre_main"]	+= "%f64 = OpTypeFloat 64\n";
1025 		}
1026 		else if (data_type.elementType == NUMBERTYPE_FLOAT16)
1027 		{
1028 			fragments["capability"]		= "OpCapability StorageInputOutput16\n";
1029 			fragments["extension"]		= "OpExtension \"SPV_KHR_16bit_storage\"\n";
1030 			fragments["pre_main"]	+= "%f16 = OpTypeFloat 16\n";
1031 		}
1032 		else if (data_type.elementType == NUMBERTYPE_INT16)
1033 		{
1034 			fragments["capability"]		= "OpCapability StorageInputOutput16\n";
1035 			fragments["extension"]		= "OpExtension \"SPV_KHR_16bit_storage\"\n";
1036 			fragments["pre_main"]	+= "%i16 = OpTypeInt 16 1\n";
1037 		}
1038 		else if (data_type.elementType == NUMBERTYPE_UINT16)
1039 		{
1040 			fragments["capability"]		= "OpCapability StorageInputOutput16\n";
1041 			fragments["extension"]		= "OpExtension \"SPV_KHR_16bit_storage\"\n";
1042 			fragments["pre_main"]	+= "%u16 = OpTypeInt 16 0\n";
1043 		}
1044 		else
1045 		{
1046 			DE_ASSERT(0 && "unhandled type");
1047 		}
1048 
1049 		if (data_type.isVector())
1050 		{
1051 			fragments["pre_main"]	+= "%" + var_type + " = OpTypeVector %" + IFDataType(1, data_type.elementType).str() + " " + numberToString(data_type.numElements) + "\n";
1052 		}
1053 
1054 		fragments["pre_main"]		+=
1055 			"%ip_" + var_type + " = OpTypePointer Input %" + var_type + "\n"
1056 			"%op_" + var_type + " = OpTypePointer Output %" + var_type + "\n";
1057 	}
1058 
1059 	if (strcmp(var_type.c_str(), "v4f32") != 0)
1060 		fragments["pre_main"]		+=
1061 			functype + " = OpTypeFunction %" + var_type + " %" + var_type + "\n"
1062 			"%a3" + var_type + " = OpTypeArray %" + var_type + " %c_i32_3\n"
1063 			"%ip_a3" + var_type + " = OpTypePointer Input %a3" + var_type + "\n"
1064 			"%op_a3" + var_type + " = OpTypePointer Output %a3" + var_type + "\n";
1065 
1066 	return fragments;
1067 }
1068 
1069 // Returns mappings from interface placeholders to their concrete values.
1070 //
1071 // The concrete values should be specialized again to provide ${input_type}
1072 // and ${output_type}.
1073 //
1074 // %ip_${input_type} and %op_${output_type} should also be defined in the final code.
fillInterfacePlaceholderVert(void)1075 map<string, string> fillInterfacePlaceholderVert (void)
1076 {
1077 	map<string, string>	fragments;
1078 
1079 	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
1080 	fragments["IF_variable"]		=
1081 		" %IF_input = OpVariable %ip_${input_type} Input\n"
1082 		"%IF_output = OpVariable %op_${output_type} Output\n";
1083 	fragments["IF_decoration"]		=
1084 		"OpDecorate  %IF_input Location 2\n"
1085 		"OpDecorate %IF_output Location 2\n";
1086 	fragments["IF_carryforward"]	=
1087 		"%IF_input_val = OpLoad %${input_type} %IF_input\n"
1088 		"   %IF_result = ${interface_op_call} %IF_input_val\n"
1089 		"                OpStore %IF_output %IF_result\n";
1090 
1091 	// Make sure the rest still need to be instantialized.
1092 	fragments["capability"]				= "${capability:opt}";
1093 	fragments["extension"]				= "${extension:opt}";
1094 	fragments["execution_mode"]			= "${execution_mode:opt}";
1095 	fragments["debug"]					= "${debug:opt}";
1096 	fragments["decoration"]				= "${decoration:opt}";
1097 	fragments["pre_main"]				= "${pre_main:opt}";
1098 	fragments["testfun"]				= "${testfun}";
1099 	fragments["interface_op_call"]    = "${interface_op_call}";
1100 	fragments["interface_op_func"]		= "${interface_op_func}";
1101 	fragments["post_interface_op_vert"]	= "${post_interface_op_vert:opt}";
1102 
1103 	return fragments;
1104 }
1105 
1106 // Returns mappings from interface placeholders to their concrete values.
1107 //
1108 // The concrete values should be specialized again to provide ${input_type}
1109 // and ${output_type}.
1110 //
1111 // %ip_${input_type} and %op_${output_type} should also be defined in the final code.
fillInterfacePlaceholderFrag(void)1112 map<string, string> fillInterfacePlaceholderFrag (void)
1113 {
1114 	map<string, string>	fragments;
1115 
1116 	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
1117 	fragments["IF_variable"]		=
1118 		" %IF_input = OpVariable %ip_${input_type} Input\n"
1119 		"%IF_output = OpVariable %op_${output_type} Output\n";
1120 	fragments["IF_decoration"]		=
1121 		"OpDecorate %IF_input Flat\n"
1122 		"OpDecorate %IF_input Location 2\n"
1123 		"OpDecorate %IF_output Location 1\n";  // Fragment shader should write to location #1.
1124 	fragments["IF_carryforward"]	=
1125 		"%IF_input_val = OpLoad %${input_type} %IF_input\n"
1126 		"   %IF_result = ${interface_op_call} %IF_input_val\n"
1127 		"                OpStore %IF_output %IF_result\n";
1128 
1129 	// Make sure the rest still need to be instantialized.
1130 	fragments["capability"]				= "${capability:opt}";
1131 	fragments["extension"]				= "${extension:opt}";
1132 	fragments["execution_mode"]			= "${execution_mode:opt}";
1133 	fragments["debug"]					= "${debug:opt}";
1134 	fragments["decoration"]				= "${decoration:opt}";
1135 	fragments["pre_main"]				= "${pre_main:opt}";
1136 	fragments["testfun"]				= "${testfun}";
1137 	fragments["interface_op_call"]		= "${interface_op_call}";
1138 	fragments["interface_op_func"]		= "${interface_op_func}";
1139 	fragments["post_interface_op_frag"]	= "${post_interface_op_frag:opt}";
1140 
1141 	return fragments;
1142 }
1143 
1144 // Returns mappings from interface placeholders to their concrete values.
1145 //
1146 // The concrete values should be specialized again to provide ${input_type}
1147 // and ${output_type}.
1148 //
1149 // %ip_${input_type}, %op_${output_type}, %ip_a3${input_type}, and $op_a3${output_type}
1150 // should also be defined in the final code.
fillInterfacePlaceholderTessCtrl(void)1151 map<string, string> fillInterfacePlaceholderTessCtrl (void)
1152 {
1153 	map<string, string>	fragments;
1154 
1155 	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
1156 	fragments["IF_variable"]		=
1157 		" %IF_input = OpVariable %ip_a3${input_type} Input\n"
1158 		"%IF_output = OpVariable %op_a3${output_type} Output\n";
1159 	fragments["IF_decoration"]		=
1160 		"OpDecorate  %IF_input Location 2\n"
1161 		"OpDecorate %IF_output Location 2\n";
1162 	fragments["IF_carryforward"]	=
1163 		" %IF_input_ptr0 = OpAccessChain %ip_${input_type} %IF_input %c_i32_0\n"
1164 		" %IF_input_ptr1 = OpAccessChain %ip_${input_type} %IF_input %c_i32_1\n"
1165 		" %IF_input_ptr2 = OpAccessChain %ip_${input_type} %IF_input %c_i32_2\n"
1166 		"%IF_output_ptr0 = OpAccessChain %op_${output_type} %IF_output %c_i32_0\n"
1167 		"%IF_output_ptr1 = OpAccessChain %op_${output_type} %IF_output %c_i32_1\n"
1168 		"%IF_output_ptr2 = OpAccessChain %op_${output_type} %IF_output %c_i32_2\n"
1169 		"%IF_input_val0 = OpLoad %${input_type} %IF_input_ptr0\n"
1170 		"%IF_input_val1 = OpLoad %${input_type} %IF_input_ptr1\n"
1171 		"%IF_input_val2 = OpLoad %${input_type} %IF_input_ptr2\n"
1172 		"%IF_input_res0 = ${interface_op_call} %IF_input_val0\n"
1173 		"%IF_input_res1 = ${interface_op_call} %IF_input_val1\n"
1174 		"%IF_input_res2 = ${interface_op_call} %IF_input_val2\n"
1175 		"OpStore %IF_output_ptr0 %IF_input_res0\n"
1176 		"OpStore %IF_output_ptr1 %IF_input_res1\n"
1177 		"OpStore %IF_output_ptr2 %IF_input_res2\n";
1178 
1179 	// Make sure the rest still need to be instantialized.
1180 	fragments["capability"]					= "${capability:opt}";
1181 	fragments["extension"]					= "${extension:opt}";
1182 	fragments["execution_mode"]				= "${execution_mode:opt}";
1183 	fragments["debug"]						= "${debug:opt}";
1184 	fragments["decoration"]					= "${decoration:opt}";
1185 	fragments["decoration_tessc"]			= "${decoration_tessc:opt}";
1186 	fragments["pre_main"]					= "${pre_main:opt}";
1187 	fragments["testfun"]					= "${testfun}";
1188 	fragments["interface_op_call"]			= "${interface_op_call}";
1189 	fragments["interface_op_func"]			= "${interface_op_func}";
1190 	fragments["post_interface_op_tessc"]	= "${post_interface_op_tessc:opt}";
1191 
1192 	return fragments;
1193 }
1194 
1195 // Returns mappings from interface placeholders to their concrete values.
1196 //
1197 // The concrete values should be specialized again to provide ${input_type}
1198 // and ${output_type}.
1199 //
1200 // %ip_${input_type}, %op_${output_type}, %ip_a3${input_type}, and $op_a3${output_type}
1201 // should also be defined in the final code.
fillInterfacePlaceholderTessEvalGeom(void)1202 map<string, string> fillInterfacePlaceholderTessEvalGeom (void)
1203 {
1204 	map<string, string>	fragments;
1205 
1206 	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
1207 	fragments["IF_variable"]		=
1208 		" %IF_input = OpVariable %ip_a3${input_type} Input\n"
1209 		"%IF_output = OpVariable %op_${output_type} Output\n";
1210 	fragments["IF_decoration"]		=
1211 		"OpDecorate  %IF_input Location 2\n"
1212 		"OpDecorate %IF_output Location 2\n";
1213 	fragments["IF_carryforward"]	=
1214 		// Only get the first value since all three values are the same anyway.
1215 		" %IF_input_ptr0 = OpAccessChain %ip_${input_type} %IF_input %c_i32_0\n"
1216 		" %IF_input_val0 = OpLoad %${input_type} %IF_input_ptr0\n"
1217 		" %IF_input_res0 = ${interface_op_call} %IF_input_val0\n"
1218 		"OpStore %IF_output %IF_input_res0\n";
1219 
1220 	// Make sure the rest still need to be instantialized.
1221 	fragments["capability"]					= "${capability:opt}";
1222 	fragments["extension"]					= "${extension:opt}";
1223 	fragments["execution_mode"]				= "${execution_mode:opt}";
1224 	fragments["debug"]						= "${debug:opt}";
1225 	fragments["decoration"]					= "${decoration:opt}";
1226 	fragments["pre_main"]					= "${pre_main:opt}";
1227 	fragments["testfun"]					= "${testfun}";
1228 	fragments["interface_op_call"]			= "${interface_op_call}";
1229 	fragments["interface_op_func"]			= "${interface_op_func}";
1230 	fragments["post_interface_op_tesse"]	= "${post_interface_op_tesse:opt}";
1231 	fragments["post_interface_op_geom"]		= "${post_interface_op_geom:opt}";
1232 
1233 	return fragments;
1234 }
1235 
passthruFragments(void)1236 map<string, string> passthruFragments (void)
1237 {
1238 	map<string, string> fragments;
1239 	fragments["testfun"] =
1240 		// A %test_code function that returns its argument unchanged.
1241 		"%test_code = OpFunction %v4f32 None %v4f32_v4f32_function\n"
1242 		"%param1 = OpFunctionParameter %v4f32\n"
1243 		"%label_testfun = OpLabel\n"
1244 		"OpReturnValue %param1\n"
1245 		"OpFunctionEnd\n";
1246 	return fragments;
1247 }
1248 
1249 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
1250 // Vertex shader gets custom code from context, the rest are pass-through.
addShaderCodeCustomVertex(vk::SourceCollections & dst,InstanceContext & context,const SpirVAsmBuildOptions * spirVAsmBuildOptions)1251 void addShaderCodeCustomVertex (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
1252 {
1253 	const deUint32 vulkanVersion = dst.usedVulkanVersion;
1254 	SpirvVersion targetSpirvVersion;
1255 
1256 	if (spirVAsmBuildOptions == DE_NULL)
1257 		targetSpirvVersion = context.resources.spirvVersion;
1258 	else
1259 		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
1260 
1261 	if (!context.interfaces.empty())
1262 	{
1263 		// Inject boilerplate code to wire up additional input/output variables between stages.
1264 		// Just copy the contents in input variable to output variable in all stages except
1265 		// the customized stage.
1266 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1267 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1268 	} else {
1269 		map<string, string> passthru = passthruFragments();
1270 
1271 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1272 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1273 	}
1274 }
1275 
addShaderCodeCustomVertex(vk::SourceCollections & dst,InstanceContext context)1276 void addShaderCodeCustomVertex (vk::SourceCollections& dst, InstanceContext context)
1277 {
1278 	addShaderCodeCustomVertex(dst, context, DE_NULL);
1279 }
1280 
1281 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
1282 // Tessellation control shader gets custom code from context, the rest are
1283 // pass-through.
addShaderCodeCustomTessControl(vk::SourceCollections & dst,InstanceContext & context,const SpirVAsmBuildOptions * spirVAsmBuildOptions)1284 void addShaderCodeCustomTessControl (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
1285 {
1286 	const deUint32 vulkanVersion = dst.usedVulkanVersion;
1287 	SpirvVersion targetSpirvVersion;
1288 
1289 	if (spirVAsmBuildOptions == DE_NULL)
1290 		targetSpirvVersion = context.resources.spirvVersion;
1291 	else
1292 		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
1293 
1294 	if (!context.interfaces.empty())
1295 	{
1296 		// Inject boilerplate code to wire up additional input/output variables between stages.
1297 		// Just copy the contents in input variable to output variable in all stages except
1298 		// the customized stage.
1299 		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1300 		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1301 		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1302 		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1303 	}
1304 	else
1305 	{
1306 		map<string, string> passthru = passthruFragments();
1307 
1308 		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1309 		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << makeTessControlShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1310 		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << makeTessEvalShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1311 		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1312 	}
1313 }
1314 
addShaderCodeCustomTessControl(vk::SourceCollections & dst,InstanceContext context)1315 void addShaderCodeCustomTessControl (vk::SourceCollections& dst, InstanceContext context)
1316 {
1317 	addShaderCodeCustomTessControl(dst, context, DE_NULL);
1318 }
1319 
1320 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
1321 // Tessellation evaluation shader gets custom code from context, the rest are
1322 // pass-through.
addShaderCodeCustomTessEval(vk::SourceCollections & dst,InstanceContext & context,const SpirVAsmBuildOptions * spirVAsmBuildOptions)1323 void addShaderCodeCustomTessEval (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
1324 {
1325 	const deUint32 vulkanVersion = dst.usedVulkanVersion;
1326 	SpirvVersion targetSpirvVersion;
1327 
1328 	if (spirVAsmBuildOptions == DE_NULL)
1329 		targetSpirvVersion = context.resources.spirvVersion;
1330 	else
1331 		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
1332 
1333 	if (!context.interfaces.empty())
1334 	{
1335 		// Inject boilerplate code to wire up additional input/output variables between stages.
1336 		// Just copy the contents in input variable to output variable in all stages except
1337 		// the customized stage.
1338 		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1339 		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1340 		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1341 		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1342 	}
1343 	else
1344 	{
1345 		map<string, string> passthru = passthruFragments();
1346 		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1347 		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << makeTessControlShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1348 		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << makeTessEvalShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1349 		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1350 	}
1351 }
1352 
addShaderCodeCustomTessEval(vk::SourceCollections & dst,InstanceContext context)1353 void addShaderCodeCustomTessEval (vk::SourceCollections& dst, InstanceContext context)
1354 {
1355 	addShaderCodeCustomTessEval(dst, context, DE_NULL);
1356 }
1357 
1358 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
1359 // Geometry shader gets custom code from context, the rest are pass-through.
addShaderCodeCustomGeometry(vk::SourceCollections & dst,InstanceContext & context,const SpirVAsmBuildOptions * spirVAsmBuildOptions)1360 void addShaderCodeCustomGeometry (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
1361 {
1362 	const deUint32 vulkanVersion = dst.usedVulkanVersion;
1363 	SpirvVersion targetSpirvVersion;
1364 
1365 	if (spirVAsmBuildOptions == DE_NULL)
1366 		targetSpirvVersion = context.resources.spirvVersion;
1367 	else
1368 		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
1369 
1370 	if (!context.interfaces.empty())
1371 	{
1372 		// Inject boilerplate code to wire up additional input/output variables between stages.
1373 		// Just copy the contents in input variable to output variable in all stages except
1374 		// the customized stage.
1375 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1376 		dst.spirvAsmSources.add("geom", spirVAsmBuildOptions) << StringTemplate(makeGeometryShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1377 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1378 	}
1379 	else
1380 	{
1381 		map<string, string> passthru = passthruFragments();
1382 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1383 		dst.spirvAsmSources.add("geom", spirVAsmBuildOptions) << makeGeometryShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1384 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1385 	}
1386 }
1387 
addShaderCodeCustomGeometry(vk::SourceCollections & dst,InstanceContext context)1388 void addShaderCodeCustomGeometry (vk::SourceCollections& dst, InstanceContext context)
1389 {
1390 	addShaderCodeCustomGeometry(dst, context, DE_NULL);
1391 }
1392 
1393 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
1394 // Fragment shader gets custom code from context, the rest are pass-through.
addShaderCodeCustomFragment(vk::SourceCollections & dst,InstanceContext & context,const SpirVAsmBuildOptions * spirVAsmBuildOptions)1395 void addShaderCodeCustomFragment (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
1396 {
1397 	const deUint32 vulkanVersion = dst.usedVulkanVersion;
1398 	SpirvVersion targetSpirvVersion;
1399 
1400 	if (spirVAsmBuildOptions == DE_NULL)
1401 		targetSpirvVersion = context.resources.spirvVersion;
1402 	else
1403 		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
1404 
1405 	if (!context.interfaces.empty())
1406 	{
1407 		// Inject boilerplate code to wire up additional input/output variables between stages.
1408 		// Just copy the contents in input variable to output variable in all stages except
1409 		// the customized stage.
1410 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1411 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1412 	}
1413 	else
1414 	{
1415 		map<string, string> passthru = passthruFragments();
1416 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1417 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(vulkanVersion, targetSpirvVersion);
1418 	}
1419 }
1420 
addShaderCodeCustomFragment(vk::SourceCollections & dst,InstanceContext context)1421 void addShaderCodeCustomFragment (vk::SourceCollections& dst, InstanceContext context)
1422 {
1423 	addShaderCodeCustomFragment(dst, context, DE_NULL);
1424 }
1425 
createCombinedModule(vk::SourceCollections & dst,InstanceContext ctx)1426 void createCombinedModule (vk::SourceCollections& dst, InstanceContext ctx)
1427 {
1428 	const bool			useTessellation	(ctx.requiredStages & (VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
1429 	const bool			useGeometry		(ctx.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT);
1430 	std::stringstream	combinedModule;
1431 	std::stringstream	opCapabilities;
1432 	std::stringstream	opEntryPoints;
1433 
1434 	// opCapabilities
1435 	{
1436 		opCapabilities << "OpCapability Shader\n";
1437 
1438 		if (useGeometry)
1439 			opCapabilities << "OpCapability Geometry\n";
1440 
1441 		if (useTessellation)
1442 			opCapabilities << "OpCapability Tessellation\n";
1443 	}
1444 
1445 	// opEntryPoints
1446 	{
1447 		if (useTessellation)
1448 			opEntryPoints << "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_vtxPosition %vert_vertex_id %vert_instance_id\n";
1449 		else
1450 			opEntryPoints << "OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_glPerVertex %vert_vertex_id %vert_instance_id\n";
1451 
1452 		if (useGeometry)
1453 			opEntryPoints << "OpEntryPoint Geometry %geom_main \"main\" %geom_out_gl_position %geom_gl_in %geom_out_color %geom_in_color\n";
1454 
1455 		if (useTessellation)
1456 		{
1457 			opEntryPoints <<	"OpEntryPoint TessellationControl %tessc_main \"main\" %tessc_out_color %tessc_gl_InvocationID %tessc_in_color %tessc_out_position %tessc_in_position %tessc_gl_TessLevelOuter %tessc_gl_TessLevelInner\n"
1458 								"OpEntryPoint TessellationEvaluation %tesse_main \"main\" %tesse_stream %tesse_gl_tessCoord %tesse_in_position %tesse_out_color %tesse_in_color \n";
1459 		}
1460 
1461 		opEntryPoints << "OpEntryPoint Fragment %frag_main \"main\" %frag_vtxColor %frag_fragColor\n";
1462 	}
1463 
1464 	combinedModule	<<	opCapabilities.str()
1465 					<<	"OpMemoryModel Logical GLSL450\n"
1466 					<<	opEntryPoints.str();
1467 
1468 	if (useGeometry)
1469 	{
1470 		combinedModule <<	"OpExecutionMode %geom_main Triangles\n"
1471 							"OpExecutionMode %geom_main Invocations 1\n"
1472 							"OpExecutionMode %geom_main OutputTriangleStrip\n"
1473 							"OpExecutionMode %geom_main OutputVertices 3\n";
1474 	}
1475 
1476 	if (useTessellation)
1477 	{
1478 		combinedModule <<	"OpExecutionMode %tessc_main OutputVertices 3\n"
1479 							"OpExecutionMode %tesse_main Triangles\n"
1480 							"OpExecutionMode %tesse_main SpacingEqual\n"
1481 							"OpExecutionMode %tesse_main VertexOrderCcw\n";
1482 	}
1483 
1484 	combinedModule <<	"OpExecutionMode %frag_main OriginUpperLeft\n"
1485 
1486 						"; Vertex decorations\n"
1487 						"OpDecorate %vert_Position Location 0\n"
1488 						"OpDecorate %vert_vtxColor Location 1\n"
1489 						"OpDecorate %vert_color Location 1\n"
1490 						"OpDecorate %vert_vertex_id BuiltIn VertexIndex\n"
1491 						"OpDecorate %vert_instance_id BuiltIn InstanceIndex\n";
1492 
1493 	// If tessellation is used, vertex position is written by tessellation stage.
1494 	// Otherwise it will be written by vertex stage.
1495 	if (useTessellation)
1496 		combinedModule <<	"OpDecorate %vert_vtxPosition Location 2\n";
1497 	else
1498 	{
1499 		combinedModule <<	"OpMemberDecorate %vert_per_vertex_out 0 BuiltIn Position\n"
1500 							"OpMemberDecorate %vert_per_vertex_out 1 BuiltIn PointSize\n"
1501 							"OpMemberDecorate %vert_per_vertex_out 2 BuiltIn ClipDistance\n"
1502 							"OpMemberDecorate %vert_per_vertex_out 3 BuiltIn CullDistance\n"
1503 							"OpDecorate %vert_per_vertex_out Block\n";
1504 	}
1505 
1506 	if (useGeometry)
1507 	{
1508 		combinedModule <<	"; Geometry decorations\n"
1509 							"OpDecorate %geom_out_gl_position BuiltIn Position\n"
1510 							"OpMemberDecorate %geom_per_vertex_in 0 BuiltIn Position\n"
1511 							"OpMemberDecorate %geom_per_vertex_in 1 BuiltIn PointSize\n"
1512 							"OpMemberDecorate %geom_per_vertex_in 2 BuiltIn ClipDistance\n"
1513 							"OpMemberDecorate %geom_per_vertex_in 3 BuiltIn CullDistance\n"
1514 							"OpDecorate %geom_per_vertex_in Block\n"
1515 							"OpDecorate %geom_out_color Location 1\n"
1516 							"OpDecorate %geom_in_color Location 1\n";
1517 	}
1518 
1519 	if (useTessellation)
1520 	{
1521 		combinedModule <<	"; Tessellation Control decorations\n"
1522 							"OpDecorate %tessc_out_color Location 1\n"
1523 							"OpDecorate %tessc_gl_InvocationID BuiltIn InvocationId\n"
1524 							"OpDecorate %tessc_in_color Location 1\n"
1525 							"OpDecorate %tessc_out_position Location 2\n"
1526 							"OpDecorate %tessc_in_position Location 2\n"
1527 							"OpDecorate %tessc_gl_TessLevelOuter Patch\n"
1528 							"OpDecorate %tessc_gl_TessLevelOuter BuiltIn TessLevelOuter\n"
1529 							"OpDecorate %tessc_gl_TessLevelInner Patch\n"
1530 							"OpDecorate %tessc_gl_TessLevelInner BuiltIn TessLevelInner\n"
1531 
1532 							"; Tessellation Evaluation decorations\n"
1533 							"OpMemberDecorate %tesse_per_vertex_out 0 BuiltIn Position\n"
1534 							"OpMemberDecorate %tesse_per_vertex_out 1 BuiltIn PointSize\n"
1535 							"OpMemberDecorate %tesse_per_vertex_out 2 BuiltIn ClipDistance\n"
1536 							"OpMemberDecorate %tesse_per_vertex_out 3 BuiltIn CullDistance\n"
1537 							"OpDecorate %tesse_per_vertex_out Block\n"
1538 							"OpDecorate %tesse_gl_tessCoord BuiltIn TessCoord\n"
1539 							"OpDecorate %tesse_in_position Location 2\n"
1540 							"OpDecorate %tesse_out_color Location 1\n"
1541 							"OpDecorate %tesse_in_color Location 1\n";
1542 	}
1543 
1544 	combinedModule <<	"; Fragment decorations\n"
1545 						"OpDecorate %frag_fragColor Location 0\n"
1546 						"OpDecorate %frag_vtxColor Location 1\n"
1547 
1548 						SPIRV_ASSEMBLY_TYPES
1549 						SPIRV_ASSEMBLY_CONSTANTS
1550 						SPIRV_ASSEMBLY_ARRAYS
1551 
1552 						"; Vertex Variables\n"
1553 						"%vert_Position = OpVariable %ip_v4f32 Input\n"
1554 						"%vert_vtxColor = OpVariable %op_v4f32 Output\n"
1555 						"%vert_color = OpVariable %ip_v4f32 Input\n"
1556 						"%vert_vertex_id = OpVariable %ip_i32 Input\n"
1557 						"%vert_instance_id = OpVariable %ip_i32 Input\n";
1558 
1559 	if (useTessellation)
1560 		combinedModule <<	"%vert_vtxPosition = OpVariable %op_v4f32 Output\n";
1561 	else
1562 	{
1563 		combinedModule <<	"%vert_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
1564 							"%vert_op_per_vertex_out = OpTypePointer Output %vert_per_vertex_out\n"
1565 							"%vert_glPerVertex = OpVariable %vert_op_per_vertex_out Output\n";
1566 	}
1567 
1568 	if (useGeometry)
1569 	{
1570 		combinedModule <<	"; Geometry Variables\n"
1571 							"%geom_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
1572 							"%geom_a3_per_vertex_in = OpTypeArray %geom_per_vertex_in %c_u32_3\n"
1573 							"%geom_ip_a3_per_vertex_in = OpTypePointer Input %geom_a3_per_vertex_in\n"
1574 							"%geom_gl_in = OpVariable %geom_ip_a3_per_vertex_in Input\n"
1575 							"%geom_out_color = OpVariable %op_v4f32 Output\n"
1576 							"%geom_in_color = OpVariable %ip_a3v4f32 Input\n"
1577 							"%geom_out_gl_position = OpVariable %op_v4f32 Output\n";
1578 	}
1579 
1580 	if (useTessellation)
1581 	{
1582 		combinedModule <<	"; Tessellation Control Variables\n"
1583 							"%tessc_out_color = OpVariable %op_a3v4f32 Output\n"
1584 							"%tessc_gl_InvocationID = OpVariable %ip_i32 Input\n"
1585 							"%tessc_in_color = OpVariable %ip_a32v4f32 Input\n"
1586 							"%tessc_out_position = OpVariable %op_a3v4f32 Output\n"
1587 							"%tessc_in_position = OpVariable %ip_a32v4f32 Input\n"
1588 							"%tessc_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
1589 							"%tessc_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
1590 
1591 							"; Tessellation Evaluation Decorations\n"
1592 							"%tesse_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
1593 							"%tesse_op_per_vertex_out = OpTypePointer Output %tesse_per_vertex_out\n"
1594 							"%tesse_stream = OpVariable %tesse_op_per_vertex_out Output\n"
1595 							"%tesse_gl_tessCoord = OpVariable %ip_v3f32 Input\n"
1596 							"%tesse_in_position = OpVariable %ip_a32v4f32 Input\n"
1597 							"%tesse_out_color = OpVariable %op_v4f32 Output\n"
1598 							"%tesse_in_color = OpVariable %ip_a32v4f32 Input\n";
1599 	}
1600 
1601 	combinedModule	<<	"; Fragment Variables\n"
1602 						"%frag_fragColor = OpVariable %op_v4f32 Output\n"
1603 						"%frag_vtxColor = OpVariable %ip_v4f32 Input\n"
1604 
1605 						"; Vertex Entry\n"
1606 						"%vert_main = OpFunction %void None %voidf\n"
1607 						"%vert_label = OpLabel\n"
1608 						"%vert_tmp_position = OpLoad %v4f32 %vert_Position\n";
1609 
1610 	if (useTessellation)
1611 		combinedModule <<	"OpStore %vert_vtxPosition %vert_tmp_position\n";
1612 	else
1613 	{
1614 		combinedModule <<	"%vert_out_pos_ptr = OpAccessChain %op_v4f32 %vert_glPerVertex %c_i32_0\n"
1615 							"OpStore %vert_out_pos_ptr %vert_tmp_position\n";
1616 	}
1617 
1618 	combinedModule <<	"%vert_tmp_color = OpLoad %v4f32 %vert_color\n"
1619 						"OpStore %vert_vtxColor %vert_tmp_color\n"
1620 						"OpReturn\n"
1621 						"OpFunctionEnd\n";
1622 
1623 	if (useGeometry)
1624 	{
1625 		combinedModule <<	"; Geometry Entry\n"
1626 							"%geom_main = OpFunction %void None %voidf\n"
1627 							"%geom_label = OpLabel\n"
1628 							"%geom_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_0 %c_i32_0\n"
1629 							"%geom_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_1 %c_i32_0\n"
1630 							"%geom_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_2 %c_i32_0\n"
1631 							"%geom_in_position_0 = OpLoad %v4f32 %geom_gl_in_0_gl_position\n"
1632 							"%geom_in_position_1 = OpLoad %v4f32 %geom_gl_in_1_gl_position\n"
1633 							"%geom_in_position_2 = OpLoad %v4f32 %geom_gl_in_2_gl_position \n"
1634 							"%geom_in_color_0_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_0\n"
1635 							"%geom_in_color_1_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_1\n"
1636 							"%geom_in_color_2_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_2\n"
1637 							"%geom_in_color_0 = OpLoad %v4f32 %geom_in_color_0_ptr\n"
1638 							"%geom_in_color_1 = OpLoad %v4f32 %geom_in_color_1_ptr\n"
1639 							"%geom_in_color_2 = OpLoad %v4f32 %geom_in_color_2_ptr\n"
1640 							"OpStore %geom_out_gl_position %geom_in_position_0\n"
1641 							"OpStore %geom_out_color %geom_in_color_0\n"
1642 							"OpEmitVertex\n"
1643 							"OpStore %geom_out_gl_position %geom_in_position_1\n"
1644 							"OpStore %geom_out_color %geom_in_color_1\n"
1645 							"OpEmitVertex\n"
1646 							"OpStore %geom_out_gl_position %geom_in_position_2\n"
1647 							"OpStore %geom_out_color %geom_in_color_2\n"
1648 							"OpEmitVertex\n"
1649 							"OpEndPrimitive\n"
1650 							"OpReturn\n"
1651 							"OpFunctionEnd\n";
1652 	}
1653 
1654 	if (useTessellation)
1655 	{
1656 		combinedModule <<	"; Tessellation Control Entry\n"
1657 							"%tessc_main = OpFunction %void None %voidf\n"
1658 							"%tessc_label = OpLabel\n"
1659 							"%tessc_invocation_id = OpLoad %i32 %tessc_gl_InvocationID\n"
1660 							"%tessc_in_color_ptr = OpAccessChain %ip_v4f32 %tessc_in_color %tessc_invocation_id\n"
1661 							"%tessc_in_position_ptr = OpAccessChain %ip_v4f32 %tessc_in_position %tessc_invocation_id\n"
1662 							"%tessc_in_color_val = OpLoad %v4f32 %tessc_in_color_ptr\n"
1663 							"%tessc_in_position_val = OpLoad %v4f32 %tessc_in_position_ptr\n"
1664 							"%tessc_out_color_ptr = OpAccessChain %op_v4f32 %tessc_out_color %tessc_invocation_id\n"
1665 							"%tessc_out_position_ptr = OpAccessChain %op_v4f32 %tessc_out_position %tessc_invocation_id\n"
1666 							"OpStore %tessc_out_color_ptr %tessc_in_color_val\n"
1667 							"OpStore %tessc_out_position_ptr %tessc_in_position_val\n"
1668 							"%tessc_is_first_invocation = OpIEqual %bool %tessc_invocation_id %c_i32_0\n"
1669 							"OpSelectionMerge %tessc_merge_label None\n"
1670 							"OpBranchConditional %tessc_is_first_invocation %tessc_first_invocation %tessc_merge_label\n"
1671 							"%tessc_first_invocation = OpLabel\n"
1672 							"%tessc_tess_outer_0 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_0\n"
1673 							"%tessc_tess_outer_1 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_1\n"
1674 							"%tessc_tess_outer_2 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_2\n"
1675 							"%tessc_tess_inner = OpAccessChain %op_f32 %tessc_gl_TessLevelInner %c_i32_0\n"
1676 							"OpStore %tessc_tess_outer_0 %c_f32_1\n"
1677 							"OpStore %tessc_tess_outer_1 %c_f32_1\n"
1678 							"OpStore %tessc_tess_outer_2 %c_f32_1\n"
1679 							"OpStore %tessc_tess_inner %c_f32_1\n"
1680 							"OpBranch %tessc_merge_label\n"
1681 							"%tessc_merge_label = OpLabel\n"
1682 							"OpReturn\n"
1683 							"OpFunctionEnd\n"
1684 
1685 							"; Tessellation Evaluation Entry\n"
1686 							"%tesse_main = OpFunction %void None %voidf\n"
1687 							"%tesse_label = OpLabel\n"
1688 							"%tesse_tc_0_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_0\n"
1689 							"%tesse_tc_1_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_1\n"
1690 							"%tesse_tc_2_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_2\n"
1691 							"%tesse_tc_0 = OpLoad %f32 %tesse_tc_0_ptr\n"
1692 							"%tesse_tc_1 = OpLoad %f32 %tesse_tc_1_ptr\n"
1693 							"%tesse_tc_2 = OpLoad %f32 %tesse_tc_2_ptr\n"
1694 							"%tesse_in_pos_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_0\n"
1695 							"%tesse_in_pos_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_1\n"
1696 							"%tesse_in_pos_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_2\n"
1697 							"%tesse_in_pos_0 = OpLoad %v4f32 %tesse_in_pos_0_ptr\n"
1698 							"%tesse_in_pos_1 = OpLoad %v4f32 %tesse_in_pos_1_ptr\n"
1699 							"%tesse_in_pos_2 = OpLoad %v4f32 %tesse_in_pos_2_ptr\n"
1700 							"%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_0 %tesse_tc_0\n"
1701 							"%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_1 %tesse_tc_1\n"
1702 							"%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_2 %tesse_tc_2\n"
1703 							"%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n"
1704 							"%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n"
1705 							"%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n"
1706 							"OpStore %tesse_out_pos_ptr %tesse_computed_out\n"
1707 							"%tesse_in_clr_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_0\n"
1708 							"%tesse_in_clr_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_1\n"
1709 							"%tesse_in_clr_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_2\n"
1710 							"%tesse_in_clr_0 = OpLoad %v4f32 %tesse_in_clr_0_ptr\n"
1711 							"%tesse_in_clr_1 = OpLoad %v4f32 %tesse_in_clr_1_ptr\n"
1712 							"%tesse_in_clr_2 = OpLoad %v4f32 %tesse_in_clr_2_ptr\n"
1713 							"%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_0 %tesse_tc_0\n"
1714 							"%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_1 %tesse_tc_1\n"
1715 							"%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_2 %tesse_tc_2\n"
1716 							"%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n"
1717 							"%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n"
1718 							"OpStore %tesse_out_color %tesse_computed_clr\n"
1719 							"OpReturn\n"
1720 							"OpFunctionEnd\n";
1721 	}
1722 
1723 	combinedModule	<<	"; Fragment Entry\n"
1724 						"%frag_main = OpFunction %void None %voidf\n"
1725 						"%frag_label_main = OpLabel\n"
1726 						"%frag_tmp1 = OpLoad %v4f32 %frag_vtxColor\n"
1727 						"OpStore %frag_fragColor %frag_tmp1\n"
1728 						"OpReturn\n"
1729 						"OpFunctionEnd\n";
1730 
1731 	dst.spirvAsmSources.add("module") << combinedModule.str();
1732 }
1733 
createUnusedVariableModules(vk::SourceCollections & dst,UnusedVariableContext ctx)1734 void createUnusedVariableModules (vk::SourceCollections& dst, UnusedVariableContext ctx)
1735 {
1736 	if (ctx.shaderTasks[SHADER_TASK_INDEX_VERTEX] != SHADER_TASK_NONE)
1737 	{
1738 		std::ostringstream	shader;
1739 		bool				tessellation = (ctx.shaderTasks[SHADER_TASK_INDEX_TESS_CONTROL] != SHADER_TASK_NONE
1740 											|| ctx.shaderTasks[SHADER_TASK_INDEX_TESS_EVAL] != SHADER_TASK_NONE);
1741 		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_VERTEX];
1742 
1743 		shader	<< "OpCapability Shader\n"
1744 				<< "OpMemoryModel Logical GLSL450\n";
1745 
1746 		// Entry point depends on if tessellation is enabled or not to provide the vertex position.
1747 		shader	<< "OpEntryPoint Vertex %main \"main\" %Position %vtxColor %color "
1748 				<< (tessellation ? "%vtxPosition" : "%vtx_glPerVertex")
1749 				<< " %vertex_id %instance_id\n";
1750 		if (task == SHADER_TASK_UNUSED_FUNC)
1751 		{
1752 			shader << getUnusedEntryPoint();
1753 		}
1754 
1755 		// Decorations.
1756 		shader	<< "OpDecorate %Position Location 0\n"
1757 				<< "OpDecorate %vtxColor Location 1\n"
1758 				<< "OpDecorate %color Location 1\n"
1759 				<< "OpDecorate %vertex_id BuiltIn VertexIndex\n"
1760 				<< "OpDecorate %instance_id BuiltIn InstanceIndex\n";
1761 		if (tessellation)
1762 		{
1763 			shader	<< "OpDecorate %vtxPosition Location 2\n";
1764 		}
1765 		else
1766 		{
1767 			shader	<< "OpMemberDecorate %vert_per_vertex_out 0 BuiltIn Position\n"
1768 					<< "OpMemberDecorate %vert_per_vertex_out 1 BuiltIn PointSize\n"
1769 					<< "OpMemberDecorate %vert_per_vertex_out 2 BuiltIn ClipDistance\n"
1770 					<< "OpMemberDecorate %vert_per_vertex_out 3 BuiltIn CullDistance\n"
1771 					<< "OpDecorate %vert_per_vertex_out Block\n";
1772 		}
1773 		if (task != SHADER_TASK_NORMAL)
1774 		{
1775 			shader	<< getUnusedDecorations(ctx.variableLocation);
1776 		}
1777 
1778 		// Standard types, constants and arrays.
1779 		shader	<< "; Start of standard types, constants and arrays\n"
1780 				<< SPIRV_ASSEMBLY_TYPES
1781 				<< SPIRV_ASSEMBLY_CONSTANTS
1782 				<< SPIRV_ASSEMBLY_ARRAYS
1783 				<< "; End of standard types, constants and arrays\n";
1784 		if (task != SHADER_TASK_NORMAL)
1785 		{
1786 			shader	<< getUnusedTypesAndConstants();
1787 		}
1788 
1789 		// Variables.
1790 		if (tessellation)
1791 		{
1792 			shader	<< "%vtxPosition = OpVariable %op_v4f32 Output\n";
1793 		}
1794 		else
1795 		{
1796 			shader	<< "%vert_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
1797 					<< "%vert_op_per_vertex_out = OpTypePointer Output %vert_per_vertex_out\n"
1798 					<< "%vtx_glPerVertex = OpVariable %vert_op_per_vertex_out Output\n";
1799 		}
1800 		shader	<< "%Position = OpVariable %ip_v4f32 Input\n"
1801 				<< "%vtxColor = OpVariable %op_v4f32 Output\n"
1802 				<< "%color = OpVariable %ip_v4f32 Input\n"
1803 				<< "%vertex_id = OpVariable %ip_i32 Input\n"
1804 				<< "%instance_id = OpVariable %ip_i32 Input\n";
1805 		if (task != SHADER_TASK_NORMAL)
1806 		{
1807 			shader	<< getUnusedBuffer();
1808 		}
1809 
1810 		// Vertex main function.
1811 		shader	<< "%main = OpFunction %void None %voidf\n"
1812 				<< "%label = OpLabel\n"
1813 				<< "%tmp_position = OpLoad %v4f32 %Position\n";
1814 		if (tessellation)
1815 		{
1816 			shader	<< "OpStore %vtxPosition %tmp_position\n";
1817 		}
1818 		else
1819 		{
1820 			shader	<< "%vert_out_pos_ptr = OpAccessChain %op_v4f32 %vtx_glPerVertex %c_i32_0\n"
1821 					<< "OpStore %vert_out_pos_ptr %tmp_position\n";
1822 		}
1823 		shader	<< "%tmp_color = OpLoad %v4f32 %color\n"
1824 				<< "OpStore %vtxColor %tmp_color\n"
1825 				<< "OpReturn\n"
1826 				<< "OpFunctionEnd\n";
1827 		if (task == SHADER_TASK_UNUSED_FUNC)
1828 		{
1829 			shader	<< getUnusedFunctionBody();
1830 		}
1831 
1832 		dst.spirvAsmSources.add("vert") << shader.str();
1833 	}
1834 
1835 	if (ctx.shaderTasks[SHADER_TASK_INDEX_GEOMETRY] != SHADER_TASK_NONE)
1836 	{
1837 		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_GEOMETRY];
1838 		std::ostringstream	shader;
1839 
1840 		if (task != SHADER_TASK_NORMAL)
1841 		{
1842 			shader << getOpCapabilityShader();
1843 		}
1844 		shader	<< "OpCapability Geometry\n"
1845 				<< "OpMemoryModel Logical GLSL450\n";
1846 
1847 		// Entry points.
1848 		shader	<< "OpEntryPoint Geometry %geom1_main \"main\" %out_gl_position %gl_in %out_color %in_color\n";
1849 		if (task == SHADER_TASK_UNUSED_FUNC)
1850 		{
1851 			shader	<< getUnusedEntryPoint();
1852 		}
1853 		shader	<< "OpExecutionMode %geom1_main Triangles\n"
1854 				<< "OpExecutionMode %geom1_main OutputTriangleStrip\n"
1855 				<< "OpExecutionMode %geom1_main OutputVertices 3\n"
1856 				<< "OpExecutionMode %geom1_main Invocations 1\n";
1857 
1858 		// Decorations.
1859 		shader	<< "OpDecorate %out_gl_position BuiltIn Position\n"
1860 				<< "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n"
1861 				<< "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n"
1862 				<< "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n"
1863 				<< "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n"
1864 				<< "OpDecorate %per_vertex_in Block\n"
1865 				<< "OpDecorate %out_color Location 1\n"
1866 				<< "OpDecorate %in_color Location 1\n";
1867 		if (task != SHADER_TASK_NORMAL)
1868 		{
1869 			shader	<< getUnusedDecorations(ctx.variableLocation);
1870 		}
1871 
1872 		// Standard types, constants and arrays.
1873 		shader	<< "; Start of standard types, constants and arrays\n"
1874 				<< SPIRV_ASSEMBLY_TYPES
1875 				<< SPIRV_ASSEMBLY_CONSTANTS
1876 				<< SPIRV_ASSEMBLY_ARRAYS
1877 				<< "; End of standard types, constants and arrays\n";
1878 		if (task != SHADER_TASK_NORMAL)
1879 		{
1880 			shader	<< getUnusedTypesAndConstants();
1881 		}
1882 
1883 		// Variables.
1884 		shader	<< "%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
1885 				<< "%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n"
1886 				<< "%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n"
1887 				<< "%gl_in = OpVariable %ip_a3_per_vertex_in Input\n"
1888 				<< "%out_color = OpVariable %op_v4f32 Output\n"
1889 				<< "%in_color = OpVariable %ip_a3v4f32 Input\n"
1890 				<< "%out_gl_position = OpVariable %op_v4f32 Output\n";
1891 		if (task != SHADER_TASK_NORMAL)
1892 		{
1893 			shader << getUnusedBuffer();
1894 		}
1895 
1896 		// Main function.
1897 		shader	<< "%geom1_main = OpFunction %void None %voidf\n"
1898 				<< "%geom1_label = OpLabel\n"
1899 				<< "%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
1900 				<< "%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
1901 				<< "%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
1902 				<< "%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n"
1903 				<< "%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n"
1904 				<< "%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n"
1905 				<< "%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
1906 				<< "%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
1907 				<< "%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
1908 				<< "%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n"
1909 				<< "%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n"
1910 				<< "%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n"
1911 				<< "OpStore %out_gl_position %geom1_in_position_0\n"
1912 				<< "OpStore %out_color %geom1_in_color_0\n"
1913 				<< "OpEmitVertex\n"
1914 				<< "OpStore %out_gl_position %geom1_in_position_1\n"
1915 				<< "OpStore %out_color %geom1_in_color_1\n"
1916 				<< "OpEmitVertex\n"
1917 				<< "OpStore %out_gl_position %geom1_in_position_2\n"
1918 				<< "OpStore %out_color %geom1_in_color_2\n"
1919 				<< "OpEmitVertex\n"
1920 				<< "OpEndPrimitive\n"
1921 				<< "OpReturn\n"
1922 				<< "OpFunctionEnd\n";
1923 		if (task == SHADER_TASK_UNUSED_FUNC)
1924 		{
1925 			shader	<< getUnusedFunctionBody();
1926 		}
1927 
1928 		dst.spirvAsmSources.add("geom") << shader.str();
1929 	}
1930 
1931 	if (ctx.shaderTasks[SHADER_TASK_INDEX_TESS_CONTROL]	!= SHADER_TASK_NONE)
1932 	{
1933 		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_TESS_CONTROL];
1934 		std::ostringstream	shader;
1935 
1936 		if (task != SHADER_TASK_NORMAL)
1937 		{
1938 			shader	<< getOpCapabilityShader();
1939 		}
1940 		shader	<< "OpCapability Tessellation\n"
1941 				<< "OpMemoryModel Logical GLSL450\n";
1942 
1943 		// Entry point.
1944 		shader	<< "OpEntryPoint TessellationControl %tessc1_main \"main\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n";
1945 		if (task == SHADER_TASK_UNUSED_FUNC)
1946 		{
1947 			shader	<< getUnusedEntryPoint();
1948 		}
1949 		shader	<< "OpExecutionMode %tessc1_main OutputVertices 3\n";
1950 
1951 		// Decorations.
1952 		shader	<< "OpDecorate %out_color Location 1\n"
1953 				<< "OpDecorate %gl_InvocationID BuiltIn InvocationId\n"
1954 				<< "OpDecorate %in_color Location 1\n"
1955 				<< "OpDecorate %out_position Location 2\n"
1956 				<< "OpDecorate %in_position Location 2\n"
1957 				<< "OpDecorate %gl_TessLevelOuter Patch\n"
1958 				<< "OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n"
1959 				<< "OpDecorate %gl_TessLevelInner Patch\n"
1960 				<< "OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n";
1961 		if (task != SHADER_TASK_NORMAL)
1962 		{
1963 			shader	<< getUnusedDecorations(ctx.variableLocation);
1964 		}
1965 
1966 		// Standard types, constants and arrays.
1967 		shader	<< "; Start of standard types, constants and arrays\n"
1968 				<< SPIRV_ASSEMBLY_TYPES
1969 				<< SPIRV_ASSEMBLY_CONSTANTS
1970 				<< SPIRV_ASSEMBLY_ARRAYS
1971 				<< "; End of standard types, constants and arrays\n";
1972 		if (task != SHADER_TASK_NORMAL)
1973 		{
1974 			shader	<< getUnusedTypesAndConstants();
1975 		}
1976 
1977 		// Variables.
1978 		shader	<< "%out_color = OpVariable %op_a3v4f32 Output\n"
1979 				<< "%gl_InvocationID = OpVariable %ip_i32 Input\n"
1980 				<< "%in_color = OpVariable %ip_a32v4f32 Input\n"
1981 				<< "%out_position = OpVariable %op_a3v4f32 Output\n"
1982 				<< "%in_position = OpVariable %ip_a32v4f32 Input\n"
1983 				<< "%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
1984 				<< "%gl_TessLevelInner = OpVariable %op_a2f32 Output\n";
1985 		if (task != SHADER_TASK_NORMAL)
1986 		{
1987 			shader << getUnusedBuffer();
1988 		}
1989 
1990 		// Main entry point.
1991 		shader	<< "%tessc1_main = OpFunction %void None %voidf\n"
1992 				<< "%tessc1_label = OpLabel\n"
1993 				<< "%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n"
1994 				<< "%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n"
1995 				<< "%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n"
1996 				<< "%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n"
1997 				<< "%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n"
1998 				<< "%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n"
1999 				<< "%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n"
2000 				<< "OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n"
2001 				<< "OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n"
2002 				<< "%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n"
2003 				<< "OpSelectionMerge %tessc1_merge_label None\n"
2004 				<< "OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n"
2005 				<< "%tessc1_first_invocation = OpLabel\n"
2006 				<< "%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
2007 				<< "%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
2008 				<< "%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
2009 				<< "%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n"
2010 				<< "OpStore %tessc1_tess_outer_0 %c_f32_1\n"
2011 				<< "OpStore %tessc1_tess_outer_1 %c_f32_1\n"
2012 				<< "OpStore %tessc1_tess_outer_2 %c_f32_1\n"
2013 				<< "OpStore %tessc1_tess_inner %c_f32_1\n"
2014 				<< "OpBranch %tessc1_merge_label\n"
2015 				<< "%tessc1_merge_label = OpLabel\n"
2016 				<< "OpReturn\n"
2017 				<< "OpFunctionEnd\n";
2018 		if (task == SHADER_TASK_UNUSED_FUNC)
2019 		{
2020 			shader	<< getUnusedFunctionBody();
2021 		}
2022 
2023 		dst.spirvAsmSources.add("tessc") << shader.str();
2024 	}
2025 
2026 	if (ctx.shaderTasks[SHADER_TASK_INDEX_TESS_EVAL] != SHADER_TASK_NONE)
2027 	{
2028 		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_TESS_EVAL];
2029 		std::ostringstream	shader;
2030 
2031 		if (task != SHADER_TASK_NORMAL)
2032 		{
2033 			shader	<< getOpCapabilityShader();
2034 		}
2035 		shader	<< "OpCapability Tessellation\n"
2036 				<< "OpMemoryModel Logical GLSL450\n";
2037 
2038 		// Entry point.
2039 		shader	<< "OpEntryPoint TessellationEvaluation %tesse1_main \"main\" %stream %gl_tessCoord %in_position %out_color %in_color \n";
2040 		if (task == SHADER_TASK_UNUSED_FUNC)
2041 		{
2042 			shader	<< getUnusedEntryPoint();
2043 		}
2044 		shader	<< "OpExecutionMode %tesse1_main Triangles\n"
2045 				<< "OpExecutionMode %tesse1_main SpacingEqual\n"
2046 				<< "OpExecutionMode %tesse1_main VertexOrderCcw\n";
2047 
2048 		// Decorations.
2049 		shader	<< "OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n"
2050 				<< "OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n"
2051 				<< "OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n"
2052 				<< "OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n"
2053 				<< "OpDecorate %per_vertex_out Block\n"
2054 				<< "OpDecorate %gl_tessCoord BuiltIn TessCoord\n"
2055 				<< "OpDecorate %in_position Location 2\n"
2056 				<< "OpDecorate %out_color Location 1\n"
2057 				<< "OpDecorate %in_color Location 1\n";
2058 		if (task != SHADER_TASK_NORMAL)
2059 		{
2060 			shader	<< getUnusedDecorations(ctx.variableLocation);
2061 		}
2062 
2063 		// Standard types, constants and arrays.
2064 		shader	<< "; Start of standard types, constants and arrays\n"
2065 				<< SPIRV_ASSEMBLY_TYPES
2066 				<< SPIRV_ASSEMBLY_CONSTANTS
2067 				<< SPIRV_ASSEMBLY_ARRAYS
2068 				<< "; End of standard types, constants and arrays\n";
2069 		if (task != SHADER_TASK_NORMAL)
2070 		{
2071 			shader	<< getUnusedTypesAndConstants();
2072 		}
2073 
2074 		// Variables.
2075 		shader	<< "%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2076 				<< "%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n"
2077 				<< "%stream = OpVariable %op_per_vertex_out Output\n"
2078 				<< "%gl_tessCoord = OpVariable %ip_v3f32 Input\n"
2079 				<< "%in_position = OpVariable %ip_a32v4f32 Input\n"
2080 				<< "%out_color = OpVariable %op_v4f32 Output\n"
2081 				<< "%in_color = OpVariable %ip_a32v4f32 Input\n";
2082 		if (task != SHADER_TASK_NORMAL)
2083 		{
2084 			shader << getUnusedBuffer();
2085 		}
2086 
2087 		// Main entry point.
2088 		shader	<< "%tesse1_main = OpFunction %void None %voidf\n"
2089 				<< "%tesse1_label = OpLabel\n"
2090 				<< "%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
2091 				<< "%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
2092 				<< "%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
2093 				<< "%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n"
2094 				<< "%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n"
2095 				<< "%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n"
2096 				<< "%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
2097 				<< "%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
2098 				<< "%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
2099 				<< "%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n"
2100 				<< "%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n"
2101 				<< "%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n"
2102 				<< "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n"
2103 				<< "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n"
2104 				<< "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n"
2105 				<< "%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
2106 				<< "%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n"
2107 				<< "%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n"
2108 				<< "OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n"
2109 				<< "%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2110 				<< "%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2111 				<< "%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2112 				<< "%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n"
2113 				<< "%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n"
2114 				<< "%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n"
2115 				<< "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n"
2116 				<< "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n"
2117 				<< "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n"
2118 				<< "%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n"
2119 				<< "%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n"
2120 				<< "OpStore %out_color %tesse1_computed_clr\n"
2121 				<< "OpReturn\n"
2122 				<< "OpFunctionEnd\n";
2123 		if (task == SHADER_TASK_UNUSED_FUNC)
2124 		{
2125 			shader	<< getUnusedFunctionBody();
2126 		}
2127 
2128 		dst.spirvAsmSources.add("tesse") << shader.str();
2129 	}
2130 
2131 	if (ctx.shaderTasks[SHADER_TASK_INDEX_FRAGMENT] != SHADER_TASK_NONE)
2132 	{
2133 		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_FRAGMENT];
2134 		std::ostringstream	shader;
2135 
2136 		shader	<< "OpCapability Shader\n"
2137 				<< "OpMemoryModel Logical GLSL450\n";
2138 
2139 		// Entry point.
2140 		shader	<< "OpEntryPoint Fragment %main \"main\" %vtxColor %fragColor\n";
2141 		if (task == SHADER_TASK_UNUSED_FUNC)
2142 		{
2143 			shader	<< getUnusedEntryPoint();
2144 		}
2145 		shader	<< "OpExecutionMode %main OriginUpperLeft\n";
2146 
2147 		// Decorations.
2148 		shader	<< "OpDecorate %fragColor Location 0\n"
2149 				<< "OpDecorate %vtxColor Location 1\n";
2150 		if (task != SHADER_TASK_NORMAL)
2151 		{
2152 			shader	<< getUnusedDecorations(ctx.variableLocation);
2153 		}
2154 
2155 		// Standard types, constants and arrays.
2156 		shader	<< "; Start of standard types, constants and arrays\n"
2157 				<< SPIRV_ASSEMBLY_TYPES
2158 				<< SPIRV_ASSEMBLY_CONSTANTS
2159 				<< SPIRV_ASSEMBLY_ARRAYS
2160 				<< "; End of standard types, constants and arrays\n";
2161 		if (task != SHADER_TASK_NORMAL)
2162 		{
2163 			shader	<< getUnusedTypesAndConstants();
2164 		}
2165 
2166 		// Variables.
2167 		shader	<< "%fragColor = OpVariable %op_v4f32 Output\n"
2168 				<< "%vtxColor = OpVariable %ip_v4f32 Input\n";
2169 		if (task != SHADER_TASK_NORMAL)
2170 		{
2171 			shader << getUnusedBuffer();
2172 		}
2173 
2174 		// Main entry point.
2175 		shader	<< "%main = OpFunction %void None %voidf\n"
2176 				<< "%label_main = OpLabel\n"
2177 				<< "%tmp1 = OpLoad %v4f32 %vtxColor\n"
2178 				<< "OpStore %fragColor %tmp1\n"
2179 				<< "OpReturn\n"
2180 				<< "OpFunctionEnd\n";
2181 		if (task == SHADER_TASK_UNUSED_FUNC)
2182 		{
2183 			shader	<< getUnusedFunctionBody();
2184 		}
2185 
2186 		dst.spirvAsmSources.add("frag") << shader.str();
2187 	}
2188 }
2189 
createMultipleEntries(vk::SourceCollections & dst,InstanceContext)2190 void createMultipleEntries (vk::SourceCollections& dst, InstanceContext)
2191 {
2192 	dst.spirvAsmSources.add("vert") <<
2193 	// This module contains 2 vertex shaders. One that is a passthrough
2194 	// and a second that inverts the color of the output (1.0 - color).
2195 		"OpCapability Shader\n"
2196 		"OpMemoryModel Logical GLSL450\n"
2197 		"OpEntryPoint Vertex %main \"vert1\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
2198 		"OpEntryPoint Vertex %main2 \"vert2\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
2199 
2200 		"OpDecorate %vtxPosition Location 2\n"
2201 		"OpDecorate %Position Location 0\n"
2202 		"OpDecorate %vtxColor Location 1\n"
2203 		"OpDecorate %color Location 1\n"
2204 		"OpDecorate %vertex_id BuiltIn VertexIndex\n"
2205 		"OpDecorate %instance_id BuiltIn InstanceIndex\n"
2206 		SPIRV_ASSEMBLY_TYPES
2207 		SPIRV_ASSEMBLY_CONSTANTS
2208 		SPIRV_ASSEMBLY_ARRAYS
2209 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2210 		"%vtxPosition = OpVariable %op_v4f32 Output\n"
2211 		"%Position = OpVariable %ip_v4f32 Input\n"
2212 		"%vtxColor = OpVariable %op_v4f32 Output\n"
2213 		"%color = OpVariable %ip_v4f32 Input\n"
2214 		"%vertex_id = OpVariable %ip_i32 Input\n"
2215 		"%instance_id = OpVariable %ip_i32 Input\n"
2216 
2217 		"%main = OpFunction %void None %voidf\n"
2218 		"%label = OpLabel\n"
2219 		"%tmp_position = OpLoad %v4f32 %Position\n"
2220 		"OpStore %vtxPosition %tmp_position\n"
2221 		"%tmp_color = OpLoad %v4f32 %color\n"
2222 		"OpStore %vtxColor %tmp_color\n"
2223 		"OpReturn\n"
2224 		"OpFunctionEnd\n"
2225 
2226 		"%main2 = OpFunction %void None %voidf\n"
2227 		"%label2 = OpLabel\n"
2228 		"%tmp_position2 = OpLoad %v4f32 %Position\n"
2229 		"OpStore %vtxPosition %tmp_position2\n"
2230 		"%tmp_color2 = OpLoad %v4f32 %color\n"
2231 		"%tmp_color3 = OpFSub %v4f32 %cval %tmp_color2\n"
2232 		"%tmp_color4 = OpVectorInsertDynamic %v4f32 %tmp_color3 %c_f32_1 %c_i32_3\n"
2233 		"OpStore %vtxColor %tmp_color4\n"
2234 		"OpReturn\n"
2235 		"OpFunctionEnd\n";
2236 
2237 	dst.spirvAsmSources.add("frag") <<
2238 		// This is a single module that contains 2 fragment shaders.
2239 		// One that passes color through and the other that inverts the output
2240 		// color (1.0 - color).
2241 		"OpCapability Shader\n"
2242 		"OpMemoryModel Logical GLSL450\n"
2243 		"OpEntryPoint Fragment %main \"frag1\" %vtxColor %fragColor\n"
2244 		"OpEntryPoint Fragment %main2 \"frag2\" %vtxColor %fragColor\n"
2245 		"OpExecutionMode %main OriginUpperLeft\n"
2246 		"OpExecutionMode %main2 OriginUpperLeft\n"
2247 
2248 		"OpDecorate %fragColor Location 0\n"
2249 		"OpDecorate %vtxColor Location 1\n"
2250 		SPIRV_ASSEMBLY_TYPES
2251 		SPIRV_ASSEMBLY_CONSTANTS
2252 		SPIRV_ASSEMBLY_ARRAYS
2253 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2254 		"%fragColor = OpVariable %op_v4f32 Output\n"
2255 		"%vtxColor = OpVariable %ip_v4f32 Input\n"
2256 
2257 		"%main = OpFunction %void None %voidf\n"
2258 		"%label_main = OpLabel\n"
2259 		"%tmp1 = OpLoad %v4f32 %vtxColor\n"
2260 		"OpStore %fragColor %tmp1\n"
2261 		"OpReturn\n"
2262 		"OpFunctionEnd\n"
2263 
2264 		"%main2 = OpFunction %void None %voidf\n"
2265 		"%label_main2 = OpLabel\n"
2266 		"%tmp2 = OpLoad %v4f32 %vtxColor\n"
2267 		"%tmp3 = OpFSub %v4f32 %cval %tmp2\n"
2268 		"%tmp4 = OpVectorInsertDynamic %v4f32 %tmp3 %c_f32_1 %c_i32_3\n"
2269 		"OpStore %fragColor %tmp4\n"
2270 		"OpReturn\n"
2271 		"OpFunctionEnd\n";
2272 
2273 	dst.spirvAsmSources.add("geom") <<
2274 		"OpCapability Geometry\n"
2275 		"OpMemoryModel Logical GLSL450\n"
2276 		"OpEntryPoint Geometry %geom1_main \"geom1\" %out_gl_position %gl_in %out_color %in_color\n"
2277 		"OpEntryPoint Geometry %geom2_main \"geom2\" %out_gl_position %gl_in %out_color %in_color\n"
2278 		"OpExecutionMode %geom1_main Triangles\n"
2279 		"OpExecutionMode %geom2_main Triangles\n"
2280 		"OpExecutionMode %geom1_main OutputTriangleStrip\n"
2281 		"OpExecutionMode %geom2_main OutputTriangleStrip\n"
2282 		"OpExecutionMode %geom1_main OutputVertices 3\n"
2283 		"OpExecutionMode %geom2_main OutputVertices 3\n"
2284 		"OpExecutionMode %geom1_main Invocations 1\n"
2285 		"OpExecutionMode %geom2_main Invocations 1\n"
2286 		"OpDecorate %out_gl_position BuiltIn Position\n"
2287 		"OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n"
2288 		"OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n"
2289 		"OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n"
2290 		"OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n"
2291 		"OpDecorate %per_vertex_in Block\n"
2292 		"OpDecorate %out_color Location 1\n"
2293 		"OpDecorate %in_color Location 1\n"
2294 		SPIRV_ASSEMBLY_TYPES
2295 		SPIRV_ASSEMBLY_CONSTANTS
2296 		SPIRV_ASSEMBLY_ARRAYS
2297 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2298 		"%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2299 		"%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n"
2300 		"%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n"
2301 		"%gl_in = OpVariable %ip_a3_per_vertex_in Input\n"
2302 		"%out_color = OpVariable %op_v4f32 Output\n"
2303 		"%in_color = OpVariable %ip_a3v4f32 Input\n"
2304 		"%out_gl_position = OpVariable %op_v4f32 Output\n"
2305 
2306 		"%geom1_main = OpFunction %void None %voidf\n"
2307 		"%geom1_label = OpLabel\n"
2308 		"%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
2309 		"%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
2310 		"%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
2311 		"%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n"
2312 		"%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n"
2313 		"%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n"
2314 		"%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2315 		"%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2316 		"%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2317 		"%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n"
2318 		"%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n"
2319 		"%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n"
2320 		"OpStore %out_gl_position %geom1_in_position_0\n"
2321 		"OpStore %out_color %geom1_in_color_0\n"
2322 		"OpEmitVertex\n"
2323 		"OpStore %out_gl_position %geom1_in_position_1\n"
2324 		"OpStore %out_color %geom1_in_color_1\n"
2325 		"OpEmitVertex\n"
2326 		"OpStore %out_gl_position %geom1_in_position_2\n"
2327 		"OpStore %out_color %geom1_in_color_2\n"
2328 		"OpEmitVertex\n"
2329 		"OpEndPrimitive\n"
2330 		"OpReturn\n"
2331 		"OpFunctionEnd\n"
2332 
2333 		"%geom2_main = OpFunction %void None %voidf\n"
2334 		"%geom2_label = OpLabel\n"
2335 		"%geom2_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
2336 		"%geom2_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
2337 		"%geom2_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
2338 		"%geom2_in_position_0 = OpLoad %v4f32 %geom2_gl_in_0_gl_position\n"
2339 		"%geom2_in_position_1 = OpLoad %v4f32 %geom2_gl_in_1_gl_position\n"
2340 		"%geom2_in_position_2 = OpLoad %v4f32 %geom2_gl_in_2_gl_position \n"
2341 		"%geom2_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2342 		"%geom2_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2343 		"%geom2_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2344 		"%geom2_in_color_0 = OpLoad %v4f32 %geom2_in_color_0_ptr\n"
2345 		"%geom2_in_color_1 = OpLoad %v4f32 %geom2_in_color_1_ptr\n"
2346 		"%geom2_in_color_2 = OpLoad %v4f32 %geom2_in_color_2_ptr\n"
2347 		"%geom2_transformed_in_color_0 = OpFSub %v4f32 %cval %geom2_in_color_0\n"
2348 		"%geom2_transformed_in_color_1 = OpFSub %v4f32 %cval %geom2_in_color_1\n"
2349 		"%geom2_transformed_in_color_2 = OpFSub %v4f32 %cval %geom2_in_color_2\n"
2350 		"%geom2_transformed_in_color_0_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_0 %c_f32_1 %c_i32_3\n"
2351 		"%geom2_transformed_in_color_1_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_1 %c_f32_1 %c_i32_3\n"
2352 		"%geom2_transformed_in_color_2_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_2 %c_f32_1 %c_i32_3\n"
2353 		"OpStore %out_gl_position %geom2_in_position_0\n"
2354 		"OpStore %out_color %geom2_transformed_in_color_0_a\n"
2355 		"OpEmitVertex\n"
2356 		"OpStore %out_gl_position %geom2_in_position_1\n"
2357 		"OpStore %out_color %geom2_transformed_in_color_1_a\n"
2358 		"OpEmitVertex\n"
2359 		"OpStore %out_gl_position %geom2_in_position_2\n"
2360 		"OpStore %out_color %geom2_transformed_in_color_2_a\n"
2361 		"OpEmitVertex\n"
2362 		"OpEndPrimitive\n"
2363 		"OpReturn\n"
2364 		"OpFunctionEnd\n";
2365 
2366 	dst.spirvAsmSources.add("tessc") <<
2367 		"OpCapability Tessellation\n"
2368 		"OpMemoryModel Logical GLSL450\n"
2369 		"OpEntryPoint TessellationControl %tessc1_main \"tessc1\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
2370 		"OpEntryPoint TessellationControl %tessc2_main \"tessc2\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
2371 		"OpExecutionMode %tessc1_main OutputVertices 3\n"
2372 		"OpExecutionMode %tessc2_main OutputVertices 3\n"
2373 		"OpDecorate %out_color Location 1\n"
2374 		"OpDecorate %gl_InvocationID BuiltIn InvocationId\n"
2375 		"OpDecorate %in_color Location 1\n"
2376 		"OpDecorate %out_position Location 2\n"
2377 		"OpDecorate %in_position Location 2\n"
2378 		"OpDecorate %gl_TessLevelOuter Patch\n"
2379 		"OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n"
2380 		"OpDecorate %gl_TessLevelInner Patch\n"
2381 		"OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n"
2382 		SPIRV_ASSEMBLY_TYPES
2383 		SPIRV_ASSEMBLY_CONSTANTS
2384 		SPIRV_ASSEMBLY_ARRAYS
2385 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2386 		"%out_color = OpVariable %op_a3v4f32 Output\n"
2387 		"%gl_InvocationID = OpVariable %ip_i32 Input\n"
2388 		"%in_color = OpVariable %ip_a32v4f32 Input\n"
2389 		"%out_position = OpVariable %op_a3v4f32 Output\n"
2390 		"%in_position = OpVariable %ip_a32v4f32 Input\n"
2391 		"%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
2392 		"%gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
2393 
2394 		"%tessc1_main = OpFunction %void None %voidf\n"
2395 		"%tessc1_label = OpLabel\n"
2396 		"%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n"
2397 		"%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n"
2398 		"%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n"
2399 		"%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n"
2400 		"%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n"
2401 		"%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n"
2402 		"%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n"
2403 		"OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n"
2404 		"OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n"
2405 		"%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n"
2406 		"OpSelectionMerge %tessc1_merge_label None\n"
2407 		"OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n"
2408 		"%tessc1_first_invocation = OpLabel\n"
2409 		"%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
2410 		"%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
2411 		"%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
2412 		"%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n"
2413 		"OpStore %tessc1_tess_outer_0 %c_f32_1\n"
2414 		"OpStore %tessc1_tess_outer_1 %c_f32_1\n"
2415 		"OpStore %tessc1_tess_outer_2 %c_f32_1\n"
2416 		"OpStore %tessc1_tess_inner %c_f32_1\n"
2417 		"OpBranch %tessc1_merge_label\n"
2418 		"%tessc1_merge_label = OpLabel\n"
2419 		"OpReturn\n"
2420 		"OpFunctionEnd\n"
2421 
2422 		"%tessc2_main = OpFunction %void None %voidf\n"
2423 		"%tessc2_label = OpLabel\n"
2424 		"%tessc2_invocation_id = OpLoad %i32 %gl_InvocationID\n"
2425 		"%tessc2_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc2_invocation_id\n"
2426 		"%tessc2_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc2_invocation_id\n"
2427 		"%tessc2_in_color_val = OpLoad %v4f32 %tessc2_in_color_ptr\n"
2428 		"%tessc2_in_position_val = OpLoad %v4f32 %tessc2_in_position_ptr\n"
2429 		"%tessc2_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc2_invocation_id\n"
2430 		"%tessc2_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc2_invocation_id\n"
2431 		"%tessc2_transformed_color = OpFSub %v4f32 %cval %tessc2_in_color_val\n"
2432 		"%tessc2_transformed_color_a = OpVectorInsertDynamic %v4f32 %tessc2_transformed_color %c_f32_1 %c_i32_3\n"
2433 		"OpStore %tessc2_out_color_ptr %tessc2_transformed_color_a\n"
2434 		"OpStore %tessc2_out_position_ptr %tessc2_in_position_val\n"
2435 		"%tessc2_is_first_invocation = OpIEqual %bool %tessc2_invocation_id %c_i32_0\n"
2436 		"OpSelectionMerge %tessc2_merge_label None\n"
2437 		"OpBranchConditional %tessc2_is_first_invocation %tessc2_first_invocation %tessc2_merge_label\n"
2438 		"%tessc2_first_invocation = OpLabel\n"
2439 		"%tessc2_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
2440 		"%tessc2_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
2441 		"%tessc2_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
2442 		"%tessc2_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n"
2443 		"OpStore %tessc2_tess_outer_0 %c_f32_1\n"
2444 		"OpStore %tessc2_tess_outer_1 %c_f32_1\n"
2445 		"OpStore %tessc2_tess_outer_2 %c_f32_1\n"
2446 		"OpStore %tessc2_tess_inner %c_f32_1\n"
2447 		"OpBranch %tessc2_merge_label\n"
2448 		"%tessc2_merge_label = OpLabel\n"
2449 		"OpReturn\n"
2450 		"OpFunctionEnd\n";
2451 
2452 	dst.spirvAsmSources.add("tesse") <<
2453 		"OpCapability Tessellation\n"
2454 		"OpMemoryModel Logical GLSL450\n"
2455 		"OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
2456 		"OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
2457 		"OpExecutionMode %tesse1_main Triangles\n"
2458 		"OpExecutionMode %tesse1_main SpacingEqual\n"
2459 		"OpExecutionMode %tesse1_main VertexOrderCcw\n"
2460 		"OpExecutionMode %tesse2_main Triangles\n"
2461 		"OpExecutionMode %tesse2_main SpacingEqual\n"
2462 		"OpExecutionMode %tesse2_main VertexOrderCcw\n"
2463 		"OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n"
2464 		"OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n"
2465 		"OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n"
2466 		"OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n"
2467 		"OpDecorate %per_vertex_out Block\n"
2468 		"OpDecorate %gl_tessCoord BuiltIn TessCoord\n"
2469 		"OpDecorate %in_position Location 2\n"
2470 		"OpDecorate %out_color Location 1\n"
2471 		"OpDecorate %in_color Location 1\n"
2472 		SPIRV_ASSEMBLY_TYPES
2473 		SPIRV_ASSEMBLY_CONSTANTS
2474 		SPIRV_ASSEMBLY_ARRAYS
2475 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2476 		"%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2477 		"%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n"
2478 		"%stream = OpVariable %op_per_vertex_out Output\n"
2479 		"%gl_tessCoord = OpVariable %ip_v3f32 Input\n"
2480 		"%in_position = OpVariable %ip_a32v4f32 Input\n"
2481 		"%out_color = OpVariable %op_v4f32 Output\n"
2482 		"%in_color = OpVariable %ip_a32v4f32 Input\n"
2483 
2484 		"%tesse1_main = OpFunction %void None %voidf\n"
2485 		"%tesse1_label = OpLabel\n"
2486 		"%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
2487 		"%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
2488 		"%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
2489 		"%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n"
2490 		"%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n"
2491 		"%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n"
2492 		"%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
2493 		"%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
2494 		"%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
2495 		"%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n"
2496 		"%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n"
2497 		"%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n"
2498 		"%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n"
2499 		"%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n"
2500 		"%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n"
2501 		"%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
2502 		"%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n"
2503 		"%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n"
2504 		"OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n"
2505 		"%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2506 		"%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2507 		"%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2508 		"%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n"
2509 		"%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n"
2510 		"%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n"
2511 		"%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n"
2512 		"%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n"
2513 		"%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n"
2514 		"%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n"
2515 		"%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n"
2516 		"OpStore %out_color %tesse1_computed_clr\n"
2517 		"OpReturn\n"
2518 		"OpFunctionEnd\n"
2519 
2520 		"%tesse2_main = OpFunction %void None %voidf\n"
2521 		"%tesse2_label = OpLabel\n"
2522 		"%tesse2_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
2523 		"%tesse2_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
2524 		"%tesse2_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
2525 		"%tesse2_tc_0 = OpLoad %f32 %tesse2_tc_0_ptr\n"
2526 		"%tesse2_tc_1 = OpLoad %f32 %tesse2_tc_1_ptr\n"
2527 		"%tesse2_tc_2 = OpLoad %f32 %tesse2_tc_2_ptr\n"
2528 		"%tesse2_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
2529 		"%tesse2_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
2530 		"%tesse2_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
2531 		"%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n"
2532 		"%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n"
2533 		"%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n"
2534 		"%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_0 %tesse2_tc_0\n"
2535 		"%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_1 %tesse2_tc_1\n"
2536 		"%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_2 %tesse2_tc_2\n"
2537 		"%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
2538 		"%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n"
2539 		"%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n"
2540 		"OpStore %tesse2_out_pos_ptr %tesse2_computed_out\n"
2541 		"%tesse2_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2542 		"%tesse2_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2543 		"%tesse2_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2544 		"%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n"
2545 		"%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n"
2546 		"%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n"
2547 		"%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_0 %tesse2_tc_0\n"
2548 		"%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_1 %tesse2_tc_1\n"
2549 		"%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_2 %tesse2_tc_2\n"
2550 		"%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n"
2551 		"%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n"
2552 		"%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n"
2553 		"%tesse2_clr_transformed_a = OpVectorInsertDynamic %v4f32 %tesse2_clr_transformed %c_f32_1 %c_i32_3\n"
2554 		"OpStore %out_color %tesse2_clr_transformed_a\n"
2555 		"OpReturn\n"
2556 		"OpFunctionEnd\n";
2557 }
2558 
compare16BitFloat(float original,deUint16 returned,RoundingModeFlags flags,tcu::TestLog & log)2559 bool compare16BitFloat (float original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log)
2560 {
2561 	// We only support RTE, RTZ, or both.
2562 	DE_ASSERT(static_cast<int>(flags) > 0 && static_cast<int>(flags) < 4);
2563 
2564 	const Float32	originalFloat	(original);
2565 	const Float16	returnedFloat	(returned);
2566 
2567 	// Zero are turned into zero under both RTE and RTZ.
2568 	if (originalFloat.isZero())
2569 	{
2570 		if (returnedFloat.isZero())
2571 			return true;
2572 
2573 		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2574 		return false;
2575 	}
2576 
2577 	// Any denormalized value input into a shader may be flushed to 0.
2578 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2579 		return true;
2580 
2581 	// Inf are always turned into Inf with the same sign, too.
2582 	if (originalFloat.isInf())
2583 	{
2584 		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2585 			return true;
2586 
2587 		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2588 		return false;
2589 	}
2590 
2591 	// NaN are always turned into NaN, too.
2592 	if (originalFloat.isNaN())
2593 	{
2594 		if (returnedFloat.isNaN())
2595 			return true;
2596 
2597 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2598 		return false;
2599 	}
2600 
2601 	// Check all rounding modes
2602 	for (int bitNdx = 0; bitNdx < 2; ++bitNdx)
2603 	{
2604 		if ((flags & (1u << bitNdx)) == 0)
2605 			continue;	// This rounding mode is not selected.
2606 
2607 		const Float16	expectedFloat	(deFloat32To16Round(original, deRoundingMode(bitNdx)));
2608 
2609 		// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2610 		if (expectedFloat.isDenorm() && returnedFloat.isZero())
2611 			return true;
2612 
2613 		// If not matched in the above cases, they should have the same bit pattern.
2614 		if (expectedFloat.bits() == returnedFloat.bits())
2615 			return true;
2616 	}
2617 
2618 	log << TestLog::Message << "Error: found unmatched 32-bit and 16-bit floats: " << originalFloat.bits() << " vs " << returned << TestLog::EndMessage;
2619 	return false;
2620 }
2621 
compare16BitFloat(deUint16 original,deUint16 returned,tcu::TestLog & log)2622 bool compare16BitFloat (deUint16 original, deUint16 returned, tcu::TestLog& log)
2623 {
2624 	const Float16	originalFloat	(original);
2625 	const Float16	returnedFloat	(returned);
2626 
2627 	if (originalFloat.isZero())
2628 	{
2629 		if (returnedFloat.isZero())
2630 			return true;
2631 
2632 		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2633 		return false;
2634 	}
2635 
2636 	// Any denormalized value input into a shader or potentially generated by any instruction in a shader
2637 	// may be flushed to 0.
2638 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2639 		return true;
2640 
2641 	// Inf are always turned into Inf with the same sign, too.
2642 	if (originalFloat.isInf())
2643 	{
2644 		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2645 			return true;
2646 
2647 		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2648 		return false;
2649 	}
2650 
2651 	// NaN are always turned into NaN, too.
2652 	if (originalFloat.isNaN())
2653 	{
2654 		if (returnedFloat.isNaN())
2655 			return true;
2656 
2657 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2658 		return false;
2659 	}
2660 
2661 	// If not matched in the above cases, they should have the same bit pattern.
2662 	if (originalFloat.bits() == returnedFloat.bits())
2663 		return true;
2664 
2665 	log << TestLog::Message << "Error: found unmatched 16-bit and 16-bit floats: " << original << " vs " << returned << TestLog::EndMessage;
2666 	return false;
2667 }
2668 
compare16BitFloat(deUint16 original,float returned,tcu::TestLog & log)2669 bool compare16BitFloat(deUint16 original, float returned, tcu::TestLog & log)
2670 {
2671 	const Float16	originalFloat	(original);
2672 	const Float32	returnedFloat	(returned);
2673 
2674 	// Zero are turned into zero under both RTE and RTZ.
2675 	if (originalFloat.isZero())
2676 	{
2677 		if (returnedFloat.isZero())
2678 			return true;
2679 
2680 		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2681 		return false;
2682 	}
2683 
2684 	// Any denormalized value input into a shader may be flushed to 0.
2685 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2686 		return true;
2687 
2688 	// Inf are always turned into Inf with the same sign, too.
2689 	if (originalFloat.isInf())
2690 	{
2691 		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2692 			return true;
2693 
2694 		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2695 		return false;
2696 	}
2697 
2698 	// NaN are always turned into NaN, too.
2699 	if (originalFloat.isNaN())
2700 	{
2701 		if (returnedFloat.isNaN())
2702 			return true;
2703 
2704 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2705 		return false;
2706 	}
2707 
2708 	// In all other cases, conversion should be exact.
2709 	const Float32 expectedFloat (deFloat16To32(original));
2710 	if (expectedFloat.bits() == returnedFloat.bits())
2711 		return true;
2712 
2713 	log << TestLog::Message << "Error: found unmatched 16-bit and 32-bit floats: " << original << " vs " << returnedFloat.bits() << TestLog::EndMessage;
2714 	return false;
2715 }
2716 
compare16BitFloat(deFloat16 original,deFloat16 returned,std::string & error)2717 bool compare16BitFloat (deFloat16 original, deFloat16 returned, std::string& error)
2718 {
2719 	std::ostringstream	log;
2720 	const Float16		originalFloat	(original);
2721 	const Float16		returnedFloat	(returned);
2722 
2723 	if (originalFloat.isZero())
2724 	{
2725 		if (returnedFloat.isZero())
2726 			return true;
2727 
2728 		log << "Error: expected zero but returned " << std::hex << "0x" << returned << " (" << returnedFloat.asFloat() << ")";
2729 		error = log.str();
2730 		return false;
2731 	}
2732 
2733 	// Any denormalized value input into a shader may be flushed to 0.
2734 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2735 		return true;
2736 
2737 	// Inf are always turned into Inf with the same sign, too.
2738 	if (originalFloat.isInf())
2739 	{
2740 		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2741 			return true;
2742 
2743 		log << "Error: expected Inf but returned " << std::hex << "0x" << returned << " (" << returnedFloat.asFloat() << ")";
2744 		error = log.str();
2745 		return false;
2746 	}
2747 
2748 	// NaN are always turned into NaN, too.
2749 	if (originalFloat.isNaN())
2750 	{
2751 		if (returnedFloat.isNaN())
2752 			return true;
2753 
2754 		log << "Error: expected NaN but returned " << std::hex << "0x" << returned << " (" << returnedFloat.asFloat() << ")";
2755 		error = log.str();
2756 		return false;
2757 	}
2758 
2759 	// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2760 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2761 		return true;
2762 
2763 	// If not matched in the above cases, they should have the same bit pattern.
2764 	if (originalFloat.bits() == returnedFloat.bits())
2765 		return true;
2766 
2767 	log << "Error: found unmatched 16-bit and 16-bit floats: 0x"
2768 		<< std::hex << original << " <=> 0x" << returned
2769 		<< " (" << originalFloat.asFloat() << " <=> " << returnedFloat.asFloat() << ")";
2770 	error = log.str();
2771 	return false;
2772 }
2773 
compare16BitFloat64(double original,deUint16 returned,RoundingModeFlags flags,tcu::TestLog & log)2774 bool compare16BitFloat64 (double original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log)
2775 {
2776 	// We only support RTE, RTZ, or both.
2777 	DE_ASSERT(static_cast<int>(flags) > 0 && static_cast<int>(flags) < 4);
2778 
2779 	const Float64	originalFloat	(original);
2780 	const Float16	returnedFloat	(returned);
2781 
2782 	// Zero are turned into zero under both RTE and RTZ.
2783 	if (originalFloat.isZero())
2784 	{
2785 		if (returnedFloat.isZero())
2786 			return true;
2787 
2788 		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2789 		return false;
2790 	}
2791 
2792 	// Any denormalized value input into a shader may be flushed to 0.
2793 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2794 		return true;
2795 
2796 	// Inf are always turned into Inf with the same sign, too.
2797 	if (originalFloat.isInf())
2798 	{
2799 		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2800 			return true;
2801 
2802 		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2803 		return false;
2804 	}
2805 
2806 	// NaN are always turned into NaN, too.
2807 	if (originalFloat.isNaN())
2808 	{
2809 		if (returnedFloat.isNaN())
2810 			return true;
2811 
2812 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2813 		return false;
2814 	}
2815 
2816 	// Check all rounding modes
2817 	for (int bitNdx = 0; bitNdx < 2; ++bitNdx)
2818 	{
2819 		if ((flags & (1u << bitNdx)) == 0)
2820 			continue;	// This rounding mode is not selected.
2821 
2822 		const Float16	expectedFloat	(deFloat64To16Round(original, deRoundingMode(bitNdx)));
2823 
2824 		// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2825 		if (expectedFloat.isDenorm() && returnedFloat.isZero())
2826 			return true;
2827 
2828 		// If not matched in the above cases, they should have the same bit pattern.
2829 		if (expectedFloat.bits() == returnedFloat.bits())
2830 			return true;
2831 	}
2832 
2833 	log << TestLog::Message << "Error: found unmatched 64-bit and 16-bit floats: " << originalFloat.bits() << " vs " << returned << TestLog::EndMessage;
2834 	return false;
2835 }
2836 
compare32BitFloat(float expected,float returned,tcu::TestLog & log)2837 bool compare32BitFloat (float expected, float returned, tcu::TestLog& log)
2838 {
2839 	const Float32	expectedFloat	(expected);
2840 	const Float32	returnedFloat	(returned);
2841 
2842 	// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2843 	if (expectedFloat.isDenorm() && returnedFloat.isZero())
2844 		return true;
2845 
2846 	{
2847 		const Float16	originalFloat	(deFloat32To16(expected));
2848 
2849 		// Any denormalized value input into a shader may be flushed to 0.
2850 		if (originalFloat.isDenorm() && returnedFloat.isZero())
2851 			return true;
2852 	}
2853 
2854 	if (expectedFloat.isNaN())
2855 	{
2856 		if (returnedFloat.isNaN())
2857 			return true;
2858 
2859 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2860 		return false;
2861 	}
2862 
2863 	if (returned == expected)
2864 		return true;
2865 
2866 	log << TestLog::Message << "Error: found unmatched 32-bit float: expected " << expectedFloat.bits() << " vs. returned " << returnedFloat.bits() << TestLog::EndMessage;
2867 	return false;
2868 }
2869 
compare64BitFloat(double expected,double returned,tcu::TestLog & log)2870 bool compare64BitFloat (double expected, double returned, tcu::TestLog& log)
2871 {
2872 	const Float64	expectedDouble	(expected);
2873 	const Float64	returnedDouble	(returned);
2874 
2875 	// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2876 	if (expectedDouble.isDenorm() && returnedDouble.isZero())
2877 		return true;
2878 
2879 	{
2880 		const Float16	originalDouble	(deFloat64To16(expected));
2881 
2882 		// Any denormalized value input into a shader may be flushed to 0.
2883 		if (originalDouble.isDenorm() && returnedDouble.isZero())
2884 			return true;
2885 	}
2886 
2887 	if (expectedDouble.isNaN())
2888 	{
2889 		if (returnedDouble.isNaN())
2890 			return true;
2891 
2892 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2893 		return false;
2894 	}
2895 
2896 	if (returned == expected)
2897 		return true;
2898 
2899 	log << TestLog::Message << "Error: found unmatched 64-bit float: expected " << expectedDouble.bits() << " vs. returned " << returnedDouble.bits() << TestLog::EndMessage;
2900 	return false;
2901 }
2902 
createBufferForResource(const DeviceInterface & vk,const VkDevice vkDevice,const Resource & resource,deUint32 queueFamilyIndex)2903 Move<VkBuffer> createBufferForResource (const DeviceInterface& vk, const VkDevice vkDevice, const Resource& resource, deUint32 queueFamilyIndex)
2904 {
2905 	const vk::VkDescriptorType resourceType = resource.getDescriptorType();
2906 
2907 	vector<deUint8>	resourceBytes;
2908 	resource.getBytes(resourceBytes);
2909 
2910 	const VkBufferCreateInfo	resourceBufferParams	=
2911 	{
2912 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,								// sType
2913 		DE_NULL,															// pNext
2914 		(VkBufferCreateFlags)0,												// flags
2915 		(VkDeviceSize)resourceBytes.size(),									// size
2916 		(VkBufferUsageFlags)getMatchingBufferUsageFlagBit(resourceType),	// usage
2917 		VK_SHARING_MODE_EXCLUSIVE,											// sharingMode
2918 		1u,																	// queueFamilyCount
2919 		&queueFamilyIndex,													// pQueueFamilyIndices
2920 	};
2921 
2922 	return createBuffer(vk, vkDevice, &resourceBufferParams);
2923 }
2924 
createImageForResource(const DeviceInterface & vk,const VkDevice vkDevice,const Resource & resource,VkFormat inputFormat,deUint32 queueFamilyIndex)2925 Move<VkImage> createImageForResource (const DeviceInterface& vk, const VkDevice vkDevice, const Resource& resource, VkFormat inputFormat, deUint32 queueFamilyIndex)
2926 {
2927 	const VkImageCreateInfo	resourceImageParams	=
2928 	{
2929 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,								//	VkStructureType		sType;
2930 		DE_NULL,															//	const void*			pNext;
2931 		0u,																	//	VkImageCreateFlags	flags;
2932 		VK_IMAGE_TYPE_2D,													//	VkImageType			imageType;
2933 		inputFormat,														//	VkFormat			format;
2934 		{ 8, 8, 1 },														//	VkExtent3D			extent;
2935 		1u,																	//	deUint32			mipLevels;
2936 		1u,																	//	deUint32			arraySize;
2937 		VK_SAMPLE_COUNT_1_BIT,												//	deUint32			samples;
2938 		VK_IMAGE_TILING_OPTIMAL,											//	VkImageTiling		tiling;
2939 		getMatchingImageUsageFlags(resource.getDescriptorType()),			//	VkImageUsageFlags	usage;
2940 		VK_SHARING_MODE_EXCLUSIVE,											//	VkSharingMode		sharingMode;
2941 		1u,																	//	deUint32			queueFamilyCount;
2942 		&queueFamilyIndex,													//	const deUint32*		pQueueFamilyIndices;
2943 		VK_IMAGE_LAYOUT_UNDEFINED											//	VkImageLayout		initialLayout;
2944 	};
2945 
2946 	return createImage(vk, vkDevice, &resourceImageParams);
2947 }
2948 
copyBufferToImage(Context & context,const DeviceInterface & vk,const VkDevice & device,const VkQueue & queue,VkCommandPool cmdPool,VkCommandBuffer cmdBuffer,VkBuffer buffer,VkImage image,VkImageAspectFlags aspect)2949 void copyBufferToImage (Context& context, const DeviceInterface& vk, const VkDevice& device, const VkQueue& queue, VkCommandPool cmdPool, VkCommandBuffer cmdBuffer, VkBuffer buffer, VkImage image, VkImageAspectFlags aspect)
2950 {
2951 	const VkBufferImageCopy			copyRegion			=
2952 	{
2953 		0u,												// VkDeviceSize				bufferOffset;
2954 		0u,												// deUint32					bufferRowLength;
2955 		0u,												// deUint32					bufferImageHeight;
2956 		{
2957 			aspect,											// VkImageAspectFlags		aspect;
2958 			0u,												// deUint32					mipLevel;
2959 			0u,												// deUint32					baseArrayLayer;
2960 			1u,												// deUint32					layerCount;
2961 		},												// VkImageSubresourceLayers	imageSubresource;
2962 		{ 0, 0, 0 },									// VkOffset3D				imageOffset;
2963 		{ 8, 8, 1 }										// VkExtent3D				imageExtent;
2964 	};
2965 
2966 	// Copy buffer to image
2967 	beginCommandBuffer(vk, cmdBuffer);
2968 
2969 	copyBufferToImage(vk, cmdBuffer, buffer, VK_WHOLE_SIZE, vector<VkBufferImageCopy>(1, copyRegion), aspect, 1u, 1u, image, VK_IMAGE_LAYOUT_GENERAL, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
2970 
2971 	endCommandBuffer(vk, cmdBuffer);
2972 
2973 	submitCommandsAndWait(vk, device, queue, cmdBuffer);
2974 	context.resetCommandPoolForVKSC(device, cmdPool);
2975 }
2976 
getImageAspectFlags(VkFormat format)2977 VkImageAspectFlags getImageAspectFlags (VkFormat format)
2978 {
2979 	const tcu::TextureFormat::ChannelOrder	channelOrder	= vk::mapVkFormat(format).order;
2980 	VkImageAspectFlags						aspectFlags		= (VkImageAspectFlags)0u;
2981 
2982 	if (tcu::hasDepthComponent(channelOrder))
2983 		aspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
2984 
2985 	if (tcu::hasStencilComponent(channelOrder))
2986 		aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
2987 
2988 	if (!aspectFlags)
2989 		aspectFlags |= VK_IMAGE_ASPECT_COLOR_BIT;
2990 
2991 	return aspectFlags;
2992 }
2993 
runAndVerifyUnusedVariablePipeline(Context & context,UnusedVariableContext unusedVariableContext)2994 TestStatus runAndVerifyUnusedVariablePipeline (Context &context, UnusedVariableContext unusedVariableContext)
2995 {
2996 	return runAndVerifyDefaultPipeline(context, unusedVariableContext.instanceContext);
2997 }
2998 
runAndVerifyDefaultPipeline(Context & context,InstanceContext instance)2999 TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance)
3000 {
3001 	if (getMinRequiredVulkanVersion(instance.resources.spirvVersion) > context.getUsedApiVersion())
3002 	{
3003 		TCU_THROW(NotSupportedError, string("Vulkan higher than or equal to " + getVulkanName(getMinRequiredVulkanVersion(instance.resources.spirvVersion)) + " is required for this test to run").c_str());
3004 	}
3005 
3006 	const DeviceInterface&						vk						= context.getDeviceInterface();
3007 	const InstanceInterface&					vkInstance				= context.getInstanceInterface();
3008 	const VkPhysicalDevice						vkPhysicalDevice		= context.getPhysicalDevice();
3009 	const deUint32								queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
3010 	const VkQueue								queue					= context.getUniversalQueue();
3011 	const VkDevice&								device					= context.getDevice();
3012 	Allocator&									allocator				= context.getDefaultAllocator();
3013 	vector<ModuleHandleSp>						modules;
3014 	map<VkShaderStageFlagBits, VkShaderModule>	moduleByStage;
3015 	const deUint32								fullRenderSize			= 256;
3016 	const deUint32								quarterRenderSize		= 64;
3017 	const tcu::UVec2							renderSize				(fullRenderSize, fullRenderSize);
3018 	const int									testSpecificSeed		= 31354125;
3019 	const int									seed					= context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed;
3020 	bool										supportsGeometry		= false;
3021 	bool										supportsTessellation	= false;
3022 	bool										hasGeometry				= false;
3023 	bool										hasTessellation			= false;
3024 	const bool									hasPushConstants		= !instance.pushConstants.empty();
3025 	const deUint32								numInResources			= static_cast<deUint32>(instance.resources.inputs.size());
3026 	const deUint32								numOutResources			= static_cast<deUint32>(instance.resources.outputs.size());
3027 	const deUint32								numResources			= numInResources + numOutResources;
3028 	const bool									needInterface			= !instance.interfaces.empty();
3029 	const VkPhysicalDeviceFeatures&				features				= context.getDeviceFeatures();
3030 	const Vec4									defaulClearColor		(0.125f, 0.25f, 0.75f, 1.0f);
3031 	bool										splitRenderArea			= instance.splitRenderArea;
3032 
3033 	const deUint32								renderDimension			= splitRenderArea ? quarterRenderSize : fullRenderSize;
3034 	const int									numRenderSegments		= splitRenderArea ? 4 : 1;
3035 
3036 	supportsGeometry		= features.geometryShader == VK_TRUE;
3037 	supportsTessellation	= features.tessellationShader == VK_TRUE;
3038 	hasGeometry				= (instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT);
3039 	hasTessellation			= (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) ||
3040 								(instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3041 
3042 	if (hasGeometry && !supportsGeometry)
3043 	{
3044 		TCU_THROW(NotSupportedError, "Geometry not supported");
3045 	}
3046 
3047 	if (hasTessellation && !supportsTessellation)
3048 	{
3049 		TCU_THROW(NotSupportedError, "Tessellation not supported");
3050 	}
3051 
3052 	// Check all required extensions are supported
3053 	for (std::vector<std::string>::const_iterator i = instance.requiredDeviceExtensions.begin(); i != instance.requiredDeviceExtensions.end(); ++i)
3054 	{
3055 		if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), *i))
3056 			TCU_THROW(NotSupportedError, (std::string("Extension not supported: ") + *i).c_str());
3057 	}
3058 
3059 #ifndef CTS_USES_VULKANSC
3060 	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
3061 		!context.getPortabilitySubsetFeatures().mutableComparisonSamplers)
3062 	{
3063 		// In portability when mutableComparisonSamplers is false then
3064 		// VkSamplerCreateInfo can't have compareEnable set to true
3065 		for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
3066 		{
3067 			const Resource&	resource	= instance.resources.inputs[inputNdx];
3068 			const bool		hasSampler	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
3069 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLER) ||
3070 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3071 			if (hasSampler &&
3072 				tcu::hasDepthComponent(vk::mapVkFormat(instance.resources.inputFormat).order))
3073 			{
3074 				TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: mutableComparisonSamplers are not supported by this implementation");
3075 			}
3076 		}
3077 	}
3078 #endif // CTS_USES_VULKANSC
3079 
3080 	{
3081 		VulkanFeatures localRequired = instance.requestedFeatures;
3082 
3083 		const VkShaderStageFlags		vertexPipelineStoresAndAtomicsAffected	= vk::VK_SHADER_STAGE_VERTEX_BIT
3084 																				| vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT
3085 																				| vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT
3086 																				| vk::VK_SHADER_STAGE_GEOMETRY_BIT;
3087 
3088 		// reset fragment stores and atomics feature requirement
3089 		if ((localRequired.coreFeatures.fragmentStoresAndAtomics != DE_FALSE) &&
3090 			(instance.customizedStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) == 0)
3091 		{
3092 			localRequired.coreFeatures.fragmentStoresAndAtomics = DE_FALSE;
3093 		}
3094 
3095 		// reset vertex pipeline stores and atomics feature requirement
3096 		if (localRequired.coreFeatures.vertexPipelineStoresAndAtomics != DE_FALSE &&
3097 			(instance.customizedStages & vertexPipelineStoresAndAtomicsAffected) == 0)
3098 		{
3099 			localRequired.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE;
3100 		}
3101 
3102 		const char* unsupportedFeature = DE_NULL;
3103 		if (!isVulkanFeaturesSupported(context, localRequired, &unsupportedFeature))
3104 			TCU_THROW(NotSupportedError, std::string("At least following requested feature not supported: ") + unsupportedFeature);
3105 	}
3106 
3107 	// Check Interface Input/Output formats are supported
3108 	if (needInterface)
3109 	{
3110 		VkFormatProperties formatProperties;
3111 		vkInstance.getPhysicalDeviceFormatProperties(vkPhysicalDevice, instance.interfaces.getInputType().getVkFormat(), &formatProperties);
3112 		if ((formatProperties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0)
3113 		{
3114 			std::string	error				= "Interface Input format (";
3115 			const std::string formatName	= getFormatName(instance.interfaces.getInputType().getVkFormat());
3116 			error += formatName + ") not supported";
3117 			TCU_THROW(NotSupportedError, error.c_str());
3118 		}
3119 
3120 		vkInstance.getPhysicalDeviceFormatProperties(vkPhysicalDevice, instance.interfaces.getOutputType().getVkFormat(), &formatProperties);
3121 		if (((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0) ||
3122 			((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0))
3123 		{
3124 			std::string	error				= "Interface Output format (";
3125 			const std::string formatName	= getFormatName(instance.interfaces.getInputType().getVkFormat());
3126 			error += formatName + ") not supported";
3127 			TCU_THROW(NotSupportedError, error.c_str());
3128 		}
3129 	}
3130 
3131 	de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4);
3132 	de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4);
3133 	const Vec4								vertexData[]			=
3134 	{
3135 		// Upper left corner:
3136 		Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),	//1
3137 		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),	//2
3138 		Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(),	//3
3139 
3140 		// Upper right corner:
3141 		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),	//4
3142 		Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),	//5
3143 		Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(),	//6
3144 
3145 		// Lower left corner:
3146 		Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(),	//7
3147 		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),	//8
3148 		Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),	//9
3149 
3150 		// Lower right corner:
3151 		Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(),	//10
3152 		Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(),	//11
3153 		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(),	//12
3154 
3155 		// The rest is used only renderFullSquare specified. Fills area already filled with clear color
3156 		// Left 1
3157 		Vec4(-1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor,					//3
3158 		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//2
3159 		Vec4(-1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor,					//7
3160 
3161 		// Left 2
3162 		Vec4(-1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor,					//7
3163 		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//2
3164 		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//8
3165 
3166 		// Left-Center
3167 		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//8
3168 		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//2
3169 		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//4
3170 
3171 		// Right-Center
3172 		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//4
3173 		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//12
3174 		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//8
3175 
3176 		// Right 2
3177 		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//4
3178 		Vec4(+1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor,					//6
3179 		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//12
3180 
3181 		// Right 1
3182 		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//12
3183 		Vec4(+1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor,					//6
3184 		Vec4(+1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor,					//10
3185 	};
3186 
3187 	const size_t							singleVertexDataSize	= 2 * sizeof(Vec4);
3188 	const size_t							vertexCount				= instance.renderFullSquare ? sizeof(vertexData) / singleVertexDataSize : 4*3;
3189 	const size_t							vertexDataSize			= vertexCount * singleVertexDataSize;
3190 
3191 	Move<VkBuffer>							vertexInputBuffer;
3192 	de::MovePtr<Allocation>					vertexInputMemory;
3193 	Move<VkBuffer>							fragOutputBuffer;
3194 	de::MovePtr<Allocation>					fragOutputMemory;
3195 	Move<VkImage>							fragOutputImage;
3196 	de::MovePtr<Allocation>					fragOutputImageMemory;
3197 	Move<VkImageView>						fragOutputImageView;
3198 
3199 	const VkBufferCreateInfo				vertexBufferParams		=
3200 	{
3201 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	//	VkStructureType		sType;
3202 		DE_NULL,								//	const void*			pNext;
3203 		0u,										//	VkBufferCreateFlags	flags;
3204 		(VkDeviceSize)vertexDataSize,			//	VkDeviceSize		size;
3205 		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,		//	VkBufferUsageFlags	usage;
3206 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode		sharingMode;
3207 		1u,										//	deUint32			queueFamilyCount;
3208 		&queueFamilyIndex,						//	const deUint32*		pQueueFamilyIndices;
3209 	};
3210 	const Unique<VkBuffer>					vertexBuffer			(createBuffer(vk, device, &vertexBufferParams));
3211 	const UniquePtr<Allocation>				vertexBufferMemory		(allocator.allocate(getBufferMemoryRequirements(vk, device, *vertexBuffer), MemoryRequirement::HostVisible));
3212 
3213 	VK_CHECK(vk.bindBufferMemory(device, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
3214 
3215 	const VkDeviceSize						imageSizeBytes			= (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y());
3216 	const VkBufferCreateInfo				readImageBufferParams	=
3217 	{
3218 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
3219 		DE_NULL,									//	const void*			pNext;
3220 		0u,											//	VkBufferCreateFlags	flags;
3221 		imageSizeBytes,								//	VkDeviceSize		size;
3222 		VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//	VkBufferUsageFlags	usage;
3223 		VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
3224 		1u,											//	deUint32			queueFamilyCount;
3225 		&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
3226 	};
3227 	const Unique<VkBuffer>					readImageBuffer			(createBuffer(vk, device, &readImageBufferParams));
3228 	const UniquePtr<Allocation>				readImageBufferMemory	(allocator.allocate(getBufferMemoryRequirements(vk, device, *readImageBuffer), MemoryRequirement::HostVisible));
3229 
3230 	VK_CHECK(vk.bindBufferMemory(device, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
3231 
3232 	VkImageCreateInfo						imageParams				=
3233 	{
3234 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									//	VkStructureType		sType;
3235 		DE_NULL,																//	const void*			pNext;
3236 		0u,																		//	VkImageCreateFlags	flags;
3237 		VK_IMAGE_TYPE_2D,														//	VkImageType			imageType;
3238 		VK_FORMAT_R8G8B8A8_UNORM,												//	VkFormat			format;
3239 		{ renderSize.x(), renderSize.y(), 1 },									//	VkExtent3D			extent;
3240 		1u,																		//	deUint32			mipLevels;
3241 		1u,																		//	deUint32			arraySize;
3242 		VK_SAMPLE_COUNT_1_BIT,													//	deUint32			samples;
3243 		VK_IMAGE_TILING_OPTIMAL,												//	VkImageTiling		tiling;
3244 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	//	VkImageUsageFlags	usage;
3245 		VK_SHARING_MODE_EXCLUSIVE,												//	VkSharingMode		sharingMode;
3246 		1u,																		//	deUint32			queueFamilyCount;
3247 		&queueFamilyIndex,														//	const deUint32*		pQueueFamilyIndices;
3248 		VK_IMAGE_LAYOUT_UNDEFINED,												//	VkImageLayout		initialLayout;
3249 	};
3250 
3251 	const Unique<VkImage>					image					(createImage(vk, device, &imageParams));
3252 	const UniquePtr<Allocation>				imageMemory				(allocator.allocate(getImageMemoryRequirements(vk, device, *image), MemoryRequirement::Any));
3253 
3254 	VK_CHECK(vk.bindImageMemory(device, *image, imageMemory->getMemory(), imageMemory->getOffset()));
3255 
3256 	if (needInterface)
3257 	{
3258 		// The pipeline renders four triangles, each with three vertexes.
3259 		// Test instantialization only provides four data points, each
3260 		// for one triangle. So we need allocate space of three times of
3261 		// input buffer's size.
3262 		vector<deUint8>							inputBufferBytes;
3263 		instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
3264 
3265 		const deUint32							inputNumBytes			= deUint32(inputBufferBytes.size() * 3);
3266 		// Create an additional buffer and backing memory for one input variable.
3267 		const VkBufferCreateInfo				vertexInputParams		=
3268 		{
3269 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
3270 			DE_NULL,									//	const void*			pNext;
3271 			0u,											//	VkBufferCreateFlags	flags;
3272 			inputNumBytes,								//	VkDeviceSize		size;
3273 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			//	VkBufferUsageFlags	usage;
3274 			VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
3275 			1u,											//	deUint32			queueFamilyCount;
3276 			&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
3277 		};
3278 
3279 		vertexInputBuffer = createBuffer(vk, device, &vertexInputParams);
3280 		vertexInputMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *vertexInputBuffer), MemoryRequirement::HostVisible);
3281 		VK_CHECK(vk.bindBufferMemory(device, *vertexInputBuffer, vertexInputMemory->getMemory(), vertexInputMemory->getOffset()));
3282 
3283 		// Create an additional buffer and backing memory for an output variable.
3284 		const VkDeviceSize						fragOutputImgSize		= (VkDeviceSize)(instance.interfaces.getOutputType().getNumBytes() * renderSize.x() * renderSize.y());
3285 		const VkBufferCreateInfo				fragOutputParams		=
3286 		{
3287 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
3288 			DE_NULL,									//	const void*			pNext;
3289 			0u,											//	VkBufferCreateFlags	flags;
3290 			fragOutputImgSize,							//	VkDeviceSize		size;
3291 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//	VkBufferUsageFlags	usage;
3292 			VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
3293 			1u,											//	deUint32			queueFamilyCount;
3294 			&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
3295 		};
3296 		fragOutputBuffer = createBuffer(vk, device, &fragOutputParams);
3297 		fragOutputMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *fragOutputBuffer), MemoryRequirement::HostVisible);
3298 		VK_CHECK(vk.bindBufferMemory(device, *fragOutputBuffer, fragOutputMemory->getMemory(), fragOutputMemory->getOffset()));
3299 
3300 		// Create an additional image and backing memory for attachment.
3301 		// Reuse the previous imageParams since we only need to change the image format.
3302 		imageParams.format		= instance.interfaces.getOutputType().getVkFormat();
3303 
3304 		// Check the usage bits on the given image format are supported.
3305 		requireFormatUsageSupport(vkInstance, vkPhysicalDevice, imageParams.format, imageParams.tiling, imageParams.usage);
3306 
3307 		fragOutputImage			= createImage(vk, device, &imageParams);
3308 		fragOutputImageMemory	= allocator.allocate(getImageMemoryRequirements(vk, device, *fragOutputImage), MemoryRequirement::Any);
3309 
3310 		VK_CHECK(vk.bindImageMemory(device, *fragOutputImage, fragOutputImageMemory->getMemory(), fragOutputImageMemory->getOffset()));
3311 	}
3312 
3313 	vector<VkAttachmentDescription>			colorAttDescs;
3314 	vector<VkAttachmentReference>			colorAttRefs;
3315 	{
3316 		const VkAttachmentDescription		attDesc					=
3317 		{
3318 			0u,												//	VkAttachmentDescriptionFlags	flags;
3319 			VK_FORMAT_R8G8B8A8_UNORM,						//	VkFormat						format;
3320 			VK_SAMPLE_COUNT_1_BIT,							//	deUint32						samples;
3321 			VK_ATTACHMENT_LOAD_OP_CLEAR,					//	VkAttachmentLoadOp				loadOp;
3322 			VK_ATTACHMENT_STORE_OP_STORE,					//	VkAttachmentStoreOp				storeOp;
3323 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,				//	VkAttachmentLoadOp				stencilLoadOp;
3324 			VK_ATTACHMENT_STORE_OP_DONT_CARE,				//	VkAttachmentStoreOp				stencilStoreOp;
3325 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout					initialLayout;
3326 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout					finalLayout;
3327 		};
3328 		colorAttDescs.push_back(attDesc);
3329 
3330 		const VkAttachmentReference			attRef					=
3331 		{
3332 			0u,												//	deUint32		attachment;
3333 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout	layout;
3334 		};
3335 		colorAttRefs.push_back(attRef);
3336 	}
3337 
3338 	if (needInterface)
3339 	{
3340 		const VkAttachmentDescription		attDesc					=
3341 		{
3342 			0u,													//	VkAttachmentDescriptionFlags	flags;
3343 			instance.interfaces.getOutputType().getVkFormat(),	//	VkFormat						format;
3344 			VK_SAMPLE_COUNT_1_BIT,								//	deUint32						samples;
3345 			VK_ATTACHMENT_LOAD_OP_CLEAR,						//	VkAttachmentLoadOp				loadOp;
3346 			VK_ATTACHMENT_STORE_OP_STORE,						//	VkAttachmentStoreOp				storeOp;
3347 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					//	VkAttachmentLoadOp				stencilLoadOp;
3348 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					//	VkAttachmentStoreOp				stencilStoreOp;
3349 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			//	VkImageLayout					initialLayout;
3350 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			//	VkImageLayout					finalLayout;
3351 		};
3352 		colorAttDescs.push_back(attDesc);
3353 
3354 		const VkAttachmentReference			attRef					=
3355 		{
3356 			1u,												//	deUint32		attachment;
3357 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout	layout;
3358 		};
3359 		colorAttRefs.push_back(attRef);
3360 	}
3361 
3362 	VkSubpassDescription					subpassDesc				=
3363 	{
3364 		0u,												//	VkSubpassDescriptionFlags		flags;
3365 		VK_PIPELINE_BIND_POINT_GRAPHICS,				//	VkPipelineBindPoint				pipelineBindPoint;
3366 		0u,												//	deUint32						inputCount;
3367 		DE_NULL,										//	const VkAttachmentReference*	pInputAttachments;
3368 		1u,												//	deUint32						colorCount;
3369 		colorAttRefs.data(),							//	const VkAttachmentReference*	pColorAttachments;
3370 		DE_NULL,										//	const VkAttachmentReference*	pResolveAttachments;
3371 		DE_NULL,										//	const VkAttachmentReference*	pDepthStencilAttachment;
3372 		0u,												//	deUint32						preserveCount;
3373 		DE_NULL,										//	const VkAttachmentReference*	pPreserveAttachments;
3374 
3375 	};
3376 	VkRenderPassCreateInfo					renderPassParams		=
3377 	{
3378 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,		//	VkStructureType					sType;
3379 		DE_NULL,										//	const void*						pNext;
3380 		(VkRenderPassCreateFlags)0,
3381 		1u,												//	deUint32						attachmentCount;
3382 		colorAttDescs.data(),							//	const VkAttachmentDescription*	pAttachments;
3383 		1u,												//	deUint32						subpassCount;
3384 		&subpassDesc,									//	const VkSubpassDescription*		pSubpasses;
3385 		0u,												//	deUint32						dependencyCount;
3386 		DE_NULL,										//	const VkSubpassDependency*		pDependencies;
3387 	};
3388 
3389 	if (needInterface)
3390 	{
3391 		subpassDesc.colorAttachmentCount += 1;
3392 		renderPassParams.attachmentCount += 1;
3393 	}
3394 
3395 	const Unique<VkRenderPass>				renderPass				(createRenderPass(vk, device, &renderPassParams));
3396 
3397 	const VkImageViewCreateInfo				colorAttViewParams		=
3398 	{
3399 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		//	VkStructureType				sType;
3400 		DE_NULL,										//	const void*					pNext;
3401 		0u,												//	VkImageViewCreateFlags		flags;
3402 		*image,											//	VkImage						image;
3403 		VK_IMAGE_VIEW_TYPE_2D,							//	VkImageViewType				viewType;
3404 		VK_FORMAT_R8G8B8A8_UNORM,						//	VkFormat					format;
3405 		{
3406 			VK_COMPONENT_SWIZZLE_R,
3407 			VK_COMPONENT_SWIZZLE_G,
3408 			VK_COMPONENT_SWIZZLE_B,
3409 			VK_COMPONENT_SWIZZLE_A
3410 		},												//	VkChannelMapping			channels;
3411 		{
3412 			VK_IMAGE_ASPECT_COLOR_BIT,						//	VkImageAspectFlags	aspectMask;
3413 			0u,												//	deUint32			baseMipLevel;
3414 			1u,												//	deUint32			mipLevels;
3415 			0u,												//	deUint32			baseArrayLayer;
3416 			1u,												//	deUint32			arraySize;
3417 		},												//	VkImageSubresourceRange		subresourceRange;
3418 	};
3419 	const Unique<VkImageView>				colorAttView			(createImageView(vk, device, &colorAttViewParams));
3420 	const VkImageAspectFlags				inputImageAspect		= getImageAspectFlags(instance.resources.inputFormat);
3421 
3422 	vector<VkImageView>						attViews;
3423 	attViews.push_back(*colorAttView);
3424 
3425 	// Handle resources requested by the test instantiation.
3426 	// These variables should be placed out of the following if block to avoid deallocation after out of scope.
3427 	vector<AllocationSp>					inResourceMemories;
3428 	vector<AllocationSp>					outResourceMemories;
3429 	vector<BufferHandleSp>					inResourceBuffers;
3430 	vector<BufferHandleSp>					outResourceBuffers;
3431 	vector<ImageHandleSp>					inResourceImages;
3432 	vector<ImageViewHandleSp>				inResourceImageViews;
3433 	vector<SamplerHandleSp>					inResourceSamplers;
3434 	Move<VkDescriptorPool>					descriptorPool;
3435 	Move<VkDescriptorSetLayout>				setLayout;
3436 	VkDescriptorSetLayout					rawSetLayout			= DE_NULL;
3437 	VkDescriptorSet							rawSet					= DE_NULL;
3438 
3439 	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
3440 
3441 	// Command buffer
3442 	const Unique<VkCommandBuffer>			cmdBuf					(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3443 
3444 	if (numResources != 0)
3445 	{
3446 		vector<VkDescriptorSetLayoutBinding>	setLayoutBindings;
3447 		vector<VkDescriptorPoolSize>			poolSizes;
3448 
3449 		setLayoutBindings.reserve(numResources);
3450 		poolSizes.reserve(numResources);
3451 
3452 		// Process all input resources.
3453 		for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
3454 		{
3455 			const Resource&	resource	= instance.resources.inputs[inputNdx];
3456 
3457 			const bool		hasImage	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)	||
3458 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3459 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3460 
3461 			const bool		hasSampler	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3462 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLER)			||
3463 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3464 
3465 			// Resource is a buffer
3466 			if (!hasImage && !hasSampler)
3467 			{
3468 				Move<VkBuffer>					resourceBuffer			= createBufferForResource(vk, device, resource, queueFamilyIndex);
3469 				de::MovePtr<Allocation>			resourceMemory			= allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3470 
3471 				VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3472 
3473 				// Copy data to memory.
3474 				{
3475 					vector<deUint8>					resourceBytes;
3476 					resource.getBytes(resourceBytes);
3477 
3478 					deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
3479 					flushAlloc(vk, device, *resourceMemory);
3480 				}
3481 
3482 				inResourceMemories.push_back(AllocationSp(resourceMemory.release()));
3483 				inResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
3484 			}
3485 			// Resource is an image
3486 			else if (hasImage)
3487 			{
3488 				Move<VkBuffer>					resourceBuffer			= createBufferForResource(vk, device, resource, queueFamilyIndex);
3489 				de::MovePtr<Allocation>			resourceMemory			= allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3490 
3491 				VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3492 
3493 				// Copy data to memory.
3494 				{
3495 					vector<deUint8>					resourceBytes;
3496 					resource.getBytes(resourceBytes);
3497 
3498 					deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
3499 					flushAlloc(vk, device, *resourceMemory);
3500 				}
3501 
3502 				Move<VkImage>					resourceImage			= createImageForResource(vk, device, resource, instance.resources.inputFormat, queueFamilyIndex);
3503 				de::MovePtr<Allocation>			resourceImageMemory		= allocator.allocate(getImageMemoryRequirements(vk, device, *resourceImage), MemoryRequirement::Any);
3504 
3505 				VK_CHECK(vk.bindImageMemory(device, *resourceImage, resourceImageMemory->getMemory(), resourceImageMemory->getOffset()));
3506 
3507 				copyBufferToImage(context, vk, device, queue, *cmdPool, *cmdBuf, resourceBuffer.get(), resourceImage.get(), inputImageAspect);
3508 
3509 				inResourceMemories.push_back(AllocationSp(resourceImageMemory.release()));
3510 				inResourceImages.push_back(ImageHandleSp(new ImageHandleUp(resourceImage)));
3511 			}
3512 
3513 			// Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool.
3514 			const VkDescriptorSetLayoutBinding	binding				=
3515 			{
3516 				inputNdx,											// binding
3517 				resource.getDescriptorType(),						// descriptorType
3518 				1u,													// descriptorCount
3519 				VK_SHADER_STAGE_ALL_GRAPHICS,						// stageFlags
3520 				DE_NULL,											// pImmutableSamplers
3521 			};
3522 			setLayoutBindings.push_back(binding);
3523 
3524 			// Note: the following code doesn't check and unify descriptors of the same type.
3525 			const VkDescriptorPoolSize		poolSize				=
3526 			{
3527 				resource.getDescriptorType(),						// type
3528 				1u,													// descriptorCount
3529 			};
3530 			poolSizes.push_back(poolSize);
3531 		}
3532 
3533 		// Process all output resources.
3534 		for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
3535 		{
3536 			const Resource&					resource				= instance.resources.outputs[outputNdx];
3537 			// Create buffer and allocate memory.
3538 			Move<VkBuffer>					resourceBuffer			= createBufferForResource(vk, device, resource, queueFamilyIndex);
3539 			de::MovePtr<Allocation>			resourceMemory			= allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3540 			vector<deUint8>					resourceBytes;
3541 
3542 			VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3543 
3544 			// Fill memory with all ones.
3545 			resource.getBytes(resourceBytes);
3546 			deMemset((deUint8*)resourceMemory->getHostPtr(), 0xff, resourceBytes.size());
3547 			flushAlloc(vk, device, *resourceMemory);
3548 
3549 			outResourceMemories.push_back(AllocationSp(resourceMemory.release()));
3550 			outResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
3551 
3552 			// Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool.
3553 			const VkDescriptorSetLayoutBinding	binding				=
3554 			{
3555 				numInResources  + outputNdx,						// binding
3556 				resource.getDescriptorType(),						// descriptorType
3557 				1u,													// descriptorCount
3558 				VK_SHADER_STAGE_ALL_GRAPHICS,						// stageFlags
3559 				DE_NULL,											// pImmutableSamplers
3560 			};
3561 			setLayoutBindings.push_back(binding);
3562 
3563 			// Note: the following code doesn't check and unify descriptors of the same type.
3564 			const VkDescriptorPoolSize		poolSize				=
3565 			{
3566 				resource.getDescriptorType(),						// type
3567 				1u,													// descriptorCount
3568 			};
3569 			poolSizes.push_back(poolSize);
3570 		}
3571 
3572 		// Create descriptor set layout, descriptor pool, and allocate descriptor set.
3573 		const VkDescriptorSetLayoutCreateInfo	setLayoutParams		=
3574 		{
3575 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
3576 			DE_NULL,												// pNext
3577 			(VkDescriptorSetLayoutCreateFlags)0,					// flags
3578 			numResources,											// bindingCount
3579 			setLayoutBindings.data(),								// pBindings
3580 		};
3581 		setLayout													= createDescriptorSetLayout(vk, device, &setLayoutParams);
3582 		rawSetLayout												= *setLayout;
3583 
3584 		const VkDescriptorPoolCreateInfo		poolParams			=
3585 		{
3586 			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,			// sType
3587 			DE_NULL,												// pNext
3588 			(VkDescriptorPoolCreateFlags)0,							// flags
3589 			1u,														// maxSets
3590 			numResources,											// poolSizeCount
3591 			poolSizes.data(),										// pPoolSizes
3592 		};
3593 		descriptorPool												= createDescriptorPool(vk, device, &poolParams);
3594 
3595 		const VkDescriptorSetAllocateInfo		setAllocParams		=
3596 		{
3597 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			// sType
3598 			DE_NULL,												// pNext
3599 			*descriptorPool,										// descriptorPool
3600 			1u,														// descriptorSetCount
3601 			&rawSetLayout,											// pSetLayouts
3602 		};
3603 		VK_CHECK(vk.allocateDescriptorSets(device, &setAllocParams, &rawSet));
3604 
3605 		// Update descriptor set.
3606 		vector<VkWriteDescriptorSet>			writeSpecs;
3607 		vector<VkDescriptorBufferInfo>			dBufferInfos;
3608 		vector<VkDescriptorImageInfo>			dImageInfos;
3609 
3610 		writeSpecs.reserve(numResources);
3611 		dBufferInfos.reserve(numResources);
3612 		dImageInfos.reserve(numResources);
3613 
3614 		deUint32								imgResourceNdx		= 0u;
3615 		deUint32								bufResourceNdx		= 0u;
3616 
3617 		for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
3618 		{
3619 			const Resource&	resource	= instance.resources.inputs[inputNdx];
3620 
3621 			const bool		hasImage	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)	||
3622 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3623 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3624 
3625 			const bool		hasSampler	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3626 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLER)			||
3627 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3628 
3629 			// Create image view and sampler
3630 			if (hasImage || hasSampler)
3631 			{
3632 				if (resource.getDescriptorType() != VK_DESCRIPTOR_TYPE_SAMPLER)
3633 				{
3634 					const VkImageViewCreateInfo	imgViewParams	=
3635 					{
3636 						VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	//	VkStructureType				sType;
3637 						DE_NULL,									//	const void*					pNext;
3638 						0u,											//	VkImageViewCreateFlags		flags;
3639 						**inResourceImages[imgResourceNdx++],		//	VkImage						image;
3640 						VK_IMAGE_VIEW_TYPE_2D,						//	VkImageViewType				viewType;
3641 						instance.resources.inputFormat,				//	VkFormat					format;
3642 						{
3643 							VK_COMPONENT_SWIZZLE_R,
3644 							VK_COMPONENT_SWIZZLE_G,
3645 							VK_COMPONENT_SWIZZLE_B,
3646 							VK_COMPONENT_SWIZZLE_A
3647 						},											//	VkComponentMapping			channels;
3648 						{
3649 							inputImageAspect,	//	VkImageAspectFlags	aspectMask;
3650 							0u,					//	deUint32			baseMipLevel;
3651 							1u,					//	deUint32			mipLevels;
3652 							0u,					//	deUint32			baseArrayLayer;
3653 							1u,					//	deUint32			arraySize;
3654 						},											//	VkImageSubresourceRange		subresourceRange;
3655 					};
3656 
3657 					Move<VkImageView>			imgView			(createImageView(vk, device, &imgViewParams));
3658 					inResourceImageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imgView)));
3659 				}
3660 
3661 				if (hasSampler)
3662 				{
3663 					const bool					hasDepthComponent	= tcu::hasDepthComponent(vk::mapVkFormat(instance.resources.inputFormat).order);
3664 					const VkSamplerCreateInfo	samplerParams
3665 					{
3666 						VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType			sType;
3667 						DE_NULL,									// const void*				pNext;
3668 						0,											// VkSamplerCreateFlags		flags;
3669 						VK_FILTER_NEAREST,							// VkFilter					magFilter:
3670 						VK_FILTER_NEAREST,							// VkFilter					minFilter;
3671 						VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode		mipmapMode;
3672 						VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeU;
3673 						VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeV;
3674 						VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeW;
3675 						0.0f,										// float					mipLodBias;
3676 						VK_FALSE,									// VkBool32					anistoropyEnable;
3677 						1.0f,										// float					maxAnisotropy;
3678 						(hasDepthComponent) ? VK_TRUE : VK_FALSE,	// VkBool32					compareEnable;
3679 						VK_COMPARE_OP_LESS,							// VkCompareOp				compareOp;
3680 						0.0f,										// float					minLod;
3681 						0.0f,										// float					maxLod;
3682 						VK_BORDER_COLOR_INT_OPAQUE_BLACK,			// VkBorderColor			borderColor;
3683 						VK_FALSE									// VkBool32					unnormalizedCoordinates;
3684 					};
3685 
3686 					Move<VkSampler>				sampler			(createSampler(vk, device, &samplerParams));
3687 					inResourceSamplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
3688 				}
3689 			}
3690 
3691 			// Create descriptor buffer and image infos
3692 			switch (resource.getDescriptorType())
3693 			{
3694 				case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
3695 				case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
3696 				{
3697 					const VkDescriptorBufferInfo	bufInfo	=
3698 					{
3699 						**inResourceBuffers[bufResourceNdx++],				// buffer
3700 						0,													// offset
3701 						VK_WHOLE_SIZE,										// size
3702 					};
3703 					dBufferInfos.push_back(bufInfo);
3704 					break;
3705 				}
3706 				case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
3707 				case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
3708 				{
3709 					const VkDescriptorImageInfo		imgInfo	=
3710 					{
3711 						DE_NULL,												// sampler
3712 						**inResourceImageViews.back(),							// imageView
3713 						VK_IMAGE_LAYOUT_GENERAL									// imageLayout
3714 					};
3715 					dImageInfos.push_back(imgInfo);
3716 					break;
3717 				}
3718 				case VK_DESCRIPTOR_TYPE_SAMPLER:
3719 				{
3720 					const VkDescriptorImageInfo		imgInfo	=
3721 					{
3722 						**inResourceSamplers.back(),							// sampler
3723 						DE_NULL,												// imageView
3724 						VK_IMAGE_LAYOUT_GENERAL									// imageLayout
3725 					};
3726 					dImageInfos.push_back(imgInfo);
3727 					break;
3728 				}
3729 				case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
3730 				{
3731 
3732 					const VkDescriptorImageInfo		imgInfo	=
3733 					{
3734 						**inResourceSamplers.back(),							// sampler
3735 						**inResourceImageViews.back(),							// imageView
3736 						VK_IMAGE_LAYOUT_GENERAL									// imageLayout
3737 					};
3738 					dImageInfos.push_back(imgInfo);
3739 					break;
3740 				}
3741 				default:
3742 					DE_FATAL("Not implemented");
3743 			}
3744 
3745 			const VkWriteDescriptorSet			writeSpec			= {
3746 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,							// sType
3747 				DE_NULL,														// pNext
3748 				rawSet,															// dstSet
3749 				inputNdx,														// binding
3750 				0,																// dstArrayElement
3751 				1u,																// descriptorCount
3752 				instance.resources.inputs[inputNdx].getDescriptorType(),		// descriptorType
3753 				( (hasImage | hasSampler)	? &dImageInfos.back()	: DE_NULL),	// pImageInfo
3754 				(!(hasImage | hasSampler)	? &dBufferInfos.back()	: DE_NULL),	// pBufferInfo
3755 				DE_NULL,														// pTexelBufferView
3756 			};
3757 			writeSpecs.push_back(writeSpec);
3758 		}
3759 
3760 		for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
3761 		{
3762 			const VkDescriptorBufferInfo		bufInfo				=
3763 			{
3764 				**outResourceBuffers[outputNdx],					// buffer
3765 				0,													// offset
3766 				VK_WHOLE_SIZE,										// size
3767 			};
3768 			dBufferInfos.push_back(bufInfo);
3769 
3770 			const VkWriteDescriptorSet			writeSpec			= {
3771 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,						// sType
3772 				DE_NULL,													// pNext
3773 				rawSet,														// dstSet
3774 				numInResources + outputNdx,									// binding
3775 				0,															// dstArrayElement
3776 				1u,															// descriptorCount
3777 				instance.resources.outputs[outputNdx].getDescriptorType(),	// descriptorType
3778 				DE_NULL,													// pImageInfo
3779 				&dBufferInfos.back(),										// pBufferInfo
3780 				DE_NULL,													// pTexelBufferView
3781 			};
3782 			writeSpecs.push_back(writeSpec);
3783 		}
3784 		vk.updateDescriptorSets(device, numResources, writeSpecs.data(), 0, DE_NULL);
3785 	}
3786 
3787 	// Pipeline layout
3788 	VkPipelineLayoutCreateInfo				pipelineLayoutParams	=
3789 	{
3790 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,			//	VkStructureType					sType;
3791 		DE_NULL,												//	const void*						pNext;
3792 		(VkPipelineLayoutCreateFlags)0,
3793 		0u,														//	deUint32						descriptorSetCount;
3794 		DE_NULL,												//	const VkDescriptorSetLayout*	pSetLayouts;
3795 		0u,														//	deUint32						pushConstantRangeCount;
3796 		DE_NULL,												//	const VkPushConstantRange*		pPushConstantRanges;
3797 	};
3798 
3799 	VkPushConstantRange						pushConstantRange		=
3800 	{
3801 		VK_SHADER_STAGE_ALL_GRAPHICS,							// VkShaderStageFlags    stageFlags;
3802 		0,														// uint32_t              offset;
3803 		0,														// uint32_t              size;
3804 	};
3805 	if (hasPushConstants)
3806 	{
3807 		vector<deUint8> pushConstantsBytes;
3808 		instance.pushConstants.getBuffer()->getBytes(pushConstantsBytes);
3809 
3810 		pushConstantRange.size						= static_cast<deUint32>(pushConstantsBytes.size());
3811 		pipelineLayoutParams.pushConstantRangeCount	= 1;
3812 		pipelineLayoutParams.pPushConstantRanges	= &pushConstantRange;
3813 	}
3814 	if (numResources != 0)
3815 	{
3816 		// Update pipeline layout with the descriptor set layout.
3817 		pipelineLayoutParams.setLayoutCount								= 1;
3818 		pipelineLayoutParams.pSetLayouts								= &rawSetLayout;
3819 	}
3820 	const Unique<VkPipelineLayout>			pipelineLayout			(createPipelineLayout(vk, device, &pipelineLayoutParams));
3821 
3822 	// Pipeline
3823 	vector<VkPipelineShaderStageCreateInfo>		shaderStageParams;
3824 	// We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline().
3825 	vector<vector<VkSpecializationMapEntry> >	specConstantEntries;
3826 	vector<VkSpecializationInfo>				specializationInfos;
3827 	if (DE_NULL != instance.resources.verifyBinary)
3828 	{
3829 		std::string shaderName;
3830 		switch(instance.customizedStages)
3831 		{
3832 		case	VK_SHADER_STAGE_VERTEX_BIT:
3833 			shaderName= "vert";
3834 			break;
3835 		case	VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
3836 			shaderName= "tessc";
3837 			break;
3838 		case	VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
3839 			shaderName= "tesse";
3840 			break;
3841 		case	VK_SHADER_STAGE_GEOMETRY_BIT:
3842 			shaderName= "geom";
3843 			break;
3844 		case	VK_SHADER_STAGE_FRAGMENT_BIT:
3845 			shaderName= "frag";
3846 			break;
3847 		default:
3848 			DE_ASSERT(0);
3849 			break;
3850 		}
3851 		const ProgramBinary& binary  = context.getBinaryCollection().get(shaderName);
3852 		if (!instance.resources.verifyBinary(binary))
3853 			return tcu::TestStatus::fail("Binary verification of SPIR-V in the test failed");
3854 
3855 	}
3856 	createPipelineShaderStages(vk, device, instance, context, modules, shaderStageParams);
3857 
3858 	// And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents.
3859 	specConstantEntries.reserve(shaderStageParams.size());
3860 	specializationInfos.reserve(shaderStageParams.size());
3861 
3862 	// Patch the specialization info field in PipelineShaderStageCreateInfos.
3863 	for (vector<VkPipelineShaderStageCreateInfo>::iterator stageInfo = shaderStageParams.begin(); stageInfo != shaderStageParams.end(); ++stageInfo)
3864 	{
3865 		const StageToSpecConstantMap::const_iterator stageIt = instance.specConstants.find(stageInfo->stage);
3866 
3867 		if (stageIt != instance.specConstants.end())
3868 		{
3869 			const size_t						numSpecConstants	= stageIt->second.getValuesCount();
3870 			vector<VkSpecializationMapEntry>	entries;
3871 			VkSpecializationInfo				specInfo;
3872 			size_t								offset				= 0;
3873 
3874 			entries.resize(numSpecConstants);
3875 
3876 			// Constant IDs are numbered sequentially starting from 0.
3877 			for (size_t ndx = 0; ndx < numSpecConstants; ++ndx)
3878 			{
3879 				const size_t valueSize	= stageIt->second.getValueSize(ndx);
3880 
3881 				entries[ndx].constantID	= (deUint32)ndx;
3882 				entries[ndx].offset		= static_cast<deUint32>(offset);
3883 				entries[ndx].size		= valueSize;
3884 
3885 				offset					+= valueSize;
3886 			}
3887 
3888 			specConstantEntries.push_back(entries);
3889 
3890 			specInfo.mapEntryCount	= (deUint32)numSpecConstants;
3891 			specInfo.pMapEntries	= specConstantEntries.back().data();
3892 			specInfo.dataSize		= offset;
3893 			specInfo.pData			= stageIt->second.getValuesBuffer();
3894 			specializationInfos.push_back(specInfo);
3895 
3896 			stageInfo->pSpecializationInfo = &specializationInfos.back();
3897 		}
3898 	}
3899 	const VkPipelineDepthStencilStateCreateInfo	depthStencilParams		=
3900 	{
3901 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	//	VkStructureType		sType;
3902 		DE_NULL,													//	const void*			pNext;
3903 		(VkPipelineDepthStencilStateCreateFlags)0,
3904 		DE_FALSE,													//	deUint32			depthTestEnable;
3905 		DE_FALSE,													//	deUint32			depthWriteEnable;
3906 		VK_COMPARE_OP_ALWAYS,										//	VkCompareOp			depthCompareOp;
3907 		DE_FALSE,													//	deUint32			depthBoundsTestEnable;
3908 		DE_FALSE,													//	deUint32			stencilTestEnable;
3909 		{
3910 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilFailOp;
3911 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilPassOp;
3912 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilDepthFailOp;
3913 			VK_COMPARE_OP_ALWAYS,										//	VkCompareOp	stencilCompareOp;
3914 			0u,															//	deUint32	stencilCompareMask;
3915 			0u,															//	deUint32	stencilWriteMask;
3916 			0u,															//	deUint32	stencilReference;
3917 		},															//	VkStencilOpState	front;
3918 		{
3919 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilFailOp;
3920 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilPassOp;
3921 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilDepthFailOp;
3922 			VK_COMPARE_OP_ALWAYS,										//	VkCompareOp	stencilCompareOp;
3923 			0u,															//	deUint32	stencilCompareMask;
3924 			0u,															//	deUint32	stencilWriteMask;
3925 			0u,															//	deUint32	stencilReference;
3926 		},															//	VkStencilOpState	back;
3927 		-1.0f,														//	float				minDepthBounds;
3928 		+1.0f,														//	float				maxDepthBounds;
3929 	};
3930 	const VkViewport							viewport0				= makeViewport(renderSize);
3931 	const VkRect2D								scissor0				= makeRect2D(0u, 0u);
3932 	const VkPipelineViewportStateCreateInfo		viewportParams			=
3933 	{
3934 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,		//	VkStructureType		sType;
3935 		DE_NULL,													//	const void*			pNext;
3936 		(VkPipelineViewportStateCreateFlags)0,
3937 		1u,															//	deUint32			viewportCount;
3938 		&viewport0,
3939 		1u,
3940 		&scissor0
3941 	};
3942 	const VkSampleMask							sampleMask				= ~0u;
3943 	const VkPipelineMultisampleStateCreateInfo	multisampleParams		=
3944 	{
3945 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType			sType;
3946 		DE_NULL,													//	const void*				pNext;
3947 		(VkPipelineMultisampleStateCreateFlags)0,
3948 		VK_SAMPLE_COUNT_1_BIT,										//	VkSampleCountFlagBits	rasterSamples;
3949 		DE_FALSE,													//	deUint32				sampleShadingEnable;
3950 		0.0f,														//	float					minSampleShading;
3951 		&sampleMask,												//	const VkSampleMask*		pSampleMask;
3952 		DE_FALSE,													//	VkBool32				alphaToCoverageEnable;
3953 		DE_FALSE,													//	VkBool32				alphaToOneEnable;
3954 	};
3955 	const VkPipelineRasterizationStateCreateInfo	rasterParams		=
3956 	{
3957 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType	sType;
3958 		DE_NULL,													//	const void*		pNext;
3959 		(VkPipelineRasterizationStateCreateFlags)0,
3960 		DE_FALSE,													//	deUint32		depthClampEnable;
3961 		DE_FALSE,													//	deUint32		rasterizerDiscardEnable;
3962 		VK_POLYGON_MODE_FILL,										//	VkFillMode		fillMode;
3963 		VK_CULL_MODE_NONE,											//	VkCullMode		cullMode;
3964 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							//	VkFrontFace		frontFace;
3965 		VK_FALSE,													//	VkBool32		depthBiasEnable;
3966 		0.0f,														//	float			depthBias;
3967 		0.0f,														//	float			depthBiasClamp;
3968 		0.0f,														//	float			slopeScaledDepthBias;
3969 		1.0f,														//	float			lineWidth;
3970 	};
3971 	const VkPrimitiveTopology topology = hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
3972 	const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyParams	=
3973 	{
3974 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	//	VkStructureType		sType;
3975 		DE_NULL,														//	const void*			pNext;
3976 		(VkPipelineInputAssemblyStateCreateFlags)0,
3977 		topology,														//	VkPrimitiveTopology	topology;
3978 		DE_FALSE,														//	deUint32			primitiveRestartEnable;
3979 	};
3980 
3981 	vector<VkVertexInputBindingDescription>		vertexBindings;
3982 	vector<VkVertexInputAttributeDescription>	vertexAttribs;
3983 
3984 	const VkVertexInputBindingDescription		vertexBinding0			=
3985 	{
3986 		0u,									// deUint32					binding;
3987 		deUint32(singleVertexDataSize),		// deUint32					strideInBytes;
3988 		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	stepRate;
3989 	};
3990 	vertexBindings.push_back(vertexBinding0);
3991 
3992 	{
3993 		VkVertexInputAttributeDescription		attr0					=
3994 		{
3995 			0u,									// deUint32	location;
3996 			0u,									// deUint32	binding;
3997 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
3998 			0u									// deUint32	offsetInBytes;
3999 		};
4000 		vertexAttribs.push_back(attr0);
4001 
4002 		VkVertexInputAttributeDescription		attr1					=
4003 		{
4004 			1u,									// deUint32	location;
4005 			0u,									// deUint32	binding;
4006 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
4007 			sizeof(Vec4),						// deUint32	offsetInBytes;
4008 		};
4009 		vertexAttribs.push_back(attr1);
4010 	}
4011 
4012 	// If the test instantiation has additional input/output interface variables, we need to create additional bindings.
4013 	// Right now we only support one additional input varible for the vertex stage, and that will be bound to binding #1
4014 	// with location #2.
4015 	if (needInterface)
4016 	{
4017 		// Portability requires stride to be multiply of minVertexInputBindingStrideAlignment
4018 		// this value is usually 4 and current tests meet this requirement but
4019 		// if this changes in future then this limit should be verified in checkSupport
4020 		const deUint32 stride = instance.interfaces.getInputType().getNumBytes();
4021 #ifndef CTS_USES_VULKANSC
4022 		if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
4023 			((stride % context.getPortabilitySubsetProperties().minVertexInputBindingStrideAlignment) != 0))
4024 		{
4025 			DE_FATAL("stride is not multiply of minVertexInputBindingStrideAlignment");
4026 		}
4027 #endif // CTS_USES_VULKANSC
4028 
4029 		const VkVertexInputBindingDescription	vertexBinding1			=
4030 		{
4031 			1u,													// deUint32					binding;
4032 			stride,												// deUint32					strideInBytes;
4033 			VK_VERTEX_INPUT_RATE_VERTEX							// VkVertexInputStepRate	stepRate;
4034 		};
4035 		vertexBindings.push_back(vertexBinding1);
4036 
4037 		VkVertexInputAttributeDescription		attr					=
4038 		{
4039 			2u,													// deUint32	location;
4040 			1u,													// deUint32	binding;
4041 			instance.interfaces.getInputType().getVkFormat(),	// VkFormat	format;
4042 			0,													// deUint32	offsetInBytes;
4043 		};
4044 		vertexAttribs.push_back(attr);
4045 	}
4046 
4047 	VkPipelineVertexInputStateCreateInfo		vertexInputStateParams	=
4048 	{
4049 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
4050 		DE_NULL,													//	const void*									pNext;
4051 		(VkPipelineVertexInputStateCreateFlags)0,
4052 		1u,															//	deUint32									bindingCount;
4053 		vertexBindings.data(),										//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
4054 		2u,															//	deUint32									attributeCount;
4055 		vertexAttribs.data(),										//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
4056 	};
4057 
4058 	if (needInterface)
4059 	{
4060 		vertexInputStateParams.vertexBindingDescriptionCount += 1;
4061 		vertexInputStateParams.vertexAttributeDescriptionCount += 1;
4062 	}
4063 
4064 	vector<VkPipelineColorBlendAttachmentState>	attBlendStates;
4065 	const VkPipelineColorBlendAttachmentState	attBlendState			=
4066 	{
4067 		DE_FALSE,													//	deUint32		blendEnable;
4068 		VK_BLEND_FACTOR_ONE,										//	VkBlend			srcBlendColor;
4069 		VK_BLEND_FACTOR_ZERO,										//	VkBlend			destBlendColor;
4070 		VK_BLEND_OP_ADD,											//	VkBlendOp		blendOpColor;
4071 		VK_BLEND_FACTOR_ONE,										//	VkBlend			srcBlendAlpha;
4072 		VK_BLEND_FACTOR_ZERO,										//	VkBlend			destBlendAlpha;
4073 		VK_BLEND_OP_ADD,											//	VkBlendOp		blendOpAlpha;
4074 		(VK_COLOR_COMPONENT_R_BIT|
4075 		 VK_COLOR_COMPONENT_G_BIT|
4076 		 VK_COLOR_COMPONENT_B_BIT|
4077 		 VK_COLOR_COMPONENT_A_BIT),									//	VkChannelFlags	channelWriteMask;
4078 	};
4079 	attBlendStates.push_back(attBlendState);
4080 
4081 	if (needInterface)
4082 		attBlendStates.push_back(attBlendState);
4083 
4084 	VkPipelineColorBlendStateCreateInfo		blendParams				=
4085 	{
4086 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
4087 		DE_NULL,													//	const void*									pNext;
4088 		(VkPipelineColorBlendStateCreateFlags)0,
4089 		DE_FALSE,													//	VkBool32									logicOpEnable;
4090 		VK_LOGIC_OP_COPY,											//	VkLogicOp									logicOp;
4091 		1u,															//	deUint32									attachmentCount;
4092 		attBlendStates.data(),										//	const VkPipelineColorBlendAttachmentState*	pAttachments;
4093 		{ 0.0f, 0.0f, 0.0f, 0.0f },									//	float										blendConst[4];
4094 	};
4095 	if (needInterface)
4096 	{
4097 		blendParams.attachmentCount += 1;
4098 	}
4099 	const VkPipelineTessellationStateCreateInfo	tessellationState	=
4100 	{
4101 		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
4102 		DE_NULL,
4103 		(VkPipelineTessellationStateCreateFlags)0,
4104 		3u
4105 	};
4106 
4107 	const	VkDynamicState							dynamicStates[]				=
4108 	{
4109 		VK_DYNAMIC_STATE_SCISSOR
4110 	};
4111 
4112 	const VkPipelineDynamicStateCreateInfo			dynamicStateCreateInfo =
4113 	{
4114 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,  // sType
4115 		DE_NULL,											   // pNext
4116 		0u,													   // flags
4117 		DE_LENGTH_OF_ARRAY(dynamicStates),					   // dynamicStateCount
4118 		dynamicStates										   // pDynamicStates
4119 	};
4120 
4121 	const VkPipelineTessellationStateCreateInfo* tessellationInfo	=	hasTessellation ? &tessellationState: DE_NULL;
4122 	const VkGraphicsPipelineCreateInfo		pipelineParams			=
4123 	{
4124 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,		//	VkStructureType									sType;
4125 		DE_NULL,												//	const void*										pNext;
4126 		0u,														//	VkPipelineCreateFlags							flags;
4127 		(deUint32)shaderStageParams.size(),						//	deUint32										stageCount;
4128 		&shaderStageParams[0],									//	const VkPipelineShaderStageCreateInfo*			pStages;
4129 		&vertexInputStateParams,								//	const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
4130 		&inputAssemblyParams,									//	const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
4131 		tessellationInfo,										//	const VkPipelineTessellationStateCreateInfo*	pTessellationState;
4132 		&viewportParams,										//	const VkPipelineViewportStateCreateInfo*		pViewportState;
4133 		&rasterParams,											//	const VkPipelineRasterStateCreateInfo*			pRasterState;
4134 		&multisampleParams,										//	const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
4135 		&depthStencilParams,									//	const VkPipelineDepthStencilStateCreateInfo*	pDepthStencilState;
4136 		&blendParams,											//	const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
4137 		&dynamicStateCreateInfo,								//	const VkPipelineDynamicStateCreateInfo*			pDynamicState;
4138 		*pipelineLayout,										//	VkPipelineLayout								layout;
4139 		*renderPass,											//	VkRenderPass									renderPass;
4140 		0u,														//	deUint32										subpass;
4141 		DE_NULL,												//	VkPipeline										basePipelineHandle;
4142 		0u,														//	deInt32											basePipelineIndex;
4143 	};
4144 
4145 	const Unique<VkPipeline>				pipeline				(createGraphicsPipeline(vk, device, DE_NULL, &pipelineParams));
4146 
4147 	if (needInterface)
4148 	{
4149 		const VkImageViewCreateInfo			fragOutputViewParams	=
4150 		{
4151 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			//	VkStructureType				sType;
4152 			DE_NULL,											//	const void*					pNext;
4153 			0u,													//	VkImageViewCreateFlags		flags;
4154 			*fragOutputImage,									//	VkImage						image;
4155 			VK_IMAGE_VIEW_TYPE_2D,								//	VkImageViewType				viewType;
4156 			instance.interfaces.getOutputType().getVkFormat(),	//	VkFormat					format;
4157 			{
4158 				VK_COMPONENT_SWIZZLE_R,
4159 				VK_COMPONENT_SWIZZLE_G,
4160 				VK_COMPONENT_SWIZZLE_B,
4161 				VK_COMPONENT_SWIZZLE_A
4162 			},													//	VkChannelMapping			channels;
4163 			{
4164 				VK_IMAGE_ASPECT_COLOR_BIT,						//	VkImageAspectFlags	aspectMask;
4165 				0u,												//	deUint32			baseMipLevel;
4166 				1u,												//	deUint32			mipLevels;
4167 				0u,												//	deUint32			baseArrayLayer;
4168 				1u,												//	deUint32			arraySize;
4169 			},													//	VkImageSubresourceRange		subresourceRange;
4170 		};
4171 		fragOutputImageView = createImageView(vk, device, &fragOutputViewParams);
4172 		attViews.push_back(*fragOutputImageView);
4173 	}
4174 
4175 	// Framebuffer
4176 	VkFramebufferCreateInfo					framebufferParams		=
4177 	{
4178 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,				//	VkStructureType		sType;
4179 		DE_NULL,												//	const void*			pNext;
4180 		(VkFramebufferCreateFlags)0,
4181 		*renderPass,											//	VkRenderPass		renderPass;
4182 		1u,														//	deUint32			attachmentCount;
4183 		attViews.data(),										//	const VkImageView*	pAttachments;
4184 		(deUint32)renderSize.x(),								//	deUint32			width;
4185 		(deUint32)renderSize.y(),								//	deUint32			height;
4186 		1u,														//	deUint32			layers;
4187 	};
4188 
4189 	if (needInterface)
4190 		framebufferParams.attachmentCount += 1;
4191 
4192 	const Unique<VkFramebuffer>				framebuffer				(createFramebuffer(vk, device, &framebufferParams));
4193 
4194 	bool firstPass = true;
4195 
4196 	for (int x = 0; x < numRenderSegments; x++)
4197 	{
4198 		for (int y = 0; y < numRenderSegments; y++)
4199 		{
4200 			// Record commands
4201 			beginCommandBuffer(vk, *cmdBuf);
4202 
4203 			if (firstPass)
4204 			{
4205 				const VkMemoryBarrier			vertFlushBarrier	=
4206 				{
4207 					VK_STRUCTURE_TYPE_MEMORY_BARRIER,			//	VkStructureType		sType;
4208 					DE_NULL,									//	const void*			pNext;
4209 					VK_ACCESS_HOST_WRITE_BIT,					//	VkMemoryOutputFlags	outputMask;
4210 					VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,		//	VkMemoryInputFlags	inputMask;
4211 				};
4212 				vector<VkImageMemoryBarrier>	colorAttBarriers;
4213 
4214 				VkImageMemoryBarrier			imgBarrier          =
4215 				{
4216 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		//	VkStructureType			sType;
4217 					DE_NULL,									//	const void*				pNext;
4218 					0u,											//	VkMemoryOutputFlags		outputMask;
4219 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		//	VkMemoryInputFlags		inputMask;
4220 					VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout			oldLayout;
4221 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout			newLayout;
4222 					queueFamilyIndex,							//	deUint32				srcQueueFamilyIndex;
4223 					queueFamilyIndex,							//	deUint32				destQueueFamilyIndex;
4224 					*image,										//	VkImage					image;
4225 					{
4226 						VK_IMAGE_ASPECT_COLOR_BIT,					//	VkImageAspect	aspect;
4227 						0u,											//	deUint32		baseMipLevel;
4228 						1u,											//	deUint32		mipLevels;
4229 						0u,											//	deUint32		baseArraySlice;
4230 						1u,											//	deUint32		arraySize;
4231 					}											//	VkImageSubresourceRange	subresourceRange;
4232 				};
4233 				colorAttBarriers.push_back(imgBarrier);
4234 				if (needInterface)
4235 				{
4236 					imgBarrier.image = *fragOutputImage;
4237 					colorAttBarriers.push_back(imgBarrier);
4238 					vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 2, colorAttBarriers.data());
4239 				}
4240 				else
4241 				{
4242 					vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 1, &vertFlushBarrier, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, colorAttBarriers.data());
4243 				}
4244 			}
4245 
4246 			{
4247 				vector<VkClearValue>			clearValue;
4248 				clearValue.push_back(makeClearValueColorF32(defaulClearColor[0], defaulClearColor[1], defaulClearColor[2], defaulClearColor[3]));
4249 				if (needInterface)
4250 				{
4251 					clearValue.push_back(makeClearValueColorU32(0, 0, 0, 0));
4252 				}
4253 
4254 
4255 				vk::VkRect2D scissor = makeRect2D(x * renderDimension, y * renderDimension, renderDimension, renderDimension);
4256 				vk.cmdSetScissor(*cmdBuf, 0u, 1u, &scissor);
4257 
4258 				beginRenderPass(vk, *cmdBuf, *renderPass, *framebuffer, scissor, (deUint32)clearValue.size(), clearValue.data());
4259 			}
4260 
4261 			vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
4262 			{
4263 				const VkDeviceSize bindingOffset = 0;
4264 				vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
4265 			}
4266 			if (needInterface)
4267 			{
4268 				const VkDeviceSize bindingOffset = 0;
4269 				vk.cmdBindVertexBuffers(*cmdBuf, 1u, 1u, &vertexInputBuffer.get(), &bindingOffset);
4270 			}
4271 			if (hasPushConstants)
4272 			{
4273 				vector<deUint8> pushConstantsBytes;
4274 				instance.pushConstants.getBuffer()->getBytes(pushConstantsBytes);
4275 
4276 				const deUint32	size	= static_cast<deUint32>(pushConstantsBytes.size());
4277 				const void*		data	= &pushConstantsBytes.front();
4278 
4279 				vk.cmdPushConstants(*cmdBuf, *pipelineLayout, VK_SHADER_STAGE_ALL_GRAPHICS, 0, size, data);
4280 			}
4281 			if (numResources != 0)
4282 			{
4283 				// Bind to set number 0.
4284 				vk.cmdBindDescriptorSets(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, &rawSet, 0, DE_NULL);
4285 			}
4286 			vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/);
4287 			endRenderPass(vk, *cmdBuf);
4288 
4289 			if (x == numRenderSegments - 1 && y == numRenderSegments - 1)
4290 			{
4291 				{
4292 					vector<VkImageMemoryBarrier>	renderFinishBarrier;
4293 					VkImageMemoryBarrier			imgBarrier				=
4294 					{
4295 						VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		//	VkStructureType			sType;
4296 						DE_NULL,									//	const void*				pNext;
4297 						VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		//	VkMemoryOutputFlags		outputMask;
4298 						VK_ACCESS_TRANSFER_READ_BIT,				//	VkMemoryInputFlags		inputMask;
4299 						VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout			oldLayout;
4300 						VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		//	VkImageLayout			newLayout;
4301 						queueFamilyIndex,							//	deUint32				srcQueueFamilyIndex;
4302 						queueFamilyIndex,							//	deUint32				destQueueFamilyIndex;
4303 						*image,										//	VkImage					image;
4304 						{
4305 							VK_IMAGE_ASPECT_COLOR_BIT,					//	VkImageAspectFlags	aspectMask;
4306 							0u,											//	deUint32			baseMipLevel;
4307 							1u,											//	deUint32			mipLevels;
4308 							0u,											//	deUint32			baseArraySlice;
4309 							1u,											//	deUint32			arraySize;
4310 						}											//	VkImageSubresourceRange	subresourceRange;
4311 					};
4312 					renderFinishBarrier.push_back(imgBarrier);
4313 
4314 					if (needInterface)
4315 					{
4316 						imgBarrier.image = *fragOutputImage;
4317 						renderFinishBarrier.push_back(imgBarrier);
4318 						vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 2, renderFinishBarrier.data());
4319 					}
4320 					else
4321 					{
4322 						vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, renderFinishBarrier.data());
4323 					}
4324 				}
4325 
4326 				{
4327 					const VkBufferImageCopy	copyParams	=
4328 					{
4329 						(VkDeviceSize)0u,						//	VkDeviceSize			bufferOffset;
4330 						(deUint32)renderSize.x(),				//	deUint32				bufferRowLength;
4331 						(deUint32)renderSize.y(),				//	deUint32				bufferImageHeight;
4332 						{
4333 							VK_IMAGE_ASPECT_COLOR_BIT,				//	VkImageAspect		aspect;
4334 							0u,										//	deUint32			mipLevel;
4335 							0u,										//	deUint32			arrayLayer;
4336 							1u,										//	deUint32			arraySize;
4337 						},										//	VkImageSubresourceCopy	imageSubresource;
4338 						{ 0u, 0u, 0u },							//	VkOffset3D				imageOffset;
4339 						{ renderSize.x(), renderSize.y(), 1u }
4340 					};
4341 					vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
4342 
4343 					if (needInterface)
4344 					{
4345 						vk.cmdCopyImageToBuffer(*cmdBuf, *fragOutputImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *fragOutputBuffer, 1u, &copyParams);
4346 					}
4347 				}
4348 
4349 				{
4350 					vector<VkBufferMemoryBarrier>	cpFinishBarriers;
4351 					VkBufferMemoryBarrier			copyFinishBarrier	=
4352 					{
4353 						VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	//	VkStructureType		sType;
4354 						DE_NULL,									//	const void*			pNext;
4355 						VK_ACCESS_TRANSFER_WRITE_BIT,				//	VkMemoryOutputFlags	outputMask;
4356 						VK_ACCESS_HOST_READ_BIT,					//	VkMemoryInputFlags	inputMask;
4357 						queueFamilyIndex,							//	deUint32			srcQueueFamilyIndex;
4358 						queueFamilyIndex,							//	deUint32			destQueueFamilyIndex;
4359 						*readImageBuffer,							//	VkBuffer			buffer;
4360 						0u,											//	VkDeviceSize		offset;
4361 						imageSizeBytes								//	VkDeviceSize		size;
4362 					};
4363 					cpFinishBarriers.push_back(copyFinishBarrier);
4364 
4365 					if (needInterface)
4366 					{
4367 						copyFinishBarrier.buffer	= *fragOutputBuffer;
4368 						copyFinishBarrier.size		= VK_WHOLE_SIZE;
4369 						cpFinishBarriers.push_back(copyFinishBarrier);
4370 
4371 						vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 2, cpFinishBarriers.data(), 0, (const VkImageMemoryBarrier*)DE_NULL);
4372 					}
4373 					else
4374 					{
4375 						vk.cmdPipelineBarrier(*cmdBuf, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, cpFinishBarriers.data(), 0, (const VkImageMemoryBarrier*)DE_NULL);
4376 					}
4377 				}
4378 				}
4379 
4380 			endCommandBuffer(vk, *cmdBuf);
4381 
4382 			if (firstPass)
4383 			{
4384 				// Upload vertex data
4385 				{
4386 					void* vertexBufPtr = vertexBufferMemory->getHostPtr();
4387 					deMemcpy(vertexBufPtr, &vertexData[0], vertexDataSize);
4388 					flushAlloc(vk, device, *vertexBufferMemory);
4389 				}
4390 
4391 				if (needInterface)
4392 				{
4393 					vector<deUint8> inputBufferBytes;
4394 					instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
4395 
4396 					const deUint32				typNumBytes		= instance.interfaces.getInputType().getNumBytes();
4397 					const deUint32				bufNumBytes		= static_cast<deUint32>(inputBufferBytes.size());
4398 
4399 					// Require that the test instantation provides four output values.
4400 					DE_ASSERT(bufNumBytes == 4 * typNumBytes);
4401 
4402 					// We have four triangles. Because interpolation happens before executing the fragment shader,
4403 					// we need to provide the same vertex attribute for the same triangle. That means, duplicate each
4404 					// value three times for all four values.
4405 
4406 					const deUint8*				provided		= static_cast<const deUint8*>(&inputBufferBytes.front());
4407 					vector<deUint8>				data;
4408 
4409 					data.reserve(3 * bufNumBytes);
4410 
4411 					for (deUint32 offset = 0; offset < bufNumBytes; offset += typNumBytes)
4412 						for (deUint32 vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
4413 							for (deUint32 byteNdx = 0; byteNdx < typNumBytes; ++byteNdx)
4414 								data.push_back(provided[offset + byteNdx]);
4415 
4416 					deMemcpy(vertexInputMemory->getHostPtr(), data.data(), data.size());
4417 
4418 					flushAlloc(vk, device, *vertexInputMemory);
4419 
4420 				}
4421 				firstPass = false;
4422 			}
4423 
4424 			// Submit & wait for completion
4425 			submitCommandsAndWait(vk, device, queue, cmdBuf.get());
4426 			context.resetCommandPoolForVKSC(device, *cmdPool);
4427 		}
4428 	}
4429 
4430 	const void* imagePtr	= readImageBufferMemory->getHostPtr();
4431 	const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
4432 												  renderSize.x(), renderSize.y(), 1, imagePtr);
4433 	// Log image
4434 	invalidateAlloc(vk, device, *readImageBufferMemory);
4435 	context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer);
4436 
4437 	if (needInterface)
4438 		invalidateAlloc(vk, device, *fragOutputMemory);
4439 
4440 	// Make sure all output resources are ready.
4441 	for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
4442 		invalidateAlloc(vk, device, *outResourceMemories[outputNdx]);
4443 
4444 	const RGBA threshold(1, 1, 1, 1);
4445 
4446 	const RGBA upperLeft(pixelBuffer.getPixel(1, 1));
4447 	if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold))
4448 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper left corner mismatch"));
4449 
4450 	const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1));
4451 	if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold))
4452 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper right corner mismatch"));
4453 
4454 	const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1));
4455 	if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold))
4456 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower left corner mismatch"));
4457 
4458 	const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1));
4459 	if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold))
4460 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower right corner mismatch"));
4461 
4462 	// Check that the contents in the ouput variable matches expected.
4463 	if (needInterface)
4464 	{
4465 		vector<deUint8>						inputBufferBytes;
4466 		vector<deUint8>						outputBufferBytes;
4467 
4468 		instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
4469 		instance.interfaces.getOutputBuffer()->getBytes(outputBufferBytes);
4470 
4471 		const IFDataType&					inputType				= instance.interfaces.getInputType();
4472 		const IFDataType&					outputType				= instance.interfaces.getOutputType();
4473 		const void*							inputData				= &inputBufferBytes.front();
4474 		const void*							outputData				= &outputBufferBytes.front();
4475 		vector<std::pair<int, int> >		positions;
4476 		const tcu::ConstPixelBufferAccess	fragOutputBufferAccess	(outputType.getTextureFormat(), renderSize.x(), renderSize.y(), 1, fragOutputMemory->getHostPtr());
4477 
4478 		positions.push_back(std::make_pair(1, 1));
4479 		positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, 1));
4480 		positions.push_back(std::make_pair(1, fragOutputBufferAccess.getHeight() - 1));
4481 		positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, fragOutputBufferAccess.getHeight() - 1));
4482 
4483 		for (deUint32 posNdx = 0; posNdx < positions.size(); ++posNdx)
4484 		{
4485 			const int	x		= positions[posNdx].first;
4486 			const int	y		= positions[posNdx].second;
4487 			bool		equal	= true;
4488 
4489 			if (outputType.elementType == NUMBERTYPE_FLOAT32)
4490 			{
4491 				const float*		expected	= static_cast<const float*>(outputData) + posNdx * outputType.numElements;
4492 				const float*		actual		= static_cast<const float*>(fragOutputBufferAccess.getPixelPtr(x, y));
4493 
4494 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4495 					if (!compare32BitFloat(expected[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4496 						equal = false;
4497 			}
4498 			else if (outputType.elementType == NUMBERTYPE_INT32)
4499 			{
4500 				const deInt32*		expected	= static_cast<const deInt32*>(outputData) + posNdx * outputType.numElements;
4501 				const deInt32*		actual		= static_cast<const deInt32*>(fragOutputBufferAccess.getPixelPtr(x, y));
4502 
4503 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4504 					if (expected[eleNdx] != actual[eleNdx])
4505 						equal = false;
4506 			}
4507 			else if (outputType.elementType == NUMBERTYPE_UINT32)
4508 			{
4509 				const deUint32*		expected	= static_cast<const deUint32*>(outputData) + posNdx * outputType.numElements;
4510 				const deUint32*		actual		= static_cast<const deUint32*>(fragOutputBufferAccess.getPixelPtr(x, y));
4511 
4512 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4513 					if (expected[eleNdx] != actual[eleNdx])
4514 						equal = false;
4515 			}
4516 			else if (outputType.elementType == NUMBERTYPE_FLOAT16 && inputType.elementType == NUMBERTYPE_FLOAT64)
4517 			{
4518 				const double*		original	= static_cast<const double*>(inputData) + posNdx * outputType.numElements;
4519 				const deFloat16*	actual		= static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4520 
4521 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4522 					if (!compare16BitFloat64(original[eleNdx], actual[eleNdx], instance.interfaces.getRoundingMode(), context.getTestContext().getLog()))
4523 						equal = false;
4524 			}
4525 			else if (outputType.elementType == NUMBERTYPE_FLOAT16 && inputType.elementType != NUMBERTYPE_FLOAT64)
4526 			{
4527 				if (inputType.elementType == NUMBERTYPE_FLOAT16)
4528 				{
4529 					const deFloat16*	original	= static_cast<const deFloat16*>(inputData) + posNdx * outputType.numElements;
4530 					const deFloat16*	actual		= static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4531 
4532 					for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4533 						if (!compare16BitFloat(original[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4534 							equal = false;
4535 				}
4536 				else
4537 				{
4538 					const float*		original	= static_cast<const float*>(inputData) + posNdx * outputType.numElements;
4539 					const deFloat16*	actual		= static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4540 
4541 					for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4542 						if (!compare16BitFloat(original[eleNdx], actual[eleNdx], instance.interfaces.getRoundingMode(), context.getTestContext().getLog()))
4543 							equal = false;
4544 				}
4545 			}
4546 			else if (outputType.elementType == NUMBERTYPE_INT16)
4547 			{
4548 				const deInt16*		expected	= static_cast<const deInt16*>(outputData) + posNdx * outputType.numElements;
4549 				const deInt16*		actual		= static_cast<const deInt16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4550 
4551 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4552 					if (expected[eleNdx] != actual[eleNdx])
4553 						equal = false;
4554 			}
4555 			else if (outputType.elementType == NUMBERTYPE_UINT16)
4556 			{
4557 				const deUint16*		expected	= static_cast<const deUint16*>(outputData) + posNdx * outputType.numElements;
4558 				const deUint16*		actual		= static_cast<const deUint16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4559 
4560 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4561 					if (expected[eleNdx] != actual[eleNdx])
4562 						equal = false;
4563 			}
4564 			else if (outputType.elementType == NUMBERTYPE_FLOAT64)
4565 			{
4566 				const double*		expected	= static_cast<const double*>(outputData) + posNdx * outputType.numElements;
4567 				const double*		actual		= static_cast<const double*>(fragOutputBufferAccess.getPixelPtr(x, y));
4568 
4569 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4570 					if (!compare64BitFloat(expected[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4571 						equal = false;
4572 			}
4573 			else {
4574 				DE_ASSERT(0 && "unhandled type");
4575 			}
4576 
4577 			if (!equal)
4578 				return TestStatus(instance.failResult, instance.getSpecializedFailMessage("fragment output dat point #" + numberToString(posNdx) + " mismatch"));
4579 		}
4580 	}
4581 
4582 	// Check the contents in output resources match with expected.
4583 	for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
4584 	{
4585 		const BufferSp& expected = instance.resources.outputs[outputNdx].getBuffer();
4586 
4587 		if (instance.resources.verifyIO != DE_NULL)
4588 		{
4589 			if (!(*instance.resources.verifyIO)(instance.resources.inputs, outResourceMemories, instance.resources.outputs, context.getTestContext().getLog()))
4590 				return tcu::TestStatus::fail("Resource returned doesn't match with expected");
4591 		}
4592 		else
4593 		{
4594 			vector<deUint8> expectedBytes;
4595 			expected->getBytes(expectedBytes);
4596 
4597 			if (deMemCmp(&expectedBytes.front(), outResourceMemories[outputNdx]->getHostPtr(), expectedBytes.size()))
4598 			{
4599 				const size_t	numExpectedEntries	= expectedBytes.size() / sizeof(float);
4600 				float*			expectedFloats		= reinterpret_cast<float*>(&expectedBytes.front());
4601 				float*			outputFloats		= reinterpret_cast<float*>(outResourceMemories[outputNdx]->getHostPtr());
4602 				float			diff				= 0.0f;
4603 				deUint32		bitDiff				= 0;
4604 
4605 				for (size_t expectedNdx = 0; expectedNdx < numExpectedEntries; ++expectedNdx)
4606 				{
4607 					// RTZ and RNE can introduce a difference of a single ULP
4608 					// The RTZ output will always be either equal or lower than the RNE expected,
4609 					// so perform a bitwise subtractraction and check for the ULP difference
4610 					bitDiff = *reinterpret_cast<deUint32*>(&expectedFloats[expectedNdx]) - *reinterpret_cast<deUint32*>(&outputFloats[expectedNdx]);
4611 
4612 					// Allow a maximum of 1 ULP difference to account for RTZ rounding
4613 					if (bitDiff & (~0x1))
4614 					{
4615 						// Note: RTZ/RNE rounding leniency isn't applied for the checks below:
4616 
4617 						// Some *variable_pointers* tests store counters in buffer
4618 						// whose value may vary if the same shader may be executed for multiple times
4619 						// in this case the output value can be expected value + non-negative integer N
4620 						if (instance.customizedStages == VK_SHADER_STAGE_VERTEX_BIT ||
4621 							instance.customizedStages == VK_SHADER_STAGE_GEOMETRY_BIT ||
4622 							instance.customizedStages == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
4623 							instance.customizedStages == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
4624 						{
4625 							if (deFloatIsInf(outputFloats[expectedNdx]) || deFloatIsNaN(outputFloats[expectedNdx]))
4626 								return tcu::TestStatus::fail("Value returned is invalid");
4627 
4628 							diff = outputFloats[expectedNdx] - expectedFloats[expectedNdx];
4629 							deUint32 intDiff = static_cast<deUint32>(diff);
4630 
4631 							if ((diff < 0.0f) || (expectedFloats[expectedNdx] + static_cast<float>(intDiff)) != outputFloats[expectedNdx])
4632 								return tcu::TestStatus::fail("Value returned should be equal to expected value plus non-negative integer");
4633 						}
4634 						else
4635 						{
4636 							return tcu::TestStatus::fail("Resource returned should be equal to expected, allowing for RTZ/RNE rounding");
4637 						}
4638 					}
4639 				}
4640 			}
4641 
4642 		}
4643 	}
4644 
4645 	return TestStatus::pass("Rendered output matches input");
4646 }
4647 
getVertFragPipelineStages(void)4648 const vector<ShaderElement>& getVertFragPipelineStages (void)
4649 {
4650 	static vector<ShaderElement> vertFragPipelineStages;
4651 	if(vertFragPipelineStages.empty())
4652 	{
4653 		vertFragPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4654 		vertFragPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4655 	}
4656 	return vertFragPipelineStages;
4657 }
4658 
getTessPipelineStages(void)4659 const vector<ShaderElement>& getTessPipelineStages (void)
4660 {
4661 	static vector<ShaderElement> tessPipelineStages;
4662 	if(tessPipelineStages.empty())
4663 	{
4664 		tessPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4665 		tessPipelineStages.push_back(ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
4666 		tessPipelineStages.push_back(ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
4667 		tessPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4668 	}
4669 	return tessPipelineStages;
4670 }
4671 
getGeomPipelineStages(void)4672 const vector<ShaderElement>& getGeomPipelineStages (void)
4673 {
4674 	static vector<ShaderElement> geomPipelineStages;
4675 	if(geomPipelineStages.empty())
4676 	{
4677 		geomPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4678 		geomPipelineStages.push_back(ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT));
4679 		geomPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4680 	}
4681 	return geomPipelineStages;
4682 }
4683 
4684 // Helper structure used by addTestForStage function.
4685 struct StageData
4686 {
4687 	typedef const vector<ShaderElement>& (*GetPipelineStagesFn)();
4688 	typedef void (*AddShaderCodeCustomStageFn)(vk::SourceCollections&, InstanceContext);
4689 
4690 	GetPipelineStagesFn			getPipelineFn;
4691 	AddShaderCodeCustomStageFn	initProgramsFn;
4692 
StageDatavkt::SpirVAssembly::StageData4693 	StageData()
4694 		: getPipelineFn(DE_NULL)
4695 		, initProgramsFn(DE_NULL)
4696 	{
4697 	}
4698 
StageDatavkt::SpirVAssembly::StageData4699 	StageData(GetPipelineStagesFn pipelineGetter, AddShaderCodeCustomStageFn programsInitializer)
4700 		: getPipelineFn(pipelineGetter)
4701 		, initProgramsFn(programsInitializer)
4702 	{
4703 	}
4704 };
4705 
4706 // Helper function used by addTestForStage function.
getStageData(vk::VkShaderStageFlagBits stage)4707 const StageData& getStageData (vk::VkShaderStageFlagBits stage)
4708 {
4709 	// Construct map
4710 	static map<vk::VkShaderStageFlagBits, StageData> testedStageData;
4711 	if(testedStageData.empty())
4712 	{
4713 		testedStageData[VK_SHADER_STAGE_VERTEX_BIT]					 = StageData(getVertFragPipelineStages, addShaderCodeCustomVertex);
4714 		testedStageData[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT]	 = StageData(getTessPipelineStages, addShaderCodeCustomTessControl);
4715 		testedStageData[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = StageData(getTessPipelineStages, addShaderCodeCustomTessEval);
4716 		testedStageData[VK_SHADER_STAGE_GEOMETRY_BIT]				 = StageData(getGeomPipelineStages, addShaderCodeCustomGeometry);
4717 		testedStageData[VK_SHADER_STAGE_FRAGMENT_BIT]				 = StageData(getVertFragPipelineStages, addShaderCodeCustomFragment);
4718 	}
4719 
4720 	return testedStageData[stage];
4721 }
4722 
createTestForStage(vk::VkShaderStageFlagBits stage,const std::string & name,const RGBA (& inputColors)[4],const RGBA (& outputColors)[4],const map<string,string> & testCodeFragments,const SpecConstants & specConstants,const PushConstants & pushConstants,const GraphicsResources & resources,const GraphicsInterfaces & interfaces,const vector<string> & extensions,VulkanFeatures vulkanFeatures,tcu::TestCaseGroup * tests,const qpTestResult failResult,const string & failMessageTemplate,const bool renderFullSquare,const bool splitRenderArea)4723 void createTestForStage (vk::VkShaderStageFlagBits	stage,
4724 						 const std::string&			name,
4725 						 const RGBA					(&inputColors)[4],
4726 						 const RGBA					(&outputColors)[4],
4727 						 const map<string, string>&	testCodeFragments,
4728 						 const SpecConstants&		specConstants,
4729 						 const PushConstants&		pushConstants,
4730 						 const GraphicsResources&	resources,
4731 						 const GraphicsInterfaces&	interfaces,
4732 						 const vector<string>&		extensions,
4733 						 VulkanFeatures				vulkanFeatures,
4734 						 tcu::TestCaseGroup*		tests,
4735 						 const qpTestResult			failResult,
4736 						 const string&				failMessageTemplate,
4737 						 const bool					renderFullSquare,
4738 						 const bool					splitRenderArea)
4739 {
4740 	const StageData&				stageData			= getStageData(stage);
4741 	DE_ASSERT(stageData.getPipelineFn || stageData.initProgramsFn);
4742 	const vector<ShaderElement>&	pipeline			= stageData.getPipelineFn();
4743 
4744 	StageToSpecConstantMap			specConstantMap;
4745 	if (!specConstants.empty())
4746 		specConstantMap[stage] = specConstants;
4747 
4748 	InstanceContext					ctx					(inputColors, outputColors, testCodeFragments, specConstantMap, pushConstants, resources, interfaces, extensions, vulkanFeatures, stage);
4749 	ctx.splitRenderArea = splitRenderArea;
4750 	for (size_t i = 0; i < pipeline.size(); ++i)
4751 	{
4752 		ctx.moduleMap[pipeline[i].moduleName].push_back(std::make_pair(pipeline[i].entryName, pipeline[i].stage));
4753 		ctx.requiredStages = static_cast<VkShaderStageFlagBits>(ctx.requiredStages | pipeline[i].stage);
4754 	}
4755 
4756 	ctx.failResult = failResult;
4757 	if (!failMessageTemplate.empty())
4758 		ctx.failMessageTemplate = failMessageTemplate;
4759 
4760 	ctx.renderFullSquare = renderFullSquare;
4761 	ctx.splitRenderArea	= splitRenderArea;
4762 	addFunctionCaseWithPrograms<InstanceContext>(tests, name, "", stageData.initProgramsFn, runAndVerifyDefaultPipeline, ctx);
4763 }
4764 
createTestsForAllStages(const std::string & name,const RGBA (& inputColors)[4],const RGBA (& outputColors)[4],const map<string,string> & testCodeFragments,const SpecConstants & specConstants,const PushConstants & pushConstants,const GraphicsResources & resources,const GraphicsInterfaces & interfaces,const vector<string> & extensions,VulkanFeatures vulkanFeatures,tcu::TestCaseGroup * tests,const qpTestResult failResult,const string & failMessageTemplate,const bool splitRenderArea)4765 void createTestsForAllStages (const std::string&			name,
4766 							  const RGBA					(&inputColors)[4],
4767 							  const RGBA					(&outputColors)[4],
4768 							  const map<string, string>&	testCodeFragments,
4769 							  const SpecConstants&			specConstants,
4770 							  const PushConstants&			pushConstants,
4771 							  const GraphicsResources&		resources,
4772 							  const GraphicsInterfaces&		interfaces,
4773 							  const vector<string>&			extensions,
4774 							  VulkanFeatures				vulkanFeatures,
4775 							  tcu::TestCaseGroup*			tests,
4776 							  const qpTestResult			failResult,
4777 							  const string&					failMessageTemplate,
4778 							  const bool					splitRenderArea)
4779 {
4780 	createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, name + "_vert",
4781 					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4782 					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4783 
4784 	createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, name + "_tessc",
4785 					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4786 					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4787 
4788 	createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, name + "_tesse",
4789 					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4790 					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4791 
4792 	createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, name + "_geom",
4793 					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4794 					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4795 
4796 	createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, name + "_frag",
4797 					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4798 					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate, false, splitRenderArea);
4799 }
4800 
addTessCtrlTest(tcu::TestCaseGroup * group,const char * name,const map<string,string> & fragments)4801 void addTessCtrlTest (tcu::TestCaseGroup* group, const char* name, const map<string, string>& fragments)
4802 {
4803 	RGBA defaultColors[4];
4804 	getDefaultColors(defaultColors);
4805 
4806 	createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, name,
4807 					   defaultColors, defaultColors, fragments, SpecConstants(), PushConstants(), GraphicsResources(),
4808 					   GraphicsInterfaces(), vector<string>(), VulkanFeatures(), group);
4809 }
4810 
4811 } // SpirVAssembly
4812 } // vkt
4813