• 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_KHR) == 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 
1857 		// Decorations.
1858 		shader	<< "OpDecorate %out_gl_position BuiltIn Position\n"
1859 				<< "OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n"
1860 				<< "OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n"
1861 				<< "OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n"
1862 				<< "OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n"
1863 				<< "OpDecorate %per_vertex_in Block\n"
1864 				<< "OpDecorate %out_color Location 1\n"
1865 				<< "OpDecorate %in_color Location 1\n";
1866 		if (task != SHADER_TASK_NORMAL)
1867 		{
1868 			shader	<< getUnusedDecorations(ctx.variableLocation);
1869 		}
1870 
1871 		// Standard types, constants and arrays.
1872 		shader	<< "; Start of standard types, constants and arrays\n"
1873 				<< SPIRV_ASSEMBLY_TYPES
1874 				<< SPIRV_ASSEMBLY_CONSTANTS
1875 				<< SPIRV_ASSEMBLY_ARRAYS
1876 				<< "; End of standard types, constants and arrays\n";
1877 		if (task != SHADER_TASK_NORMAL)
1878 		{
1879 			shader	<< getUnusedTypesAndConstants();
1880 		}
1881 
1882 		// Variables.
1883 		shader	<< "%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
1884 				<< "%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n"
1885 				<< "%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n"
1886 				<< "%gl_in = OpVariable %ip_a3_per_vertex_in Input\n"
1887 				<< "%out_color = OpVariable %op_v4f32 Output\n"
1888 				<< "%in_color = OpVariable %ip_a3v4f32 Input\n"
1889 				<< "%out_gl_position = OpVariable %op_v4f32 Output\n";
1890 		if (task != SHADER_TASK_NORMAL)
1891 		{
1892 			shader << getUnusedBuffer();
1893 		}
1894 
1895 		// Main function.
1896 		shader	<< "%geom1_main = OpFunction %void None %voidf\n"
1897 				<< "%geom1_label = OpLabel\n"
1898 				<< "%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
1899 				<< "%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
1900 				<< "%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
1901 				<< "%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n"
1902 				<< "%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n"
1903 				<< "%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n"
1904 				<< "%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
1905 				<< "%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
1906 				<< "%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
1907 				<< "%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n"
1908 				<< "%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n"
1909 				<< "%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n"
1910 				<< "OpStore %out_gl_position %geom1_in_position_0\n"
1911 				<< "OpStore %out_color %geom1_in_color_0\n"
1912 				<< "OpEmitVertex\n"
1913 				<< "OpStore %out_gl_position %geom1_in_position_1\n"
1914 				<< "OpStore %out_color %geom1_in_color_1\n"
1915 				<< "OpEmitVertex\n"
1916 				<< "OpStore %out_gl_position %geom1_in_position_2\n"
1917 				<< "OpStore %out_color %geom1_in_color_2\n"
1918 				<< "OpEmitVertex\n"
1919 				<< "OpEndPrimitive\n"
1920 				<< "OpReturn\n"
1921 				<< "OpFunctionEnd\n";
1922 		if (task == SHADER_TASK_UNUSED_FUNC)
1923 		{
1924 			shader	<< getUnusedFunctionBody();
1925 		}
1926 
1927 		dst.spirvAsmSources.add("geom") << shader.str();
1928 	}
1929 
1930 	if (ctx.shaderTasks[SHADER_TASK_INDEX_TESS_CONTROL]	!= SHADER_TASK_NONE)
1931 	{
1932 		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_TESS_CONTROL];
1933 		std::ostringstream	shader;
1934 
1935 		if (task != SHADER_TASK_NORMAL)
1936 		{
1937 			shader	<< getOpCapabilityShader();
1938 		}
1939 		shader	<< "OpCapability Tessellation\n"
1940 				<< "OpMemoryModel Logical GLSL450\n";
1941 
1942 		// Entry point.
1943 		shader	<< "OpEntryPoint TessellationControl %tessc1_main \"main\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n";
1944 		if (task == SHADER_TASK_UNUSED_FUNC)
1945 		{
1946 			shader	<< getUnusedEntryPoint();
1947 		}
1948 		shader	<< "OpExecutionMode %tessc1_main OutputVertices 3\n";
1949 
1950 		// Decorations.
1951 		shader	<< "OpDecorate %out_color Location 1\n"
1952 				<< "OpDecorate %gl_InvocationID BuiltIn InvocationId\n"
1953 				<< "OpDecorate %in_color Location 1\n"
1954 				<< "OpDecorate %out_position Location 2\n"
1955 				<< "OpDecorate %in_position Location 2\n"
1956 				<< "OpDecorate %gl_TessLevelOuter Patch\n"
1957 				<< "OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n"
1958 				<< "OpDecorate %gl_TessLevelInner Patch\n"
1959 				<< "OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n";
1960 		if (task != SHADER_TASK_NORMAL)
1961 		{
1962 			shader	<< getUnusedDecorations(ctx.variableLocation);
1963 		}
1964 
1965 		// Standard types, constants and arrays.
1966 		shader	<< "; Start of standard types, constants and arrays\n"
1967 				<< SPIRV_ASSEMBLY_TYPES
1968 				<< SPIRV_ASSEMBLY_CONSTANTS
1969 				<< SPIRV_ASSEMBLY_ARRAYS
1970 				<< "; End of standard types, constants and arrays\n";
1971 		if (task != SHADER_TASK_NORMAL)
1972 		{
1973 			shader	<< getUnusedTypesAndConstants();
1974 		}
1975 
1976 		// Variables.
1977 		shader	<< "%out_color = OpVariable %op_a3v4f32 Output\n"
1978 				<< "%gl_InvocationID = OpVariable %ip_i32 Input\n"
1979 				<< "%in_color = OpVariable %ip_a32v4f32 Input\n"
1980 				<< "%out_position = OpVariable %op_a3v4f32 Output\n"
1981 				<< "%in_position = OpVariable %ip_a32v4f32 Input\n"
1982 				<< "%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
1983 				<< "%gl_TessLevelInner = OpVariable %op_a2f32 Output\n";
1984 		if (task != SHADER_TASK_NORMAL)
1985 		{
1986 			shader << getUnusedBuffer();
1987 		}
1988 
1989 		// Main entry point.
1990 		shader	<< "%tessc1_main = OpFunction %void None %voidf\n"
1991 				<< "%tessc1_label = OpLabel\n"
1992 				<< "%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n"
1993 				<< "%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n"
1994 				<< "%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n"
1995 				<< "%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n"
1996 				<< "%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n"
1997 				<< "%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n"
1998 				<< "%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n"
1999 				<< "OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n"
2000 				<< "OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n"
2001 				<< "%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n"
2002 				<< "OpSelectionMerge %tessc1_merge_label None\n"
2003 				<< "OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n"
2004 				<< "%tessc1_first_invocation = OpLabel\n"
2005 				<< "%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
2006 				<< "%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
2007 				<< "%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
2008 				<< "%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n"
2009 				<< "OpStore %tessc1_tess_outer_0 %c_f32_1\n"
2010 				<< "OpStore %tessc1_tess_outer_1 %c_f32_1\n"
2011 				<< "OpStore %tessc1_tess_outer_2 %c_f32_1\n"
2012 				<< "OpStore %tessc1_tess_inner %c_f32_1\n"
2013 				<< "OpBranch %tessc1_merge_label\n"
2014 				<< "%tessc1_merge_label = OpLabel\n"
2015 				<< "OpReturn\n"
2016 				<< "OpFunctionEnd\n";
2017 		if (task == SHADER_TASK_UNUSED_FUNC)
2018 		{
2019 			shader	<< getUnusedFunctionBody();
2020 		}
2021 
2022 		dst.spirvAsmSources.add("tessc") << shader.str();
2023 	}
2024 
2025 	if (ctx.shaderTasks[SHADER_TASK_INDEX_TESS_EVAL] != SHADER_TASK_NONE)
2026 	{
2027 		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_TESS_EVAL];
2028 		std::ostringstream	shader;
2029 
2030 		if (task != SHADER_TASK_NORMAL)
2031 		{
2032 			shader	<< getOpCapabilityShader();
2033 		}
2034 		shader	<< "OpCapability Tessellation\n"
2035 				<< "OpMemoryModel Logical GLSL450\n";
2036 
2037 		// Entry point.
2038 		shader	<< "OpEntryPoint TessellationEvaluation %tesse1_main \"main\" %stream %gl_tessCoord %in_position %out_color %in_color \n";
2039 		if (task == SHADER_TASK_UNUSED_FUNC)
2040 		{
2041 			shader	<< getUnusedEntryPoint();
2042 		}
2043 		shader	<< "OpExecutionMode %tesse1_main Triangles\n"
2044 				<< "OpExecutionMode %tesse1_main SpacingEqual\n"
2045 				<< "OpExecutionMode %tesse1_main VertexOrderCcw\n";
2046 
2047 		// Decorations.
2048 		shader	<< "OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n"
2049 				<< "OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n"
2050 				<< "OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n"
2051 				<< "OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n"
2052 				<< "OpDecorate %per_vertex_out Block\n"
2053 				<< "OpDecorate %gl_tessCoord BuiltIn TessCoord\n"
2054 				<< "OpDecorate %in_position Location 2\n"
2055 				<< "OpDecorate %out_color Location 1\n"
2056 				<< "OpDecorate %in_color Location 1\n";
2057 		if (task != SHADER_TASK_NORMAL)
2058 		{
2059 			shader	<< getUnusedDecorations(ctx.variableLocation);
2060 		}
2061 
2062 		// Standard types, constants and arrays.
2063 		shader	<< "; Start of standard types, constants and arrays\n"
2064 				<< SPIRV_ASSEMBLY_TYPES
2065 				<< SPIRV_ASSEMBLY_CONSTANTS
2066 				<< SPIRV_ASSEMBLY_ARRAYS
2067 				<< "; End of standard types, constants and arrays\n";
2068 		if (task != SHADER_TASK_NORMAL)
2069 		{
2070 			shader	<< getUnusedTypesAndConstants();
2071 		}
2072 
2073 		// Variables.
2074 		shader	<< "%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2075 				<< "%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n"
2076 				<< "%stream = OpVariable %op_per_vertex_out Output\n"
2077 				<< "%gl_tessCoord = OpVariable %ip_v3f32 Input\n"
2078 				<< "%in_position = OpVariable %ip_a32v4f32 Input\n"
2079 				<< "%out_color = OpVariable %op_v4f32 Output\n"
2080 				<< "%in_color = OpVariable %ip_a32v4f32 Input\n";
2081 		if (task != SHADER_TASK_NORMAL)
2082 		{
2083 			shader << getUnusedBuffer();
2084 		}
2085 
2086 		// Main entry point.
2087 		shader	<< "%tesse1_main = OpFunction %void None %voidf\n"
2088 				<< "%tesse1_label = OpLabel\n"
2089 				<< "%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
2090 				<< "%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
2091 				<< "%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
2092 				<< "%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n"
2093 				<< "%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n"
2094 				<< "%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n"
2095 				<< "%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
2096 				<< "%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
2097 				<< "%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
2098 				<< "%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n"
2099 				<< "%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n"
2100 				<< "%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n"
2101 				<< "%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n"
2102 				<< "%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n"
2103 				<< "%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n"
2104 				<< "%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
2105 				<< "%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n"
2106 				<< "%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n"
2107 				<< "OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n"
2108 				<< "%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2109 				<< "%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2110 				<< "%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2111 				<< "%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n"
2112 				<< "%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n"
2113 				<< "%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n"
2114 				<< "%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n"
2115 				<< "%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n"
2116 				<< "%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n"
2117 				<< "%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n"
2118 				<< "%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n"
2119 				<< "OpStore %out_color %tesse1_computed_clr\n"
2120 				<< "OpReturn\n"
2121 				<< "OpFunctionEnd\n";
2122 		if (task == SHADER_TASK_UNUSED_FUNC)
2123 		{
2124 			shader	<< getUnusedFunctionBody();
2125 		}
2126 
2127 		dst.spirvAsmSources.add("tesse") << shader.str();
2128 	}
2129 
2130 	if (ctx.shaderTasks[SHADER_TASK_INDEX_FRAGMENT] != SHADER_TASK_NONE)
2131 	{
2132 		const ShaderTask&	task = ctx.shaderTasks[SHADER_TASK_INDEX_FRAGMENT];
2133 		std::ostringstream	shader;
2134 
2135 		shader	<< "OpCapability Shader\n"
2136 				<< "OpMemoryModel Logical GLSL450\n";
2137 
2138 		// Entry point.
2139 		shader	<< "OpEntryPoint Fragment %main \"main\" %vtxColor %fragColor\n";
2140 		if (task == SHADER_TASK_UNUSED_FUNC)
2141 		{
2142 			shader	<< getUnusedEntryPoint();
2143 		}
2144 		shader	<< "OpExecutionMode %main OriginUpperLeft\n";
2145 
2146 		// Decorations.
2147 		shader	<< "OpDecorate %fragColor Location 0\n"
2148 				<< "OpDecorate %vtxColor Location 1\n";
2149 		if (task != SHADER_TASK_NORMAL)
2150 		{
2151 			shader	<< getUnusedDecorations(ctx.variableLocation);
2152 		}
2153 
2154 		// Standard types, constants and arrays.
2155 		shader	<< "; Start of standard types, constants and arrays\n"
2156 				<< SPIRV_ASSEMBLY_TYPES
2157 				<< SPIRV_ASSEMBLY_CONSTANTS
2158 				<< SPIRV_ASSEMBLY_ARRAYS
2159 				<< "; End of standard types, constants and arrays\n";
2160 		if (task != SHADER_TASK_NORMAL)
2161 		{
2162 			shader	<< getUnusedTypesAndConstants();
2163 		}
2164 
2165 		// Variables.
2166 		shader	<< "%fragColor = OpVariable %op_v4f32 Output\n"
2167 				<< "%vtxColor = OpVariable %ip_v4f32 Input\n";
2168 		if (task != SHADER_TASK_NORMAL)
2169 		{
2170 			shader << getUnusedBuffer();
2171 		}
2172 
2173 		// Main entry point.
2174 		shader	<< "%main = OpFunction %void None %voidf\n"
2175 				<< "%label_main = OpLabel\n"
2176 				<< "%tmp1 = OpLoad %v4f32 %vtxColor\n"
2177 				<< "OpStore %fragColor %tmp1\n"
2178 				<< "OpReturn\n"
2179 				<< "OpFunctionEnd\n";
2180 		if (task == SHADER_TASK_UNUSED_FUNC)
2181 		{
2182 			shader	<< getUnusedFunctionBody();
2183 		}
2184 
2185 		dst.spirvAsmSources.add("frag") << shader.str();
2186 	}
2187 }
2188 
createMultipleEntries(vk::SourceCollections & dst,InstanceContext)2189 void createMultipleEntries (vk::SourceCollections& dst, InstanceContext)
2190 {
2191 	dst.spirvAsmSources.add("vert") <<
2192 	// This module contains 2 vertex shaders. One that is a passthrough
2193 	// and a second that inverts the color of the output (1.0 - color).
2194 		"OpCapability Shader\n"
2195 		"OpMemoryModel Logical GLSL450\n"
2196 		"OpEntryPoint Vertex %main \"vert1\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
2197 		"OpEntryPoint Vertex %main2 \"vert2\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
2198 
2199 		"OpDecorate %vtxPosition Location 2\n"
2200 		"OpDecorate %Position Location 0\n"
2201 		"OpDecorate %vtxColor Location 1\n"
2202 		"OpDecorate %color Location 1\n"
2203 		"OpDecorate %vertex_id BuiltIn VertexIndex\n"
2204 		"OpDecorate %instance_id BuiltIn InstanceIndex\n"
2205 		SPIRV_ASSEMBLY_TYPES
2206 		SPIRV_ASSEMBLY_CONSTANTS
2207 		SPIRV_ASSEMBLY_ARRAYS
2208 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2209 		"%vtxPosition = OpVariable %op_v4f32 Output\n"
2210 		"%Position = OpVariable %ip_v4f32 Input\n"
2211 		"%vtxColor = OpVariable %op_v4f32 Output\n"
2212 		"%color = OpVariable %ip_v4f32 Input\n"
2213 		"%vertex_id = OpVariable %ip_i32 Input\n"
2214 		"%instance_id = OpVariable %ip_i32 Input\n"
2215 
2216 		"%main = OpFunction %void None %voidf\n"
2217 		"%label = OpLabel\n"
2218 		"%tmp_position = OpLoad %v4f32 %Position\n"
2219 		"OpStore %vtxPosition %tmp_position\n"
2220 		"%tmp_color = OpLoad %v4f32 %color\n"
2221 		"OpStore %vtxColor %tmp_color\n"
2222 		"OpReturn\n"
2223 		"OpFunctionEnd\n"
2224 
2225 		"%main2 = OpFunction %void None %voidf\n"
2226 		"%label2 = OpLabel\n"
2227 		"%tmp_position2 = OpLoad %v4f32 %Position\n"
2228 		"OpStore %vtxPosition %tmp_position2\n"
2229 		"%tmp_color2 = OpLoad %v4f32 %color\n"
2230 		"%tmp_color3 = OpFSub %v4f32 %cval %tmp_color2\n"
2231 		"%tmp_color4 = OpVectorInsertDynamic %v4f32 %tmp_color3 %c_f32_1 %c_i32_3\n"
2232 		"OpStore %vtxColor %tmp_color4\n"
2233 		"OpReturn\n"
2234 		"OpFunctionEnd\n";
2235 
2236 	dst.spirvAsmSources.add("frag") <<
2237 		// This is a single module that contains 2 fragment shaders.
2238 		// One that passes color through and the other that inverts the output
2239 		// color (1.0 - color).
2240 		"OpCapability Shader\n"
2241 		"OpMemoryModel Logical GLSL450\n"
2242 		"OpEntryPoint Fragment %main \"frag1\" %vtxColor %fragColor\n"
2243 		"OpEntryPoint Fragment %main2 \"frag2\" %vtxColor %fragColor\n"
2244 		"OpExecutionMode %main OriginUpperLeft\n"
2245 		"OpExecutionMode %main2 OriginUpperLeft\n"
2246 
2247 		"OpDecorate %fragColor Location 0\n"
2248 		"OpDecorate %vtxColor Location 1\n"
2249 		SPIRV_ASSEMBLY_TYPES
2250 		SPIRV_ASSEMBLY_CONSTANTS
2251 		SPIRV_ASSEMBLY_ARRAYS
2252 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2253 		"%fragColor = OpVariable %op_v4f32 Output\n"
2254 		"%vtxColor = OpVariable %ip_v4f32 Input\n"
2255 
2256 		"%main = OpFunction %void None %voidf\n"
2257 		"%label_main = OpLabel\n"
2258 		"%tmp1 = OpLoad %v4f32 %vtxColor\n"
2259 		"OpStore %fragColor %tmp1\n"
2260 		"OpReturn\n"
2261 		"OpFunctionEnd\n"
2262 
2263 		"%main2 = OpFunction %void None %voidf\n"
2264 		"%label_main2 = OpLabel\n"
2265 		"%tmp2 = OpLoad %v4f32 %vtxColor\n"
2266 		"%tmp3 = OpFSub %v4f32 %cval %tmp2\n"
2267 		"%tmp4 = OpVectorInsertDynamic %v4f32 %tmp3 %c_f32_1 %c_i32_3\n"
2268 		"OpStore %fragColor %tmp4\n"
2269 		"OpReturn\n"
2270 		"OpFunctionEnd\n";
2271 
2272 	dst.spirvAsmSources.add("geom") <<
2273 		"OpCapability Geometry\n"
2274 		"OpMemoryModel Logical GLSL450\n"
2275 		"OpEntryPoint Geometry %geom1_main \"geom1\" %out_gl_position %gl_in %out_color %in_color\n"
2276 		"OpEntryPoint Geometry %geom2_main \"geom2\" %out_gl_position %gl_in %out_color %in_color\n"
2277 		"OpExecutionMode %geom1_main Triangles\n"
2278 		"OpExecutionMode %geom2_main Triangles\n"
2279 		"OpExecutionMode %geom1_main OutputTriangleStrip\n"
2280 		"OpExecutionMode %geom2_main OutputTriangleStrip\n"
2281 		"OpExecutionMode %geom1_main OutputVertices 3\n"
2282 		"OpExecutionMode %geom2_main OutputVertices 3\n"
2283 		"OpDecorate %out_gl_position BuiltIn Position\n"
2284 		"OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n"
2285 		"OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n"
2286 		"OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n"
2287 		"OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n"
2288 		"OpDecorate %per_vertex_in Block\n"
2289 		"OpDecorate %out_color Location 1\n"
2290 		"OpDecorate %in_color Location 1\n"
2291 		SPIRV_ASSEMBLY_TYPES
2292 		SPIRV_ASSEMBLY_CONSTANTS
2293 		SPIRV_ASSEMBLY_ARRAYS
2294 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2295 		"%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2296 		"%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n"
2297 		"%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n"
2298 		"%gl_in = OpVariable %ip_a3_per_vertex_in Input\n"
2299 		"%out_color = OpVariable %op_v4f32 Output\n"
2300 		"%in_color = OpVariable %ip_a3v4f32 Input\n"
2301 		"%out_gl_position = OpVariable %op_v4f32 Output\n"
2302 
2303 		"%geom1_main = OpFunction %void None %voidf\n"
2304 		"%geom1_label = OpLabel\n"
2305 		"%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
2306 		"%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
2307 		"%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
2308 		"%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n"
2309 		"%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n"
2310 		"%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n"
2311 		"%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2312 		"%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2313 		"%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2314 		"%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n"
2315 		"%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n"
2316 		"%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n"
2317 		"OpStore %out_gl_position %geom1_in_position_0\n"
2318 		"OpStore %out_color %geom1_in_color_0\n"
2319 		"OpEmitVertex\n"
2320 		"OpStore %out_gl_position %geom1_in_position_1\n"
2321 		"OpStore %out_color %geom1_in_color_1\n"
2322 		"OpEmitVertex\n"
2323 		"OpStore %out_gl_position %geom1_in_position_2\n"
2324 		"OpStore %out_color %geom1_in_color_2\n"
2325 		"OpEmitVertex\n"
2326 		"OpEndPrimitive\n"
2327 		"OpReturn\n"
2328 		"OpFunctionEnd\n"
2329 
2330 		"%geom2_main = OpFunction %void None %voidf\n"
2331 		"%geom2_label = OpLabel\n"
2332 		"%geom2_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
2333 		"%geom2_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
2334 		"%geom2_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
2335 		"%geom2_in_position_0 = OpLoad %v4f32 %geom2_gl_in_0_gl_position\n"
2336 		"%geom2_in_position_1 = OpLoad %v4f32 %geom2_gl_in_1_gl_position\n"
2337 		"%geom2_in_position_2 = OpLoad %v4f32 %geom2_gl_in_2_gl_position \n"
2338 		"%geom2_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2339 		"%geom2_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2340 		"%geom2_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2341 		"%geom2_in_color_0 = OpLoad %v4f32 %geom2_in_color_0_ptr\n"
2342 		"%geom2_in_color_1 = OpLoad %v4f32 %geom2_in_color_1_ptr\n"
2343 		"%geom2_in_color_2 = OpLoad %v4f32 %geom2_in_color_2_ptr\n"
2344 		"%geom2_transformed_in_color_0 = OpFSub %v4f32 %cval %geom2_in_color_0\n"
2345 		"%geom2_transformed_in_color_1 = OpFSub %v4f32 %cval %geom2_in_color_1\n"
2346 		"%geom2_transformed_in_color_2 = OpFSub %v4f32 %cval %geom2_in_color_2\n"
2347 		"%geom2_transformed_in_color_0_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_0 %c_f32_1 %c_i32_3\n"
2348 		"%geom2_transformed_in_color_1_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_1 %c_f32_1 %c_i32_3\n"
2349 		"%geom2_transformed_in_color_2_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_2 %c_f32_1 %c_i32_3\n"
2350 		"OpStore %out_gl_position %geom2_in_position_0\n"
2351 		"OpStore %out_color %geom2_transformed_in_color_0_a\n"
2352 		"OpEmitVertex\n"
2353 		"OpStore %out_gl_position %geom2_in_position_1\n"
2354 		"OpStore %out_color %geom2_transformed_in_color_1_a\n"
2355 		"OpEmitVertex\n"
2356 		"OpStore %out_gl_position %geom2_in_position_2\n"
2357 		"OpStore %out_color %geom2_transformed_in_color_2_a\n"
2358 		"OpEmitVertex\n"
2359 		"OpEndPrimitive\n"
2360 		"OpReturn\n"
2361 		"OpFunctionEnd\n";
2362 
2363 	dst.spirvAsmSources.add("tessc") <<
2364 		"OpCapability Tessellation\n"
2365 		"OpMemoryModel Logical GLSL450\n"
2366 		"OpEntryPoint TessellationControl %tessc1_main \"tessc1\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
2367 		"OpEntryPoint TessellationControl %tessc2_main \"tessc2\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
2368 		"OpExecutionMode %tessc1_main OutputVertices 3\n"
2369 		"OpExecutionMode %tessc2_main OutputVertices 3\n"
2370 		"OpDecorate %out_color Location 1\n"
2371 		"OpDecorate %gl_InvocationID BuiltIn InvocationId\n"
2372 		"OpDecorate %in_color Location 1\n"
2373 		"OpDecorate %out_position Location 2\n"
2374 		"OpDecorate %in_position Location 2\n"
2375 		"OpDecorate %gl_TessLevelOuter Patch\n"
2376 		"OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n"
2377 		"OpDecorate %gl_TessLevelInner Patch\n"
2378 		"OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n"
2379 		SPIRV_ASSEMBLY_TYPES
2380 		SPIRV_ASSEMBLY_CONSTANTS
2381 		SPIRV_ASSEMBLY_ARRAYS
2382 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2383 		"%out_color = OpVariable %op_a3v4f32 Output\n"
2384 		"%gl_InvocationID = OpVariable %ip_i32 Input\n"
2385 		"%in_color = OpVariable %ip_a32v4f32 Input\n"
2386 		"%out_position = OpVariable %op_a3v4f32 Output\n"
2387 		"%in_position = OpVariable %ip_a32v4f32 Input\n"
2388 		"%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
2389 		"%gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
2390 
2391 		"%tessc1_main = OpFunction %void None %voidf\n"
2392 		"%tessc1_label = OpLabel\n"
2393 		"%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n"
2394 		"%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n"
2395 		"%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n"
2396 		"%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n"
2397 		"%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n"
2398 		"%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n"
2399 		"%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n"
2400 		"OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n"
2401 		"OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n"
2402 		"%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n"
2403 		"OpSelectionMerge %tessc1_merge_label None\n"
2404 		"OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n"
2405 		"%tessc1_first_invocation = OpLabel\n"
2406 		"%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
2407 		"%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
2408 		"%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
2409 		"%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n"
2410 		"OpStore %tessc1_tess_outer_0 %c_f32_1\n"
2411 		"OpStore %tessc1_tess_outer_1 %c_f32_1\n"
2412 		"OpStore %tessc1_tess_outer_2 %c_f32_1\n"
2413 		"OpStore %tessc1_tess_inner %c_f32_1\n"
2414 		"OpBranch %tessc1_merge_label\n"
2415 		"%tessc1_merge_label = OpLabel\n"
2416 		"OpReturn\n"
2417 		"OpFunctionEnd\n"
2418 
2419 		"%tessc2_main = OpFunction %void None %voidf\n"
2420 		"%tessc2_label = OpLabel\n"
2421 		"%tessc2_invocation_id = OpLoad %i32 %gl_InvocationID\n"
2422 		"%tessc2_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc2_invocation_id\n"
2423 		"%tessc2_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc2_invocation_id\n"
2424 		"%tessc2_in_color_val = OpLoad %v4f32 %tessc2_in_color_ptr\n"
2425 		"%tessc2_in_position_val = OpLoad %v4f32 %tessc2_in_position_ptr\n"
2426 		"%tessc2_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc2_invocation_id\n"
2427 		"%tessc2_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc2_invocation_id\n"
2428 		"%tessc2_transformed_color = OpFSub %v4f32 %cval %tessc2_in_color_val\n"
2429 		"%tessc2_transformed_color_a = OpVectorInsertDynamic %v4f32 %tessc2_transformed_color %c_f32_1 %c_i32_3\n"
2430 		"OpStore %tessc2_out_color_ptr %tessc2_transformed_color_a\n"
2431 		"OpStore %tessc2_out_position_ptr %tessc2_in_position_val\n"
2432 		"%tessc2_is_first_invocation = OpIEqual %bool %tessc2_invocation_id %c_i32_0\n"
2433 		"OpSelectionMerge %tessc2_merge_label None\n"
2434 		"OpBranchConditional %tessc2_is_first_invocation %tessc2_first_invocation %tessc2_merge_label\n"
2435 		"%tessc2_first_invocation = OpLabel\n"
2436 		"%tessc2_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
2437 		"%tessc2_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
2438 		"%tessc2_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
2439 		"%tessc2_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n"
2440 		"OpStore %tessc2_tess_outer_0 %c_f32_1\n"
2441 		"OpStore %tessc2_tess_outer_1 %c_f32_1\n"
2442 		"OpStore %tessc2_tess_outer_2 %c_f32_1\n"
2443 		"OpStore %tessc2_tess_inner %c_f32_1\n"
2444 		"OpBranch %tessc2_merge_label\n"
2445 		"%tessc2_merge_label = OpLabel\n"
2446 		"OpReturn\n"
2447 		"OpFunctionEnd\n";
2448 
2449 	dst.spirvAsmSources.add("tesse") <<
2450 		"OpCapability Tessellation\n"
2451 		"OpMemoryModel Logical GLSL450\n"
2452 		"OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
2453 		"OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
2454 		"OpExecutionMode %tesse1_main Triangles\n"
2455 		"OpExecutionMode %tesse1_main SpacingEqual\n"
2456 		"OpExecutionMode %tesse1_main VertexOrderCcw\n"
2457 		"OpExecutionMode %tesse2_main Triangles\n"
2458 		"OpExecutionMode %tesse2_main SpacingEqual\n"
2459 		"OpExecutionMode %tesse2_main VertexOrderCcw\n"
2460 		"OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n"
2461 		"OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n"
2462 		"OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n"
2463 		"OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n"
2464 		"OpDecorate %per_vertex_out Block\n"
2465 		"OpDecorate %gl_tessCoord BuiltIn TessCoord\n"
2466 		"OpDecorate %in_position Location 2\n"
2467 		"OpDecorate %out_color Location 1\n"
2468 		"OpDecorate %in_color Location 1\n"
2469 		SPIRV_ASSEMBLY_TYPES
2470 		SPIRV_ASSEMBLY_CONSTANTS
2471 		SPIRV_ASSEMBLY_ARRAYS
2472 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
2473 		"%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
2474 		"%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n"
2475 		"%stream = OpVariable %op_per_vertex_out Output\n"
2476 		"%gl_tessCoord = OpVariable %ip_v3f32 Input\n"
2477 		"%in_position = OpVariable %ip_a32v4f32 Input\n"
2478 		"%out_color = OpVariable %op_v4f32 Output\n"
2479 		"%in_color = OpVariable %ip_a32v4f32 Input\n"
2480 
2481 		"%tesse1_main = OpFunction %void None %voidf\n"
2482 		"%tesse1_label = OpLabel\n"
2483 		"%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
2484 		"%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
2485 		"%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
2486 		"%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n"
2487 		"%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n"
2488 		"%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n"
2489 		"%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
2490 		"%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
2491 		"%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
2492 		"%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n"
2493 		"%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n"
2494 		"%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n"
2495 		"%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n"
2496 		"%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n"
2497 		"%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n"
2498 		"%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
2499 		"%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n"
2500 		"%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n"
2501 		"OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n"
2502 		"%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2503 		"%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2504 		"%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2505 		"%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n"
2506 		"%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n"
2507 		"%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n"
2508 		"%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n"
2509 		"%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n"
2510 		"%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n"
2511 		"%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n"
2512 		"%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n"
2513 		"OpStore %out_color %tesse1_computed_clr\n"
2514 		"OpReturn\n"
2515 		"OpFunctionEnd\n"
2516 
2517 		"%tesse2_main = OpFunction %void None %voidf\n"
2518 		"%tesse2_label = OpLabel\n"
2519 		"%tesse2_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
2520 		"%tesse2_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
2521 		"%tesse2_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
2522 		"%tesse2_tc_0 = OpLoad %f32 %tesse2_tc_0_ptr\n"
2523 		"%tesse2_tc_1 = OpLoad %f32 %tesse2_tc_1_ptr\n"
2524 		"%tesse2_tc_2 = OpLoad %f32 %tesse2_tc_2_ptr\n"
2525 		"%tesse2_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
2526 		"%tesse2_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
2527 		"%tesse2_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
2528 		"%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n"
2529 		"%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n"
2530 		"%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n"
2531 		"%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_0 %tesse2_tc_0\n"
2532 		"%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_1 %tesse2_tc_1\n"
2533 		"%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_2 %tesse2_tc_2\n"
2534 		"%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
2535 		"%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n"
2536 		"%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n"
2537 		"OpStore %tesse2_out_pos_ptr %tesse2_computed_out\n"
2538 		"%tesse2_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
2539 		"%tesse2_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
2540 		"%tesse2_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
2541 		"%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n"
2542 		"%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n"
2543 		"%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n"
2544 		"%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_0 %tesse2_tc_0\n"
2545 		"%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_1 %tesse2_tc_1\n"
2546 		"%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_2 %tesse2_tc_2\n"
2547 		"%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n"
2548 		"%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n"
2549 		"%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n"
2550 		"%tesse2_clr_transformed_a = OpVectorInsertDynamic %v4f32 %tesse2_clr_transformed %c_f32_1 %c_i32_3\n"
2551 		"OpStore %out_color %tesse2_clr_transformed_a\n"
2552 		"OpReturn\n"
2553 		"OpFunctionEnd\n";
2554 }
2555 
compare16BitFloat(float original,deUint16 returned,RoundingModeFlags flags,tcu::TestLog & log)2556 bool compare16BitFloat (float original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log)
2557 {
2558 	// We only support RTE, RTZ, or both.
2559 	DE_ASSERT(static_cast<int>(flags) > 0 && static_cast<int>(flags) < 4);
2560 
2561 	const Float32	originalFloat	(original);
2562 	const Float16	returnedFloat	(returned);
2563 
2564 	// Zero are turned into zero under both RTE and RTZ.
2565 	if (originalFloat.isZero())
2566 	{
2567 		if (returnedFloat.isZero())
2568 			return true;
2569 
2570 		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2571 		return false;
2572 	}
2573 
2574 	// Any denormalized value input into a shader may be flushed to 0.
2575 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2576 		return true;
2577 
2578 	// Inf are always turned into Inf with the same sign, too.
2579 	if (originalFloat.isInf())
2580 	{
2581 		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2582 			return true;
2583 
2584 		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2585 		return false;
2586 	}
2587 
2588 	// NaN are always turned into NaN, too.
2589 	if (originalFloat.isNaN())
2590 	{
2591 		if (returnedFloat.isNaN())
2592 			return true;
2593 
2594 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2595 		return false;
2596 	}
2597 
2598 	// Check all rounding modes
2599 	for (int bitNdx = 0; bitNdx < 2; ++bitNdx)
2600 	{
2601 		if ((flags & (1u << bitNdx)) == 0)
2602 			continue;	// This rounding mode is not selected.
2603 
2604 		const Float16	expectedFloat	(deFloat32To16Round(original, deRoundingMode(bitNdx)));
2605 
2606 		// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2607 		if (expectedFloat.isDenorm() && returnedFloat.isZero())
2608 			return true;
2609 
2610 		// If not matched in the above cases, they should have the same bit pattern.
2611 		if (expectedFloat.bits() == returnedFloat.bits())
2612 			return true;
2613 	}
2614 
2615 	log << TestLog::Message << "Error: found unmatched 32-bit and 16-bit floats: " << originalFloat.bits() << " vs " << returned << TestLog::EndMessage;
2616 	return false;
2617 }
2618 
compare16BitFloat(deUint16 original,deUint16 returned,tcu::TestLog & log)2619 bool compare16BitFloat (deUint16 original, deUint16 returned, tcu::TestLog& log)
2620 {
2621 	const Float16	originalFloat	(original);
2622 	const Float16	returnedFloat	(returned);
2623 
2624 	if (originalFloat.isZero())
2625 	{
2626 		if (returnedFloat.isZero())
2627 			return true;
2628 
2629 		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2630 		return false;
2631 	}
2632 
2633 	// Any denormalized value input into a shader or potentially generated by any instruction in a shader
2634 	// may be flushed to 0.
2635 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2636 		return true;
2637 
2638 	// Inf are always turned into Inf with the same sign, too.
2639 	if (originalFloat.isInf())
2640 	{
2641 		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2642 			return true;
2643 
2644 		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2645 		return false;
2646 	}
2647 
2648 	// NaN are always turned into NaN, too.
2649 	if (originalFloat.isNaN())
2650 	{
2651 		if (returnedFloat.isNaN())
2652 			return true;
2653 
2654 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2655 		return false;
2656 	}
2657 
2658 	// If not matched in the above cases, they should have the same bit pattern.
2659 	if (originalFloat.bits() == returnedFloat.bits())
2660 		return true;
2661 
2662 	log << TestLog::Message << "Error: found unmatched 16-bit and 16-bit floats: " << original << " vs " << returned << TestLog::EndMessage;
2663 	return false;
2664 }
2665 
compare16BitFloat(deUint16 original,float returned,tcu::TestLog & log)2666 bool compare16BitFloat(deUint16 original, float returned, tcu::TestLog & log)
2667 {
2668 	const Float16	originalFloat	(original);
2669 	const Float32	returnedFloat	(returned);
2670 
2671 	// Zero are turned into zero under both RTE and RTZ.
2672 	if (originalFloat.isZero())
2673 	{
2674 		if (returnedFloat.isZero())
2675 			return true;
2676 
2677 		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2678 		return false;
2679 	}
2680 
2681 	// Any denormalized value input into a shader may be flushed to 0.
2682 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2683 		return true;
2684 
2685 	// Inf are always turned into Inf with the same sign, too.
2686 	if (originalFloat.isInf())
2687 	{
2688 		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2689 			return true;
2690 
2691 		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2692 		return false;
2693 	}
2694 
2695 	// NaN are always turned into NaN, too.
2696 	if (originalFloat.isNaN())
2697 	{
2698 		if (returnedFloat.isNaN())
2699 			return true;
2700 
2701 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2702 		return false;
2703 	}
2704 
2705 	// In all other cases, conversion should be exact.
2706 	const Float32 expectedFloat (deFloat16To32(original));
2707 	if (expectedFloat.bits() == returnedFloat.bits())
2708 		return true;
2709 
2710 	log << TestLog::Message << "Error: found unmatched 16-bit and 32-bit floats: " << original << " vs " << returnedFloat.bits() << TestLog::EndMessage;
2711 	return false;
2712 }
2713 
compare16BitFloat(deFloat16 original,deFloat16 returned,std::string & error)2714 bool compare16BitFloat (deFloat16 original, deFloat16 returned, std::string& error)
2715 {
2716 	std::ostringstream	log;
2717 	const Float16		originalFloat	(original);
2718 	const Float16		returnedFloat	(returned);
2719 
2720 	if (originalFloat.isZero())
2721 	{
2722 		if (returnedFloat.isZero())
2723 			return true;
2724 
2725 		log << "Error: expected zero but returned " << std::hex << "0x" << returned << " (" << returnedFloat.asFloat() << ")";
2726 		error = log.str();
2727 		return false;
2728 	}
2729 
2730 	// Any denormalized value input into a shader may be flushed to 0.
2731 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2732 		return true;
2733 
2734 	// Inf are always turned into Inf with the same sign, too.
2735 	if (originalFloat.isInf())
2736 	{
2737 		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2738 			return true;
2739 
2740 		log << "Error: expected Inf but returned " << std::hex << "0x" << returned << " (" << returnedFloat.asFloat() << ")";
2741 		error = log.str();
2742 		return false;
2743 	}
2744 
2745 	// NaN are always turned into NaN, too.
2746 	if (originalFloat.isNaN())
2747 	{
2748 		if (returnedFloat.isNaN())
2749 			return true;
2750 
2751 		log << "Error: expected NaN but returned " << std::hex << "0x" << returned << " (" << returnedFloat.asFloat() << ")";
2752 		error = log.str();
2753 		return false;
2754 	}
2755 
2756 	// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2757 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2758 		return true;
2759 
2760 	// If not matched in the above cases, they should have the same bit pattern.
2761 	if (originalFloat.bits() == returnedFloat.bits())
2762 		return true;
2763 
2764 	log << "Error: found unmatched 16-bit and 16-bit floats: 0x"
2765 		<< std::hex << original << " <=> 0x" << returned
2766 		<< " (" << originalFloat.asFloat() << " <=> " << returnedFloat.asFloat() << ")";
2767 	error = log.str();
2768 	return false;
2769 }
2770 
compare16BitFloat64(double original,deUint16 returned,RoundingModeFlags flags,tcu::TestLog & log)2771 bool compare16BitFloat64 (double original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log)
2772 {
2773 	// We only support RTE, RTZ, or both.
2774 	DE_ASSERT(static_cast<int>(flags) > 0 && static_cast<int>(flags) < 4);
2775 
2776 	const Float64	originalFloat	(original);
2777 	const Float16	returnedFloat	(returned);
2778 
2779 	// Zero are turned into zero under both RTE and RTZ.
2780 	if (originalFloat.isZero())
2781 	{
2782 		if (returnedFloat.isZero())
2783 			return true;
2784 
2785 		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
2786 		return false;
2787 	}
2788 
2789 	// Any denormalized value input into a shader may be flushed to 0.
2790 	if (originalFloat.isDenorm() && returnedFloat.isZero())
2791 		return true;
2792 
2793 	// Inf are always turned into Inf with the same sign, too.
2794 	if (originalFloat.isInf())
2795 	{
2796 		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
2797 			return true;
2798 
2799 		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
2800 		return false;
2801 	}
2802 
2803 	// NaN are always turned into NaN, too.
2804 	if (originalFloat.isNaN())
2805 	{
2806 		if (returnedFloat.isNaN())
2807 			return true;
2808 
2809 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2810 		return false;
2811 	}
2812 
2813 	// Check all rounding modes
2814 	for (int bitNdx = 0; bitNdx < 2; ++bitNdx)
2815 	{
2816 		if ((flags & (1u << bitNdx)) == 0)
2817 			continue;	// This rounding mode is not selected.
2818 
2819 		const Float16	expectedFloat	(deFloat64To16Round(original, deRoundingMode(bitNdx)));
2820 
2821 		// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2822 		if (expectedFloat.isDenorm() && returnedFloat.isZero())
2823 			return true;
2824 
2825 		// If not matched in the above cases, they should have the same bit pattern.
2826 		if (expectedFloat.bits() == returnedFloat.bits())
2827 			return true;
2828 	}
2829 
2830 	log << TestLog::Message << "Error: found unmatched 64-bit and 16-bit floats: " << originalFloat.bits() << " vs " << returned << TestLog::EndMessage;
2831 	return false;
2832 }
2833 
compare32BitFloat(float expected,float returned,tcu::TestLog & log)2834 bool compare32BitFloat (float expected, float returned, tcu::TestLog& log)
2835 {
2836 	const Float32	expectedFloat	(expected);
2837 	const Float32	returnedFloat	(returned);
2838 
2839 	// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2840 	if (expectedFloat.isDenorm() && returnedFloat.isZero())
2841 		return true;
2842 
2843 	{
2844 		const Float16	originalFloat	(deFloat32To16(expected));
2845 
2846 		// Any denormalized value input into a shader may be flushed to 0.
2847 		if (originalFloat.isDenorm() && returnedFloat.isZero())
2848 			return true;
2849 	}
2850 
2851 	if (expectedFloat.isNaN())
2852 	{
2853 		if (returnedFloat.isNaN())
2854 			return true;
2855 
2856 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2857 		return false;
2858 	}
2859 
2860 	if (returned == expected)
2861 		return true;
2862 
2863 	log << TestLog::Message << "Error: found unmatched 32-bit float: expected " << expectedFloat.bits() << " vs. returned " << returnedFloat.bits() << TestLog::EndMessage;
2864 	return false;
2865 }
2866 
compare64BitFloat(double expected,double returned,tcu::TestLog & log)2867 bool compare64BitFloat (double expected, double returned, tcu::TestLog& log)
2868 {
2869 	const Float64	expectedDouble	(expected);
2870 	const Float64	returnedDouble	(returned);
2871 
2872 	// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
2873 	if (expectedDouble.isDenorm() && returnedDouble.isZero())
2874 		return true;
2875 
2876 	{
2877 		const Float16	originalDouble	(deFloat64To16(expected));
2878 
2879 		// Any denormalized value input into a shader may be flushed to 0.
2880 		if (originalDouble.isDenorm() && returnedDouble.isZero())
2881 			return true;
2882 	}
2883 
2884 	if (expectedDouble.isNaN())
2885 	{
2886 		if (returnedDouble.isNaN())
2887 			return true;
2888 
2889 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
2890 		return false;
2891 	}
2892 
2893 	if (returned == expected)
2894 		return true;
2895 
2896 	log << TestLog::Message << "Error: found unmatched 64-bit float: expected " << expectedDouble.bits() << " vs. returned " << returnedDouble.bits() << TestLog::EndMessage;
2897 	return false;
2898 }
2899 
createBufferForResource(const DeviceInterface & vk,const VkDevice vkDevice,const Resource & resource,deUint32 queueFamilyIndex)2900 Move<VkBuffer> createBufferForResource (const DeviceInterface& vk, const VkDevice vkDevice, const Resource& resource, deUint32 queueFamilyIndex)
2901 {
2902 	const vk::VkDescriptorType resourceType = resource.getDescriptorType();
2903 
2904 	vector<deUint8>	resourceBytes;
2905 	resource.getBytes(resourceBytes);
2906 
2907 	const VkBufferCreateInfo	resourceBufferParams	=
2908 	{
2909 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,								// sType
2910 		DE_NULL,															// pNext
2911 		(VkBufferCreateFlags)0,												// flags
2912 		(VkDeviceSize)resourceBytes.size(),									// size
2913 		(VkBufferUsageFlags)getMatchingBufferUsageFlagBit(resourceType),	// usage
2914 		VK_SHARING_MODE_EXCLUSIVE,											// sharingMode
2915 		1u,																	// queueFamilyCount
2916 		&queueFamilyIndex,													// pQueueFamilyIndices
2917 	};
2918 
2919 	return createBuffer(vk, vkDevice, &resourceBufferParams);
2920 }
2921 
createImageForResource(const DeviceInterface & vk,const VkDevice vkDevice,const Resource & resource,VkFormat inputFormat,deUint32 queueFamilyIndex)2922 Move<VkImage> createImageForResource (const DeviceInterface& vk, const VkDevice vkDevice, const Resource& resource, VkFormat inputFormat, deUint32 queueFamilyIndex)
2923 {
2924 	const VkImageCreateInfo	resourceImageParams	=
2925 	{
2926 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,								//	VkStructureType		sType;
2927 		DE_NULL,															//	const void*			pNext;
2928 		0u,																	//	VkImageCreateFlags	flags;
2929 		VK_IMAGE_TYPE_2D,													//	VkImageType			imageType;
2930 		inputFormat,														//	VkFormat			format;
2931 		{ 8, 8, 1 },														//	VkExtent3D			extent;
2932 		1u,																	//	deUint32			mipLevels;
2933 		1u,																	//	deUint32			arraySize;
2934 		VK_SAMPLE_COUNT_1_BIT,												//	deUint32			samples;
2935 		VK_IMAGE_TILING_OPTIMAL,											//	VkImageTiling		tiling;
2936 		getMatchingImageUsageFlags(resource.getDescriptorType()),			//	VkImageUsageFlags	usage;
2937 		VK_SHARING_MODE_EXCLUSIVE,											//	VkSharingMode		sharingMode;
2938 		1u,																	//	deUint32			queueFamilyCount;
2939 		&queueFamilyIndex,													//	const deUint32*		pQueueFamilyIndices;
2940 		VK_IMAGE_LAYOUT_UNDEFINED											//	VkImageLayout		initialLayout;
2941 	};
2942 
2943 	return createImage(vk, vkDevice, &resourceImageParams);
2944 }
2945 
copyBufferToImage(const DeviceInterface & vk,const VkDevice & device,const VkQueue & queue,VkCommandBuffer cmdBuffer,VkBuffer buffer,VkImage image,VkImageAspectFlags aspect)2946 void copyBufferToImage (const DeviceInterface& vk, const VkDevice& device, const VkQueue& queue, VkCommandBuffer cmdBuffer, VkBuffer buffer, VkImage image, VkImageAspectFlags aspect)
2947 {
2948 	const VkBufferImageCopy			copyRegion			=
2949 	{
2950 		0u,												// VkDeviceSize				bufferOffset;
2951 		0u,												// deUint32					bufferRowLength;
2952 		0u,												// deUint32					bufferImageHeight;
2953 		{
2954 			aspect,											// VkImageAspectFlags		aspect;
2955 			0u,												// deUint32					mipLevel;
2956 			0u,												// deUint32					baseArrayLayer;
2957 			1u,												// deUint32					layerCount;
2958 		},												// VkImageSubresourceLayers	imageSubresource;
2959 		{ 0, 0, 0 },									// VkOffset3D				imageOffset;
2960 		{ 8, 8, 1 }										// VkExtent3D				imageExtent;
2961 	};
2962 
2963 	// Copy buffer to image
2964 	beginCommandBuffer(vk, cmdBuffer);
2965 
2966 	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);
2967 
2968 	endCommandBuffer(vk, cmdBuffer);
2969 
2970 	submitCommandsAndWait(vk, device, queue, cmdBuffer);
2971 }
2972 
getImageAspectFlags(VkFormat format)2973 VkImageAspectFlags getImageAspectFlags (VkFormat format)
2974 {
2975 	const tcu::TextureFormat::ChannelOrder	channelOrder	= vk::mapVkFormat(format).order;
2976 	VkImageAspectFlags						aspectFlags		= (VkImageAspectFlags)0u;
2977 
2978 	if (tcu::hasDepthComponent(channelOrder))
2979 		aspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
2980 
2981 	if (tcu::hasStencilComponent(channelOrder))
2982 		aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
2983 
2984 	if (!aspectFlags)
2985 		aspectFlags |= VK_IMAGE_ASPECT_COLOR_BIT;
2986 
2987 	return aspectFlags;
2988 };
2989 
runAndVerifyUnusedVariablePipeline(Context & context,UnusedVariableContext unusedVariableContext)2990 TestStatus runAndVerifyUnusedVariablePipeline (Context &context, UnusedVariableContext unusedVariableContext)
2991 {
2992 	return runAndVerifyDefaultPipeline(context, unusedVariableContext.instanceContext);
2993 }
2994 
runAndVerifyDefaultPipeline(Context & context,InstanceContext instance)2995 TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance)
2996 {
2997 	if (getMinRequiredVulkanVersion(instance.resources.spirvVersion) > context.getUsedApiVersion())
2998 	{
2999 		TCU_THROW(NotSupportedError, string("Vulkan higher than or equal to " + getVulkanName(getMinRequiredVulkanVersion(instance.resources.spirvVersion)) + " is required for this test to run").c_str());
3000 	}
3001 
3002 	const DeviceInterface&						vk						= context.getDeviceInterface();
3003 	const InstanceInterface&					vkInstance				= context.getInstanceInterface();
3004 	const VkPhysicalDevice						vkPhysicalDevice		= context.getPhysicalDevice();
3005 	const deUint32								queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
3006 	const VkQueue								queue					= context.getUniversalQueue();
3007 	const VkDevice&								device					= context.getDevice();
3008 	Allocator&									allocator				= context.getDefaultAllocator();
3009 	vector<ModuleHandleSp>						modules;
3010 	map<VkShaderStageFlagBits, VkShaderModule>	moduleByStage;
3011 	const deUint32								fullRenderSize			= 256;
3012 	const deUint32								quarterRenderSize		= 64;
3013 	const tcu::UVec2							renderSize				(fullRenderSize, fullRenderSize);
3014 	const int									testSpecificSeed		= 31354125;
3015 	const int									seed					= context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed;
3016 	bool										supportsGeometry		= false;
3017 	bool										supportsTessellation	= false;
3018 	bool										hasGeometry				= false;
3019 	bool										hasTessellation			= false;
3020 	const bool									hasPushConstants		= !instance.pushConstants.empty();
3021 	const deUint32								numResources			= static_cast<deUint32>(instance.resources.inputs.size() + instance.resources.outputs.size());
3022 	const bool									needInterface			= !instance.interfaces.empty();
3023 	const VkPhysicalDeviceFeatures&				features				= context.getDeviceFeatures();
3024 	const Vec4									defaulClearColor		(0.125f, 0.25f, 0.75f, 1.0f);
3025 	bool										splitRenderArea			= instance.splitRenderArea;
3026 
3027 	const deUint32								renderDimension			= splitRenderArea ? quarterRenderSize : fullRenderSize;
3028 	const int									numRenderSegments		= splitRenderArea ? 4 : 1;
3029 
3030 	supportsGeometry		= features.geometryShader == VK_TRUE;
3031 	supportsTessellation	= features.tessellationShader == VK_TRUE;
3032 	hasGeometry				= (instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT);
3033 	hasTessellation			= (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) ||
3034 								(instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3035 
3036 	if (hasGeometry && !supportsGeometry)
3037 	{
3038 		TCU_THROW(NotSupportedError, "Geometry not supported");
3039 	}
3040 
3041 	if (hasTessellation && !supportsTessellation)
3042 	{
3043 		TCU_THROW(NotSupportedError, "Tessellation not supported");
3044 	}
3045 
3046 	// Check all required extensions are supported
3047 	for (std::vector<std::string>::const_iterator i = instance.requiredDeviceExtensions.begin(); i != instance.requiredDeviceExtensions.end(); ++i)
3048 	{
3049 		if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), *i))
3050 			TCU_THROW(NotSupportedError, (std::string("Extension not supported: ") + *i).c_str());
3051 	}
3052 
3053 	// Core features
3054 	{
3055 		const VkShaderStageFlags		vertexPipelineStoresAndAtomicsAffected	= vk::VK_SHADER_STAGE_VERTEX_BIT
3056 																				| vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT
3057 																				| vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT
3058 																				| vk::VK_SHADER_STAGE_GEOMETRY_BIT;
3059 		const char*						unsupportedFeature						= DE_NULL;
3060 		vk::VkPhysicalDeviceFeatures	localRequiredCoreFeatures				= instance.requestedFeatures.coreFeatures;
3061 
3062 		// reset fragment stores and atomics feature requirement
3063 		if ((localRequiredCoreFeatures.fragmentStoresAndAtomics != DE_FALSE) &&
3064 			(instance.customizedStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) == 0)
3065 		{
3066 			localRequiredCoreFeatures.fragmentStoresAndAtomics = DE_FALSE;
3067 		}
3068 
3069 		// reset vertex pipeline stores and atomics feature requirement
3070 		if (localRequiredCoreFeatures.vertexPipelineStoresAndAtomics != DE_FALSE &&
3071 			(instance.customizedStages & vertexPipelineStoresAndAtomicsAffected) == 0)
3072 		{
3073 			localRequiredCoreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE;
3074 		}
3075 
3076 		if (!isCoreFeaturesSupported(context, localRequiredCoreFeatures, &unsupportedFeature))
3077 			TCU_THROW(NotSupportedError, std::string("At least following requested core feature is not supported: ") + unsupportedFeature);
3078 	}
3079 
3080 	// Extension features
3081 	{
3082 		// 8bit storage features
3083 		{
3084 			if (!is8BitStorageFeaturesSupported(context, instance.requestedFeatures.ext8BitStorage))
3085 				TCU_THROW(NotSupportedError, "Requested 8bit storage features not supported");
3086 		}
3087 
3088 		// 16bit storage features
3089 		{
3090 			if (!is16BitStorageFeaturesSupported(context, instance.requestedFeatures.ext16BitStorage))
3091 				TCU_THROW(NotSupportedError, "Requested 16bit storage features not supported");
3092 		}
3093 
3094 		// Variable Pointers features
3095 		{
3096 			if (!isVariablePointersFeaturesSupported(context, instance.requestedFeatures.extVariablePointers))
3097 				TCU_THROW(NotSupportedError, "Requested Variable Pointer features not supported");
3098 		}
3099 
3100 		// Float16/Int8 shader features
3101 		{
3102 			if (!isFloat16Int8FeaturesSupported(context, instance.requestedFeatures.extFloat16Int8))
3103 				TCU_THROW(NotSupportedError, "Requested 16bit float or 8bit int feature not supported");
3104 		}
3105 	}
3106 
3107 	// FloatControls features
3108 	{
3109 		if (!isFloatControlsFeaturesSupported(context, instance.requestedFeatures.floatControlsProperties))
3110 			TCU_THROW(NotSupportedError, "Requested Float Controls features not supported");
3111 	}
3112 
3113 	// Check Interface Input/Output formats are supported
3114 	if (needInterface)
3115 	{
3116 		VkFormatProperties formatProperties;
3117 		vkInstance.getPhysicalDeviceFormatProperties(vkPhysicalDevice, instance.interfaces.getInputType().getVkFormat(), &formatProperties);
3118 		if ((formatProperties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0)
3119 		{
3120 			std::string	error				= "Interface Input format (";
3121 			const std::string formatName	= getFormatName(instance.interfaces.getInputType().getVkFormat());
3122 			error += formatName + ") not supported";
3123 			TCU_THROW(NotSupportedError, error.c_str());
3124 		}
3125 
3126 		vkInstance.getPhysicalDeviceFormatProperties(vkPhysicalDevice, instance.interfaces.getOutputType().getVkFormat(), &formatProperties);
3127 		if (((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0) ||
3128 			((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0))
3129 		{
3130 			std::string	error				= "Interface Output format (";
3131 			const std::string formatName	= getFormatName(instance.interfaces.getInputType().getVkFormat());
3132 			error += formatName + ") not supported";
3133 			TCU_THROW(NotSupportedError, error.c_str());
3134 		}
3135 	}
3136 
3137 	de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4);
3138 	de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4);
3139 	const Vec4								vertexData[]			=
3140 	{
3141 		// Upper left corner:
3142 		Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),	//1
3143 		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),	//2
3144 		Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(),	//3
3145 
3146 		// Upper right corner:
3147 		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),	//4
3148 		Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),	//5
3149 		Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(),	//6
3150 
3151 		// Lower left corner:
3152 		Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(),	//7
3153 		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),	//8
3154 		Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),	//9
3155 
3156 		// Lower right corner:
3157 		Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(),	//10
3158 		Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(),	//11
3159 		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(),	//12
3160 
3161 		// The rest is used only renderFullSquare specified. Fills area already filled with clear color
3162 		// Left 1
3163 		Vec4(-1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor,					//3
3164 		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//2
3165 		Vec4(-1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor,					//7
3166 
3167 		// Left 2
3168 		Vec4(-1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor,					//7
3169 		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//2
3170 		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//8
3171 
3172 		// Left-Center
3173 		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//8
3174 		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//2
3175 		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//4
3176 
3177 		// Right-Center
3178 		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//4
3179 		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//12
3180 		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//8
3181 
3182 		// Right 2
3183 		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor,					//4
3184 		Vec4(+1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor,					//6
3185 		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//12
3186 
3187 		// Right 1
3188 		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor,					//12
3189 		Vec4(+1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor,					//6
3190 		Vec4(+1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor,					//10
3191 	};
3192 
3193 	const size_t							singleVertexDataSize	= 2 * sizeof(Vec4);
3194 	const size_t							vertexCount				= instance.renderFullSquare ? sizeof(vertexData) / singleVertexDataSize : 4*3;
3195 	const size_t							vertexDataSize			= vertexCount * singleVertexDataSize;
3196 
3197 	Move<VkBuffer>							vertexInputBuffer;
3198 	de::MovePtr<Allocation>					vertexInputMemory;
3199 	Move<VkBuffer>							fragOutputBuffer;
3200 	de::MovePtr<Allocation>					fragOutputMemory;
3201 	Move<VkImage>							fragOutputImage;
3202 	de::MovePtr<Allocation>					fragOutputImageMemory;
3203 	Move<VkImageView>						fragOutputImageView;
3204 
3205 	const VkBufferCreateInfo				vertexBufferParams		=
3206 	{
3207 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	//	VkStructureType		sType;
3208 		DE_NULL,								//	const void*			pNext;
3209 		0u,										//	VkBufferCreateFlags	flags;
3210 		(VkDeviceSize)vertexDataSize,			//	VkDeviceSize		size;
3211 		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,		//	VkBufferUsageFlags	usage;
3212 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode		sharingMode;
3213 		1u,										//	deUint32			queueFamilyCount;
3214 		&queueFamilyIndex,						//	const deUint32*		pQueueFamilyIndices;
3215 	};
3216 	const Unique<VkBuffer>					vertexBuffer			(createBuffer(vk, device, &vertexBufferParams));
3217 	const UniquePtr<Allocation>				vertexBufferMemory		(allocator.allocate(getBufferMemoryRequirements(vk, device, *vertexBuffer), MemoryRequirement::HostVisible));
3218 
3219 	VK_CHECK(vk.bindBufferMemory(device, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
3220 
3221 	const VkDeviceSize						imageSizeBytes			= (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y());
3222 	const VkBufferCreateInfo				readImageBufferParams	=
3223 	{
3224 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
3225 		DE_NULL,									//	const void*			pNext;
3226 		0u,											//	VkBufferCreateFlags	flags;
3227 		imageSizeBytes,								//	VkDeviceSize		size;
3228 		VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//	VkBufferUsageFlags	usage;
3229 		VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
3230 		1u,											//	deUint32			queueFamilyCount;
3231 		&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
3232 	};
3233 	const Unique<VkBuffer>					readImageBuffer			(createBuffer(vk, device, &readImageBufferParams));
3234 	const UniquePtr<Allocation>				readImageBufferMemory	(allocator.allocate(getBufferMemoryRequirements(vk, device, *readImageBuffer), MemoryRequirement::HostVisible));
3235 
3236 	VK_CHECK(vk.bindBufferMemory(device, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
3237 
3238 	VkImageCreateInfo						imageParams				=
3239 	{
3240 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									//	VkStructureType		sType;
3241 		DE_NULL,																//	const void*			pNext;
3242 		0u,																		//	VkImageCreateFlags	flags;
3243 		VK_IMAGE_TYPE_2D,														//	VkImageType			imageType;
3244 		VK_FORMAT_R8G8B8A8_UNORM,												//	VkFormat			format;
3245 		{ renderSize.x(), renderSize.y(), 1 },									//	VkExtent3D			extent;
3246 		1u,																		//	deUint32			mipLevels;
3247 		1u,																		//	deUint32			arraySize;
3248 		VK_SAMPLE_COUNT_1_BIT,													//	deUint32			samples;
3249 		VK_IMAGE_TILING_OPTIMAL,												//	VkImageTiling		tiling;
3250 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	//	VkImageUsageFlags	usage;
3251 		VK_SHARING_MODE_EXCLUSIVE,												//	VkSharingMode		sharingMode;
3252 		1u,																		//	deUint32			queueFamilyCount;
3253 		&queueFamilyIndex,														//	const deUint32*		pQueueFamilyIndices;
3254 		VK_IMAGE_LAYOUT_UNDEFINED,												//	VkImageLayout		initialLayout;
3255 	};
3256 
3257 	const Unique<VkImage>					image					(createImage(vk, device, &imageParams));
3258 	const UniquePtr<Allocation>				imageMemory				(allocator.allocate(getImageMemoryRequirements(vk, device, *image), MemoryRequirement::Any));
3259 
3260 	VK_CHECK(vk.bindImageMemory(device, *image, imageMemory->getMemory(), imageMemory->getOffset()));
3261 
3262 	if (needInterface)
3263 	{
3264 		// The pipeline renders four triangles, each with three vertexes.
3265 		// Test instantialization only provides four data points, each
3266 		// for one triangle. So we need allocate space of three times of
3267 		// input buffer's size.
3268 		vector<deUint8>							inputBufferBytes;
3269 		instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
3270 
3271 		const deUint32							inputNumBytes			= deUint32(inputBufferBytes.size() * 3);
3272 		// Create an additional buffer and backing memory for one input variable.
3273 		const VkBufferCreateInfo				vertexInputParams		=
3274 		{
3275 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
3276 			DE_NULL,									//	const void*			pNext;
3277 			0u,											//	VkBufferCreateFlags	flags;
3278 			inputNumBytes,								//	VkDeviceSize		size;
3279 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			//	VkBufferUsageFlags	usage;
3280 			VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
3281 			1u,											//	deUint32			queueFamilyCount;
3282 			&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
3283 		};
3284 
3285 		vertexInputBuffer = createBuffer(vk, device, &vertexInputParams);
3286 		vertexInputMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *vertexInputBuffer), MemoryRequirement::HostVisible);
3287 		VK_CHECK(vk.bindBufferMemory(device, *vertexInputBuffer, vertexInputMemory->getMemory(), vertexInputMemory->getOffset()));
3288 
3289 		// Create an additional buffer and backing memory for an output variable.
3290 		const VkDeviceSize						fragOutputImgSize		= (VkDeviceSize)(instance.interfaces.getOutputType().getNumBytes() * renderSize.x() * renderSize.y());
3291 		const VkBufferCreateInfo				fragOutputParams		=
3292 		{
3293 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
3294 			DE_NULL,									//	const void*			pNext;
3295 			0u,											//	VkBufferCreateFlags	flags;
3296 			fragOutputImgSize,							//	VkDeviceSize		size;
3297 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//	VkBufferUsageFlags	usage;
3298 			VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
3299 			1u,											//	deUint32			queueFamilyCount;
3300 			&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
3301 		};
3302 		fragOutputBuffer = createBuffer(vk, device, &fragOutputParams);
3303 		fragOutputMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *fragOutputBuffer), MemoryRequirement::HostVisible);
3304 		VK_CHECK(vk.bindBufferMemory(device, *fragOutputBuffer, fragOutputMemory->getMemory(), fragOutputMemory->getOffset()));
3305 
3306 		// Create an additional image and backing memory for attachment.
3307 		// Reuse the previous imageParams since we only need to change the image format.
3308 		imageParams.format		= instance.interfaces.getOutputType().getVkFormat();
3309 
3310 		// Check the usage bits on the given image format are supported.
3311 		requireFormatUsageSupport(vkInstance, vkPhysicalDevice, imageParams.format, imageParams.tiling, imageParams.usage);
3312 
3313 		fragOutputImage			= createImage(vk, device, &imageParams);
3314 		fragOutputImageMemory	= allocator.allocate(getImageMemoryRequirements(vk, device, *fragOutputImage), MemoryRequirement::Any);
3315 
3316 		VK_CHECK(vk.bindImageMemory(device, *fragOutputImage, fragOutputImageMemory->getMemory(), fragOutputImageMemory->getOffset()));
3317 	}
3318 
3319 	vector<VkAttachmentDescription>			colorAttDescs;
3320 	vector<VkAttachmentReference>			colorAttRefs;
3321 	{
3322 		const VkAttachmentDescription		attDesc					=
3323 		{
3324 			0u,												//	VkAttachmentDescriptionFlags	flags;
3325 			VK_FORMAT_R8G8B8A8_UNORM,						//	VkFormat						format;
3326 			VK_SAMPLE_COUNT_1_BIT,							//	deUint32						samples;
3327 			VK_ATTACHMENT_LOAD_OP_CLEAR,					//	VkAttachmentLoadOp				loadOp;
3328 			VK_ATTACHMENT_STORE_OP_STORE,					//	VkAttachmentStoreOp				storeOp;
3329 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,				//	VkAttachmentLoadOp				stencilLoadOp;
3330 			VK_ATTACHMENT_STORE_OP_DONT_CARE,				//	VkAttachmentStoreOp				stencilStoreOp;
3331 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout					initialLayout;
3332 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout					finalLayout;
3333 		};
3334 		colorAttDescs.push_back(attDesc);
3335 
3336 		const VkAttachmentReference			attRef					=
3337 		{
3338 			0u,												//	deUint32		attachment;
3339 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout	layout;
3340 		};
3341 		colorAttRefs.push_back(attRef);
3342 	}
3343 
3344 	if (needInterface)
3345 	{
3346 		const VkAttachmentDescription		attDesc					=
3347 		{
3348 			0u,													//	VkAttachmentDescriptionFlags	flags;
3349 			instance.interfaces.getOutputType().getVkFormat(),	//	VkFormat						format;
3350 			VK_SAMPLE_COUNT_1_BIT,								//	deUint32						samples;
3351 			VK_ATTACHMENT_LOAD_OP_CLEAR,						//	VkAttachmentLoadOp				loadOp;
3352 			VK_ATTACHMENT_STORE_OP_STORE,						//	VkAttachmentStoreOp				storeOp;
3353 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					//	VkAttachmentLoadOp				stencilLoadOp;
3354 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					//	VkAttachmentStoreOp				stencilStoreOp;
3355 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			//	VkImageLayout					initialLayout;
3356 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			//	VkImageLayout					finalLayout;
3357 		};
3358 		colorAttDescs.push_back(attDesc);
3359 
3360 		const VkAttachmentReference			attRef					=
3361 		{
3362 			1u,												//	deUint32		attachment;
3363 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout	layout;
3364 		};
3365 		colorAttRefs.push_back(attRef);
3366 	}
3367 
3368 	VkSubpassDescription					subpassDesc				=
3369 	{
3370 		0u,												//	VkSubpassDescriptionFlags		flags;
3371 		VK_PIPELINE_BIND_POINT_GRAPHICS,				//	VkPipelineBindPoint				pipelineBindPoint;
3372 		0u,												//	deUint32						inputCount;
3373 		DE_NULL,										//	const VkAttachmentReference*	pInputAttachments;
3374 		1u,												//	deUint32						colorCount;
3375 		colorAttRefs.data(),							//	const VkAttachmentReference*	pColorAttachments;
3376 		DE_NULL,										//	const VkAttachmentReference*	pResolveAttachments;
3377 		DE_NULL,										//	const VkAttachmentReference*	pDepthStencilAttachment;
3378 		0u,												//	deUint32						preserveCount;
3379 		DE_NULL,										//	const VkAttachmentReference*	pPreserveAttachments;
3380 
3381 	};
3382 	VkRenderPassCreateInfo					renderPassParams		=
3383 	{
3384 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,		//	VkStructureType					sType;
3385 		DE_NULL,										//	const void*						pNext;
3386 		(VkRenderPassCreateFlags)0,
3387 		1u,												//	deUint32						attachmentCount;
3388 		colorAttDescs.data(),							//	const VkAttachmentDescription*	pAttachments;
3389 		1u,												//	deUint32						subpassCount;
3390 		&subpassDesc,									//	const VkSubpassDescription*		pSubpasses;
3391 		0u,												//	deUint32						dependencyCount;
3392 		DE_NULL,										//	const VkSubpassDependency*		pDependencies;
3393 	};
3394 
3395 	if (needInterface)
3396 	{
3397 		subpassDesc.colorAttachmentCount += 1;
3398 		renderPassParams.attachmentCount += 1;
3399 	}
3400 
3401 	const Unique<VkRenderPass>				renderPass				(createRenderPass(vk, device, &renderPassParams));
3402 
3403 	const VkImageViewCreateInfo				colorAttViewParams		=
3404 	{
3405 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		//	VkStructureType				sType;
3406 		DE_NULL,										//	const void*					pNext;
3407 		0u,												//	VkImageViewCreateFlags		flags;
3408 		*image,											//	VkImage						image;
3409 		VK_IMAGE_VIEW_TYPE_2D,							//	VkImageViewType				viewType;
3410 		VK_FORMAT_R8G8B8A8_UNORM,						//	VkFormat					format;
3411 		{
3412 			VK_COMPONENT_SWIZZLE_R,
3413 			VK_COMPONENT_SWIZZLE_G,
3414 			VK_COMPONENT_SWIZZLE_B,
3415 			VK_COMPONENT_SWIZZLE_A
3416 		},												//	VkChannelMapping			channels;
3417 		{
3418 			VK_IMAGE_ASPECT_COLOR_BIT,						//	VkImageAspectFlags	aspectMask;
3419 			0u,												//	deUint32			baseMipLevel;
3420 			1u,												//	deUint32			mipLevels;
3421 			0u,												//	deUint32			baseArrayLayer;
3422 			1u,												//	deUint32			arraySize;
3423 		},												//	VkImageSubresourceRange		subresourceRange;
3424 	};
3425 	const Unique<VkImageView>				colorAttView			(createImageView(vk, device, &colorAttViewParams));
3426 	const VkImageAspectFlags				inputImageAspect		= getImageAspectFlags(instance.resources.inputFormat);
3427 
3428 	vector<VkImageView>						attViews;
3429 	attViews.push_back(*colorAttView);
3430 
3431 	// Handle resources requested by the test instantiation.
3432 	const deUint32							numInResources			= static_cast<deUint32>(instance.resources.inputs.size());
3433 	const deUint32							numOutResources			= static_cast<deUint32>(instance.resources.outputs.size());
3434 	// These variables should be placed out of the following if block to avoid deallocation after out of scope.
3435 	vector<AllocationSp>					inResourceMemories;
3436 	vector<AllocationSp>					outResourceMemories;
3437 	vector<BufferHandleSp>					inResourceBuffers;
3438 	vector<BufferHandleSp>					outResourceBuffers;
3439 	vector<ImageHandleSp>					inResourceImages;
3440 	vector<ImageViewHandleSp>				inResourceImageViews;
3441 	vector<SamplerHandleSp>					inResourceSamplers;
3442 	Move<VkDescriptorPool>					descriptorPool;
3443 	Move<VkDescriptorSetLayout>				setLayout;
3444 	VkDescriptorSetLayout					rawSetLayout			= DE_NULL;
3445 	VkDescriptorSet							rawSet					= DE_NULL;
3446 
3447 	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
3448 
3449 	// Command buffer
3450 	const Unique<VkCommandBuffer>			cmdBuf					(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3451 
3452 	if (numResources != 0)
3453 	{
3454 		vector<VkDescriptorSetLayoutBinding>	setLayoutBindings;
3455 		vector<VkDescriptorPoolSize>			poolSizes;
3456 
3457 		setLayoutBindings.reserve(numResources);
3458 		poolSizes.reserve(numResources);
3459 
3460 		// Process all input resources.
3461 		for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
3462 		{
3463 			const Resource&	resource	= instance.resources.inputs[inputNdx];
3464 
3465 			const bool		hasImage	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)	||
3466 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3467 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3468 
3469 			const bool		hasSampler	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3470 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLER)			||
3471 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3472 
3473 			// Resource is a buffer
3474 			if (!hasImage && !hasSampler)
3475 			{
3476 				Move<VkBuffer>					resourceBuffer			= createBufferForResource(vk, device, resource, queueFamilyIndex);
3477 				de::MovePtr<Allocation>			resourceMemory			= allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3478 
3479 				VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3480 
3481 				// Copy data to memory.
3482 				{
3483 					vector<deUint8>					resourceBytes;
3484 					resource.getBytes(resourceBytes);
3485 
3486 					deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
3487 					flushAlloc(vk, device, *resourceMemory);
3488 				}
3489 
3490 				inResourceMemories.push_back(AllocationSp(resourceMemory.release()));
3491 				inResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
3492 			}
3493 			// Resource is an image
3494 			else if (hasImage)
3495 			{
3496 				Move<VkBuffer>					resourceBuffer			= createBufferForResource(vk, device, resource, queueFamilyIndex);
3497 				de::MovePtr<Allocation>			resourceMemory			= allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3498 
3499 				VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3500 
3501 				// Copy data to memory.
3502 				{
3503 					vector<deUint8>					resourceBytes;
3504 					resource.getBytes(resourceBytes);
3505 
3506 					deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
3507 					flushAlloc(vk, device, *resourceMemory);
3508 				}
3509 
3510 				Move<VkImage>					resourceImage			= createImageForResource(vk, device, resource, instance.resources.inputFormat, queueFamilyIndex);
3511 				de::MovePtr<Allocation>			resourceImageMemory		= allocator.allocate(getImageMemoryRequirements(vk, device, *resourceImage), MemoryRequirement::Any);
3512 
3513 				VK_CHECK(vk.bindImageMemory(device, *resourceImage, resourceImageMemory->getMemory(), resourceImageMemory->getOffset()));
3514 
3515 				copyBufferToImage(vk, device, queue, *cmdBuf, resourceBuffer.get(), resourceImage.get(), inputImageAspect);
3516 
3517 				inResourceMemories.push_back(AllocationSp(resourceImageMemory.release()));
3518 				inResourceImages.push_back(ImageHandleSp(new ImageHandleUp(resourceImage)));
3519 			}
3520 
3521 			// Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool.
3522 			const VkDescriptorSetLayoutBinding	binding				=
3523 			{
3524 				inputNdx,											// binding
3525 				resource.getDescriptorType(),						// descriptorType
3526 				1u,													// descriptorCount
3527 				VK_SHADER_STAGE_ALL_GRAPHICS,						// stageFlags
3528 				DE_NULL,											// pImmutableSamplers
3529 			};
3530 			setLayoutBindings.push_back(binding);
3531 
3532 			// Note: the following code doesn't check and unify descriptors of the same type.
3533 			const VkDescriptorPoolSize		poolSize				=
3534 			{
3535 				resource.getDescriptorType(),						// type
3536 				1u,													// descriptorCount
3537 			};
3538 			poolSizes.push_back(poolSize);
3539 		}
3540 
3541 		// Process all output resources.
3542 		for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
3543 		{
3544 			const Resource&					resource				= instance.resources.outputs[outputNdx];
3545 			// Create buffer and allocate memory.
3546 			Move<VkBuffer>					resourceBuffer			= createBufferForResource(vk, device, resource, queueFamilyIndex);
3547 			de::MovePtr<Allocation>			resourceMemory			= allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3548 			vector<deUint8>					resourceBytes;
3549 
3550 			VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3551 
3552 			// Fill memory with all ones.
3553 			resource.getBytes(resourceBytes);
3554 			deMemset((deUint8*)resourceMemory->getHostPtr(), 0xff, resourceBytes.size());
3555 			flushAlloc(vk, device, *resourceMemory);
3556 
3557 			outResourceMemories.push_back(AllocationSp(resourceMemory.release()));
3558 			outResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
3559 
3560 			// Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool.
3561 			const VkDescriptorSetLayoutBinding	binding				=
3562 			{
3563 				numInResources  + outputNdx,						// binding
3564 				resource.getDescriptorType(),						// descriptorType
3565 				1u,													// descriptorCount
3566 				VK_SHADER_STAGE_ALL_GRAPHICS,						// stageFlags
3567 				DE_NULL,											// pImmutableSamplers
3568 			};
3569 			setLayoutBindings.push_back(binding);
3570 
3571 			// Note: the following code doesn't check and unify descriptors of the same type.
3572 			const VkDescriptorPoolSize		poolSize				=
3573 			{
3574 				resource.getDescriptorType(),						// type
3575 				1u,													// descriptorCount
3576 			};
3577 			poolSizes.push_back(poolSize);
3578 		}
3579 
3580 		// Create descriptor set layout, descriptor pool, and allocate descriptor set.
3581 		const VkDescriptorSetLayoutCreateInfo	setLayoutParams		=
3582 		{
3583 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
3584 			DE_NULL,												// pNext
3585 			(VkDescriptorSetLayoutCreateFlags)0,					// flags
3586 			numResources,											// bindingCount
3587 			setLayoutBindings.data(),								// pBindings
3588 		};
3589 		setLayout													= createDescriptorSetLayout(vk, device, &setLayoutParams);
3590 		rawSetLayout												= *setLayout;
3591 
3592 		const VkDescriptorPoolCreateInfo		poolParams			=
3593 		{
3594 			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,			// sType
3595 			DE_NULL,												// pNext
3596 			(VkDescriptorPoolCreateFlags)0,							// flags
3597 			1u,														// maxSets
3598 			numResources,											// poolSizeCount
3599 			poolSizes.data(),										// pPoolSizes
3600 		};
3601 		descriptorPool												= createDescriptorPool(vk, device, &poolParams);
3602 
3603 		const VkDescriptorSetAllocateInfo		setAllocParams		=
3604 		{
3605 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			// sType
3606 			DE_NULL,												// pNext
3607 			*descriptorPool,										// descriptorPool
3608 			1u,														// descriptorSetCount
3609 			&rawSetLayout,											// pSetLayouts
3610 		};
3611 		VK_CHECK(vk.allocateDescriptorSets(device, &setAllocParams, &rawSet));
3612 
3613 		// Update descriptor set.
3614 		vector<VkWriteDescriptorSet>			writeSpecs;
3615 		vector<VkDescriptorBufferInfo>			dBufferInfos;
3616 		vector<VkDescriptorImageInfo>			dImageInfos;
3617 
3618 		writeSpecs.reserve(numResources);
3619 		dBufferInfos.reserve(numResources);
3620 		dImageInfos.reserve(numResources);
3621 
3622 		deUint32								imgResourceNdx		= 0u;
3623 		deUint32								bufResourceNdx		= 0u;
3624 
3625 		for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
3626 		{
3627 			const Resource&	resource	= instance.resources.inputs[inputNdx];
3628 
3629 			const bool		hasImage	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)	||
3630 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3631 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3632 
3633 			const bool		hasSampler	= (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)	||
3634 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLER)			||
3635 										  (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3636 
3637 			// Create image view and sampler
3638 			if (hasImage || hasSampler)
3639 			{
3640 				if (resource.getDescriptorType() != VK_DESCRIPTOR_TYPE_SAMPLER)
3641 				{
3642 					const VkImageViewCreateInfo	imgViewParams	=
3643 					{
3644 						VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	//	VkStructureType				sType;
3645 						DE_NULL,									//	const void*					pNext;
3646 						0u,											//	VkImageViewCreateFlags		flags;
3647 						**inResourceImages[imgResourceNdx++],		//	VkImage						image;
3648 						VK_IMAGE_VIEW_TYPE_2D,						//	VkImageViewType				viewType;
3649 						instance.resources.inputFormat,				//	VkFormat					format;
3650 						{
3651 							VK_COMPONENT_SWIZZLE_R,
3652 							VK_COMPONENT_SWIZZLE_G,
3653 							VK_COMPONENT_SWIZZLE_B,
3654 							VK_COMPONENT_SWIZZLE_A
3655 						},											//	VkComponentMapping			channels;
3656 						{
3657 							inputImageAspect,	//	VkImageAspectFlags	aspectMask;
3658 							0u,					//	deUint32			baseMipLevel;
3659 							1u,					//	deUint32			mipLevels;
3660 							0u,					//	deUint32			baseArrayLayer;
3661 							1u,					//	deUint32			arraySize;
3662 						},											//	VkImageSubresourceRange		subresourceRange;
3663 					};
3664 
3665 					Move<VkImageView>			imgView			(createImageView(vk, device, &imgViewParams));
3666 					inResourceImageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imgView)));
3667 				}
3668 
3669 				if (hasSampler)
3670 				{
3671 					const bool					hasDepthComponent	= tcu::hasDepthComponent(vk::mapVkFormat(instance.resources.inputFormat).order);
3672 					const VkSamplerCreateInfo	samplerParams		=
3673 					{
3674 						VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType			sType;
3675 						DE_NULL,									// const void*				pNext;
3676 						0,											// VkSamplerCreateFlags		flags;
3677 						VK_FILTER_NEAREST,							// VkFilter					magFilter:
3678 						VK_FILTER_NEAREST,							// VkFilter					minFilter;
3679 						VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode		mipmapMode;
3680 						VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeU;
3681 						VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeV;
3682 						VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// VkSamplerAddressMode		addressModeW;
3683 						0.0f,										// float					mipLodBias;
3684 						VK_FALSE,									// VkBool32					anistoropyEnable;
3685 						1.0f,										// float					maxAnisotropy;
3686 						(hasDepthComponent) ? VK_TRUE : VK_FALSE,	// VkBool32					compareEnable;
3687 						VK_COMPARE_OP_LESS,							// VkCompareOp				compareOp;
3688 						0.0f,										// float					minLod;
3689 						0.0f,										// float					maxLod;
3690 						VK_BORDER_COLOR_INT_OPAQUE_BLACK,			// VkBorderColor			borderColor;
3691 						VK_FALSE									// VkBool32					unnormalizedCoordinates;
3692 					};
3693 
3694 					Move<VkSampler>				sampler			(createSampler(vk, device, &samplerParams));
3695 					inResourceSamplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
3696 				}
3697 			}
3698 
3699 			// Create descriptor buffer and image infos
3700 			switch (resource.getDescriptorType())
3701 			{
3702 				case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
3703 				case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
3704 				{
3705 					const VkDescriptorBufferInfo	bufInfo	=
3706 					{
3707 						**inResourceBuffers[bufResourceNdx++],				// buffer
3708 						0,													// offset
3709 						VK_WHOLE_SIZE,										// size
3710 					};
3711 					dBufferInfos.push_back(bufInfo);
3712 					break;
3713 				}
3714 				case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
3715 				case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
3716 				{
3717 					const VkDescriptorImageInfo		imgInfo	=
3718 					{
3719 						DE_NULL,												// sampler
3720 						**inResourceImageViews.back(),							// imageView
3721 						VK_IMAGE_LAYOUT_GENERAL									// imageLayout
3722 					};
3723 					dImageInfos.push_back(imgInfo);
3724 					break;
3725 				}
3726 				case VK_DESCRIPTOR_TYPE_SAMPLER:
3727 				{
3728 					const VkDescriptorImageInfo		imgInfo	=
3729 					{
3730 						**inResourceSamplers.back(),							// sampler
3731 						DE_NULL,												// imageView
3732 						VK_IMAGE_LAYOUT_GENERAL									// imageLayout
3733 					};
3734 					dImageInfos.push_back(imgInfo);
3735 					break;
3736 				}
3737 				case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
3738 				{
3739 
3740 					const VkDescriptorImageInfo		imgInfo	=
3741 					{
3742 						**inResourceSamplers.back(),							// sampler
3743 						**inResourceImageViews.back(),							// imageView
3744 						VK_IMAGE_LAYOUT_GENERAL									// imageLayout
3745 					};
3746 					dImageInfos.push_back(imgInfo);
3747 					break;
3748 				}
3749 				default:
3750 					DE_FATAL("Not implemented");
3751 			}
3752 
3753 			const VkWriteDescriptorSet			writeSpec			= {
3754 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,							// sType
3755 				DE_NULL,														// pNext
3756 				rawSet,															// dstSet
3757 				inputNdx,														// binding
3758 				0,																// dstArrayElement
3759 				1u,																// descriptorCount
3760 				instance.resources.inputs[inputNdx].getDescriptorType(),		// descriptorType
3761 				( (hasImage | hasSampler)	? &dImageInfos.back()	: DE_NULL),	// pImageInfo
3762 				(!(hasImage | hasSampler)	? &dBufferInfos.back()	: DE_NULL),	// pBufferInfo
3763 				DE_NULL,														// pTexelBufferView
3764 			};
3765 			writeSpecs.push_back(writeSpec);
3766 		}
3767 
3768 		for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
3769 		{
3770 			const VkDescriptorBufferInfo		bufInfo				=
3771 			{
3772 				**outResourceBuffers[outputNdx],					// buffer
3773 				0,													// offset
3774 				VK_WHOLE_SIZE,										// size
3775 			};
3776 			dBufferInfos.push_back(bufInfo);
3777 
3778 			const VkWriteDescriptorSet			writeSpec			= {
3779 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,						// sType
3780 				DE_NULL,													// pNext
3781 				rawSet,														// dstSet
3782 				numInResources + outputNdx,									// binding
3783 				0,															// dstArrayElement
3784 				1u,															// descriptorCount
3785 				instance.resources.outputs[outputNdx].getDescriptorType(),	// descriptorType
3786 				DE_NULL,													// pImageInfo
3787 				&dBufferInfos.back(),										// pBufferInfo
3788 				DE_NULL,													// pTexelBufferView
3789 			};
3790 			writeSpecs.push_back(writeSpec);
3791 		}
3792 		vk.updateDescriptorSets(device, numResources, writeSpecs.data(), 0, DE_NULL);
3793 	}
3794 
3795 	// Pipeline layout
3796 	VkPipelineLayoutCreateInfo				pipelineLayoutParams	=
3797 	{
3798 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,			//	VkStructureType					sType;
3799 		DE_NULL,												//	const void*						pNext;
3800 		(VkPipelineLayoutCreateFlags)0,
3801 		0u,														//	deUint32						descriptorSetCount;
3802 		DE_NULL,												//	const VkDescriptorSetLayout*	pSetLayouts;
3803 		0u,														//	deUint32						pushConstantRangeCount;
3804 		DE_NULL,												//	const VkPushConstantRange*		pPushConstantRanges;
3805 	};
3806 
3807 	VkPushConstantRange						pushConstantRange		=
3808 	{
3809 		VK_SHADER_STAGE_ALL_GRAPHICS,							// VkShaderStageFlags    stageFlags;
3810 		0,														// uint32_t              offset;
3811 		0,														// uint32_t              size;
3812 	};
3813 	if (hasPushConstants)
3814 	{
3815 		vector<deUint8> pushConstantsBytes;
3816 		instance.pushConstants.getBuffer()->getBytes(pushConstantsBytes);
3817 
3818 		pushConstantRange.size						= static_cast<deUint32>(pushConstantsBytes.size());
3819 		pipelineLayoutParams.pushConstantRangeCount	= 1;
3820 		pipelineLayoutParams.pPushConstantRanges	= &pushConstantRange;
3821 	}
3822 	if (numResources != 0)
3823 	{
3824 		// Update pipeline layout with the descriptor set layout.
3825 		pipelineLayoutParams.setLayoutCount								= 1;
3826 		pipelineLayoutParams.pSetLayouts								= &rawSetLayout;
3827 	}
3828 	const Unique<VkPipelineLayout>			pipelineLayout			(createPipelineLayout(vk, device, &pipelineLayoutParams));
3829 
3830 	// Pipeline
3831 	vector<VkPipelineShaderStageCreateInfo>		shaderStageParams;
3832 	// We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline().
3833 	vector<vector<VkSpecializationMapEntry> >	specConstantEntries;
3834 	vector<VkSpecializationInfo>				specializationInfos;
3835 	if (DE_NULL != instance.resources.verifyBinary)
3836 	{
3837 		std::string shaderName;
3838 		switch(instance.customizedStages)
3839 		{
3840 		case	VK_SHADER_STAGE_VERTEX_BIT:
3841 			shaderName= "vert";
3842 			break;
3843 		case	VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
3844 			shaderName= "tessc";
3845 			break;
3846 		case	VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
3847 			shaderName= "tesse";
3848 			break;
3849 		case	VK_SHADER_STAGE_GEOMETRY_BIT:
3850 			shaderName= "geom";
3851 			break;
3852 		case	VK_SHADER_STAGE_FRAGMENT_BIT:
3853 			shaderName= "frag";
3854 			break;
3855 		default:
3856 			DE_ASSERT(0);
3857 			break;
3858 		}
3859 		const ProgramBinary& binary  = context.getBinaryCollection().get(shaderName);
3860 		if (!instance.resources.verifyBinary(binary))
3861 			return tcu::TestStatus::fail("Binary verification of SPIR-V in the test failed");
3862 
3863 	}
3864 	createPipelineShaderStages(vk, device, instance, context, modules, shaderStageParams);
3865 
3866 	// And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents.
3867 	specConstantEntries.reserve(shaderStageParams.size());
3868 	specializationInfos.reserve(shaderStageParams.size());
3869 
3870 	// Patch the specialization info field in PipelineShaderStageCreateInfos.
3871 	for (vector<VkPipelineShaderStageCreateInfo>::iterator stageInfo = shaderStageParams.begin(); stageInfo != shaderStageParams.end(); ++stageInfo)
3872 	{
3873 		const StageToSpecConstantMap::const_iterator stageIt = instance.specConstants.find(stageInfo->stage);
3874 
3875 		if (stageIt != instance.specConstants.end())
3876 		{
3877 			const size_t						numSpecConstants	= stageIt->second.getValuesCount();
3878 			vector<VkSpecializationMapEntry>	entries;
3879 			VkSpecializationInfo				specInfo;
3880 			size_t								offset				= 0;
3881 
3882 			entries.resize(numSpecConstants);
3883 
3884 			// Constant IDs are numbered sequentially starting from 0.
3885 			for (size_t ndx = 0; ndx < numSpecConstants; ++ndx)
3886 			{
3887 				const size_t valueSize	= stageIt->second.getValueSize(ndx);
3888 
3889 				entries[ndx].constantID	= (deUint32)ndx;
3890 				entries[ndx].offset		= static_cast<deUint32>(offset);
3891 				entries[ndx].size		= valueSize;
3892 
3893 				offset					+= valueSize;
3894 			}
3895 
3896 			specConstantEntries.push_back(entries);
3897 
3898 			specInfo.mapEntryCount	= (deUint32)numSpecConstants;
3899 			specInfo.pMapEntries	= specConstantEntries.back().data();
3900 			specInfo.dataSize		= offset;
3901 			specInfo.pData			= stageIt->second.getValuesBuffer();
3902 			specializationInfos.push_back(specInfo);
3903 
3904 			stageInfo->pSpecializationInfo = &specializationInfos.back();
3905 		}
3906 	}
3907 	const VkPipelineDepthStencilStateCreateInfo	depthStencilParams		=
3908 	{
3909 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	//	VkStructureType		sType;
3910 		DE_NULL,													//	const void*			pNext;
3911 		(VkPipelineDepthStencilStateCreateFlags)0,
3912 		DE_FALSE,													//	deUint32			depthTestEnable;
3913 		DE_FALSE,													//	deUint32			depthWriteEnable;
3914 		VK_COMPARE_OP_ALWAYS,										//	VkCompareOp			depthCompareOp;
3915 		DE_FALSE,													//	deUint32			depthBoundsTestEnable;
3916 		DE_FALSE,													//	deUint32			stencilTestEnable;
3917 		{
3918 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilFailOp;
3919 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilPassOp;
3920 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilDepthFailOp;
3921 			VK_COMPARE_OP_ALWAYS,										//	VkCompareOp	stencilCompareOp;
3922 			0u,															//	deUint32	stencilCompareMask;
3923 			0u,															//	deUint32	stencilWriteMask;
3924 			0u,															//	deUint32	stencilReference;
3925 		},															//	VkStencilOpState	front;
3926 		{
3927 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilFailOp;
3928 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilPassOp;
3929 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilDepthFailOp;
3930 			VK_COMPARE_OP_ALWAYS,										//	VkCompareOp	stencilCompareOp;
3931 			0u,															//	deUint32	stencilCompareMask;
3932 			0u,															//	deUint32	stencilWriteMask;
3933 			0u,															//	deUint32	stencilReference;
3934 		},															//	VkStencilOpState	back;
3935 		-1.0f,														//	float				minDepthBounds;
3936 		+1.0f,														//	float				maxDepthBounds;
3937 	};
3938 	const VkViewport							viewport0				= makeViewport(renderSize);
3939 	const VkRect2D								scissor0				= makeRect2D(0u, 0u);
3940 	const VkPipelineViewportStateCreateInfo		viewportParams			=
3941 	{
3942 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,		//	VkStructureType		sType;
3943 		DE_NULL,													//	const void*			pNext;
3944 		(VkPipelineViewportStateCreateFlags)0,
3945 		1u,															//	deUint32			viewportCount;
3946 		&viewport0,
3947 		1u,
3948 		&scissor0
3949 	};
3950 	const VkSampleMask							sampleMask				= ~0u;
3951 	const VkPipelineMultisampleStateCreateInfo	multisampleParams		=
3952 	{
3953 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType			sType;
3954 		DE_NULL,													//	const void*				pNext;
3955 		(VkPipelineMultisampleStateCreateFlags)0,
3956 		VK_SAMPLE_COUNT_1_BIT,										//	VkSampleCountFlagBits	rasterSamples;
3957 		DE_FALSE,													//	deUint32				sampleShadingEnable;
3958 		0.0f,														//	float					minSampleShading;
3959 		&sampleMask,												//	const VkSampleMask*		pSampleMask;
3960 		DE_FALSE,													//	VkBool32				alphaToCoverageEnable;
3961 		DE_FALSE,													//	VkBool32				alphaToOneEnable;
3962 	};
3963 	const VkPipelineRasterizationStateCreateInfo	rasterParams		=
3964 	{
3965 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType	sType;
3966 		DE_NULL,													//	const void*		pNext;
3967 		(VkPipelineRasterizationStateCreateFlags)0,
3968 		DE_FALSE,													//	deUint32		depthClampEnable;
3969 		DE_FALSE,													//	deUint32		rasterizerDiscardEnable;
3970 		VK_POLYGON_MODE_FILL,										//	VkFillMode		fillMode;
3971 		VK_CULL_MODE_NONE,											//	VkCullMode		cullMode;
3972 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							//	VkFrontFace		frontFace;
3973 		VK_FALSE,													//	VkBool32		depthBiasEnable;
3974 		0.0f,														//	float			depthBias;
3975 		0.0f,														//	float			depthBiasClamp;
3976 		0.0f,														//	float			slopeScaledDepthBias;
3977 		1.0f,														//	float			lineWidth;
3978 	};
3979 	const VkPrimitiveTopology topology = hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
3980 	const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyParams	=
3981 	{
3982 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	//	VkStructureType		sType;
3983 		DE_NULL,														//	const void*			pNext;
3984 		(VkPipelineInputAssemblyStateCreateFlags)0,
3985 		topology,														//	VkPrimitiveTopology	topology;
3986 		DE_FALSE,														//	deUint32			primitiveRestartEnable;
3987 	};
3988 
3989 	vector<VkVertexInputBindingDescription>		vertexBindings;
3990 	vector<VkVertexInputAttributeDescription>	vertexAttribs;
3991 
3992 	const VkVertexInputBindingDescription		vertexBinding0			=
3993 	{
3994 		0u,									// deUint32					binding;
3995 		deUint32(singleVertexDataSize),		// deUint32					strideInBytes;
3996 		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	stepRate;
3997 	};
3998 	vertexBindings.push_back(vertexBinding0);
3999 
4000 	{
4001 		VkVertexInputAttributeDescription		attr0					=
4002 		{
4003 			0u,									// deUint32	location;
4004 			0u,									// deUint32	binding;
4005 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
4006 			0u									// deUint32	offsetInBytes;
4007 		};
4008 		vertexAttribs.push_back(attr0);
4009 
4010 		VkVertexInputAttributeDescription		attr1					=
4011 		{
4012 			1u,									// deUint32	location;
4013 			0u,									// deUint32	binding;
4014 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
4015 			sizeof(Vec4),						// deUint32	offsetInBytes;
4016 		};
4017 		vertexAttribs.push_back(attr1);
4018 	};
4019 
4020 	// If the test instantiation has additional input/output interface variables, we need to create additional bindings.
4021 	// Right now we only support one additional input varible for the vertex stage, and that will be bound to binding #1
4022 	// with location #2.
4023 	if (needInterface)
4024 	{
4025 		const VkVertexInputBindingDescription	vertexBinding1			=
4026 		{
4027 			1u,													// deUint32					binding;
4028 			instance.interfaces.getInputType().getNumBytes(),	// deUint32					strideInBytes;
4029 			VK_VERTEX_INPUT_RATE_VERTEX							// VkVertexInputStepRate	stepRate;
4030 		};
4031 		vertexBindings.push_back(vertexBinding1);
4032 
4033 		VkVertexInputAttributeDescription		attr					=
4034 		{
4035 			2u,													// deUint32	location;
4036 			1u,													// deUint32	binding;
4037 			instance.interfaces.getInputType().getVkFormat(),	// VkFormat	format;
4038 			0,													// deUint32	offsetInBytes;
4039 		};
4040 		vertexAttribs.push_back(attr);
4041 	}
4042 
4043 	VkPipelineVertexInputStateCreateInfo		vertexInputStateParams	=
4044 	{
4045 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
4046 		DE_NULL,													//	const void*									pNext;
4047 		(VkPipelineVertexInputStateCreateFlags)0,
4048 		1u,															//	deUint32									bindingCount;
4049 		vertexBindings.data(),										//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
4050 		2u,															//	deUint32									attributeCount;
4051 		vertexAttribs.data(),										//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
4052 	};
4053 
4054 	if (needInterface)
4055 	{
4056 		vertexInputStateParams.vertexBindingDescriptionCount += 1;
4057 		vertexInputStateParams.vertexAttributeDescriptionCount += 1;
4058 	}
4059 
4060 	vector<VkPipelineColorBlendAttachmentState>	attBlendStates;
4061 	const VkPipelineColorBlendAttachmentState	attBlendState			=
4062 	{
4063 		DE_FALSE,													//	deUint32		blendEnable;
4064 		VK_BLEND_FACTOR_ONE,										//	VkBlend			srcBlendColor;
4065 		VK_BLEND_FACTOR_ZERO,										//	VkBlend			destBlendColor;
4066 		VK_BLEND_OP_ADD,											//	VkBlendOp		blendOpColor;
4067 		VK_BLEND_FACTOR_ONE,										//	VkBlend			srcBlendAlpha;
4068 		VK_BLEND_FACTOR_ZERO,										//	VkBlend			destBlendAlpha;
4069 		VK_BLEND_OP_ADD,											//	VkBlendOp		blendOpAlpha;
4070 		(VK_COLOR_COMPONENT_R_BIT|
4071 		 VK_COLOR_COMPONENT_G_BIT|
4072 		 VK_COLOR_COMPONENT_B_BIT|
4073 		 VK_COLOR_COMPONENT_A_BIT),									//	VkChannelFlags	channelWriteMask;
4074 	};
4075 	attBlendStates.push_back(attBlendState);
4076 
4077 	if (needInterface)
4078 		attBlendStates.push_back(attBlendState);
4079 
4080 	VkPipelineColorBlendStateCreateInfo		blendParams				=
4081 	{
4082 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
4083 		DE_NULL,													//	const void*									pNext;
4084 		(VkPipelineColorBlendStateCreateFlags)0,
4085 		DE_FALSE,													//	VkBool32									logicOpEnable;
4086 		VK_LOGIC_OP_COPY,											//	VkLogicOp									logicOp;
4087 		1u,															//	deUint32									attachmentCount;
4088 		attBlendStates.data(),										//	const VkPipelineColorBlendAttachmentState*	pAttachments;
4089 		{ 0.0f, 0.0f, 0.0f, 0.0f },									//	float										blendConst[4];
4090 	};
4091 	if (needInterface)
4092 	{
4093 		blendParams.attachmentCount += 1;
4094 	}
4095 	const VkPipelineTessellationStateCreateInfo	tessellationState	=
4096 	{
4097 		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
4098 		DE_NULL,
4099 		(VkPipelineTessellationStateCreateFlags)0,
4100 		3u
4101 	};
4102 
4103 	const	VkDynamicState							dynamicStates[]				=
4104 	{
4105 		VK_DYNAMIC_STATE_SCISSOR
4106 	};
4107 
4108 	const VkPipelineDynamicStateCreateInfo			dynamicStateCreateInfo =
4109 	{
4110 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,  // sType
4111 		DE_NULL,											   // pNext
4112 		0u,													   // flags
4113 		DE_LENGTH_OF_ARRAY(dynamicStates),					   // dynamicStateCount
4114 		dynamicStates										   // pDynamicStates
4115 	};
4116 
4117 	const VkPipelineTessellationStateCreateInfo* tessellationInfo	=	hasTessellation ? &tessellationState: DE_NULL;
4118 	const VkGraphicsPipelineCreateInfo		pipelineParams			=
4119 	{
4120 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,		//	VkStructureType									sType;
4121 		DE_NULL,												//	const void*										pNext;
4122 		0u,														//	VkPipelineCreateFlags							flags;
4123 		(deUint32)shaderStageParams.size(),						//	deUint32										stageCount;
4124 		&shaderStageParams[0],									//	const VkPipelineShaderStageCreateInfo*			pStages;
4125 		&vertexInputStateParams,								//	const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
4126 		&inputAssemblyParams,									//	const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
4127 		tessellationInfo,										//	const VkPipelineTessellationStateCreateInfo*	pTessellationState;
4128 		&viewportParams,										//	const VkPipelineViewportStateCreateInfo*		pViewportState;
4129 		&rasterParams,											//	const VkPipelineRasterStateCreateInfo*			pRasterState;
4130 		&multisampleParams,										//	const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
4131 		&depthStencilParams,									//	const VkPipelineDepthStencilStateCreateInfo*	pDepthStencilState;
4132 		&blendParams,											//	const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
4133 		&dynamicStateCreateInfo,								//	const VkPipelineDynamicStateCreateInfo*			pDynamicState;
4134 		*pipelineLayout,										//	VkPipelineLayout								layout;
4135 		*renderPass,											//	VkRenderPass									renderPass;
4136 		0u,														//	deUint32										subpass;
4137 		DE_NULL,												//	VkPipeline										basePipelineHandle;
4138 		0u,														//	deInt32											basePipelineIndex;
4139 	};
4140 
4141 	const Unique<VkPipeline>				pipeline				(createGraphicsPipeline(vk, device, DE_NULL, &pipelineParams));
4142 
4143 	if (needInterface)
4144 	{
4145 		const VkImageViewCreateInfo			fragOutputViewParams	=
4146 		{
4147 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			//	VkStructureType				sType;
4148 			DE_NULL,											//	const void*					pNext;
4149 			0u,													//	VkImageViewCreateFlags		flags;
4150 			*fragOutputImage,									//	VkImage						image;
4151 			VK_IMAGE_VIEW_TYPE_2D,								//	VkImageViewType				viewType;
4152 			instance.interfaces.getOutputType().getVkFormat(),	//	VkFormat					format;
4153 			{
4154 				VK_COMPONENT_SWIZZLE_R,
4155 				VK_COMPONENT_SWIZZLE_G,
4156 				VK_COMPONENT_SWIZZLE_B,
4157 				VK_COMPONENT_SWIZZLE_A
4158 			},													//	VkChannelMapping			channels;
4159 			{
4160 				VK_IMAGE_ASPECT_COLOR_BIT,						//	VkImageAspectFlags	aspectMask;
4161 				0u,												//	deUint32			baseMipLevel;
4162 				1u,												//	deUint32			mipLevels;
4163 				0u,												//	deUint32			baseArrayLayer;
4164 				1u,												//	deUint32			arraySize;
4165 			},													//	VkImageSubresourceRange		subresourceRange;
4166 		};
4167 		fragOutputImageView = createImageView(vk, device, &fragOutputViewParams);
4168 		attViews.push_back(*fragOutputImageView);
4169 	}
4170 
4171 	// Framebuffer
4172 	VkFramebufferCreateInfo					framebufferParams		=
4173 	{
4174 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,				//	VkStructureType		sType;
4175 		DE_NULL,												//	const void*			pNext;
4176 		(VkFramebufferCreateFlags)0,
4177 		*renderPass,											//	VkRenderPass		renderPass;
4178 		1u,														//	deUint32			attachmentCount;
4179 		attViews.data(),										//	const VkImageView*	pAttachments;
4180 		(deUint32)renderSize.x(),								//	deUint32			width;
4181 		(deUint32)renderSize.y(),								//	deUint32			height;
4182 		1u,														//	deUint32			layers;
4183 	};
4184 
4185 	if (needInterface)
4186 		framebufferParams.attachmentCount += 1;
4187 
4188 	const Unique<VkFramebuffer>				framebuffer				(createFramebuffer(vk, device, &framebufferParams));
4189 
4190 	bool firstPass = true;
4191 
4192 	for (int x = 0; x < numRenderSegments; x++)
4193 	{
4194 		for (int y = 0; y < numRenderSegments; y++)
4195 		{
4196 			// Record commands
4197 			beginCommandBuffer(vk, *cmdBuf);
4198 
4199 			if (firstPass)
4200 			{
4201 				const VkMemoryBarrier			vertFlushBarrier	=
4202 				{
4203 					VK_STRUCTURE_TYPE_MEMORY_BARRIER,			//	VkStructureType		sType;
4204 					DE_NULL,									//	const void*			pNext;
4205 					VK_ACCESS_HOST_WRITE_BIT,					//	VkMemoryOutputFlags	outputMask;
4206 					VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,		//	VkMemoryInputFlags	inputMask;
4207 				};
4208 				vector<VkImageMemoryBarrier>	colorAttBarriers;
4209 
4210 				VkImageMemoryBarrier			imgBarrier          =
4211 				{
4212 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		//	VkStructureType			sType;
4213 					DE_NULL,									//	const void*				pNext;
4214 					0u,											//	VkMemoryOutputFlags		outputMask;
4215 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		//	VkMemoryInputFlags		inputMask;
4216 					VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout			oldLayout;
4217 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout			newLayout;
4218 					queueFamilyIndex,							//	deUint32				srcQueueFamilyIndex;
4219 					queueFamilyIndex,							//	deUint32				destQueueFamilyIndex;
4220 					*image,										//	VkImage					image;
4221 					{
4222 						VK_IMAGE_ASPECT_COLOR_BIT,					//	VkImageAspect	aspect;
4223 						0u,											//	deUint32		baseMipLevel;
4224 						1u,											//	deUint32		mipLevels;
4225 						0u,											//	deUint32		baseArraySlice;
4226 						1u,											//	deUint32		arraySize;
4227 					}											//	VkImageSubresourceRange	subresourceRange;
4228 				};
4229 				colorAttBarriers.push_back(imgBarrier);
4230 				if (needInterface)
4231 				{
4232 					imgBarrier.image = *fragOutputImage;
4233 					colorAttBarriers.push_back(imgBarrier);
4234 					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());
4235 				}
4236 				else
4237 				{
4238 					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());
4239 				}
4240 			}
4241 
4242 			{
4243 				vector<VkClearValue>			clearValue;
4244 				clearValue.push_back(makeClearValueColorF32(defaulClearColor[0], defaulClearColor[1], defaulClearColor[2], defaulClearColor[3]));
4245 				if (needInterface)
4246 				{
4247 					clearValue.push_back(makeClearValueColorU32(0, 0, 0, 0));
4248 				}
4249 
4250 
4251 				vk::VkRect2D scissor = makeRect2D(x * renderDimension, y * renderDimension, renderDimension, renderDimension);
4252 				vk.cmdSetScissor(*cmdBuf, 0u, 1u, &scissor);
4253 
4254 				beginRenderPass(vk, *cmdBuf, *renderPass, *framebuffer, scissor, (deUint32)clearValue.size(), clearValue.data());
4255 			}
4256 
4257 			vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
4258 			{
4259 				const VkDeviceSize bindingOffset = 0;
4260 				vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
4261 			}
4262 			if (needInterface)
4263 			{
4264 				const VkDeviceSize bindingOffset = 0;
4265 				vk.cmdBindVertexBuffers(*cmdBuf, 1u, 1u, &vertexInputBuffer.get(), &bindingOffset);
4266 			}
4267 			if (hasPushConstants)
4268 			{
4269 				vector<deUint8> pushConstantsBytes;
4270 				instance.pushConstants.getBuffer()->getBytes(pushConstantsBytes);
4271 
4272 				const deUint32	size	= static_cast<deUint32>(pushConstantsBytes.size());
4273 				const void*		data	= &pushConstantsBytes.front();
4274 
4275 				vk.cmdPushConstants(*cmdBuf, *pipelineLayout, VK_SHADER_STAGE_ALL_GRAPHICS, 0, size, data);
4276 			}
4277 			if (numResources != 0)
4278 			{
4279 				// Bind to set number 0.
4280 				vk.cmdBindDescriptorSets(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, &rawSet, 0, DE_NULL);
4281 			}
4282 			vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/);
4283 			endRenderPass(vk, *cmdBuf);
4284 
4285 			if (x == numRenderSegments - 1 && y == numRenderSegments - 1)
4286 			{
4287 				{
4288 					vector<VkImageMemoryBarrier>	renderFinishBarrier;
4289 					VkImageMemoryBarrier			imgBarrier				=
4290 					{
4291 						VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		//	VkStructureType			sType;
4292 						DE_NULL,									//	const void*				pNext;
4293 						VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		//	VkMemoryOutputFlags		outputMask;
4294 						VK_ACCESS_TRANSFER_READ_BIT,				//	VkMemoryInputFlags		inputMask;
4295 						VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout			oldLayout;
4296 						VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		//	VkImageLayout			newLayout;
4297 						queueFamilyIndex,							//	deUint32				srcQueueFamilyIndex;
4298 						queueFamilyIndex,							//	deUint32				destQueueFamilyIndex;
4299 						*image,										//	VkImage					image;
4300 						{
4301 							VK_IMAGE_ASPECT_COLOR_BIT,					//	VkImageAspectFlags	aspectMask;
4302 							0u,											//	deUint32			baseMipLevel;
4303 							1u,											//	deUint32			mipLevels;
4304 							0u,											//	deUint32			baseArraySlice;
4305 							1u,											//	deUint32			arraySize;
4306 						}											//	VkImageSubresourceRange	subresourceRange;
4307 					};
4308 					renderFinishBarrier.push_back(imgBarrier);
4309 
4310 					if (needInterface)
4311 					{
4312 						imgBarrier.image = *fragOutputImage;
4313 						renderFinishBarrier.push_back(imgBarrier);
4314 						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());
4315 					}
4316 					else
4317 					{
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, 1, renderFinishBarrier.data());
4319 					}
4320 				}
4321 
4322 				{
4323 					const VkBufferImageCopy	copyParams	=
4324 					{
4325 						(VkDeviceSize)0u,						//	VkDeviceSize			bufferOffset;
4326 						(deUint32)renderSize.x(),				//	deUint32				bufferRowLength;
4327 						(deUint32)renderSize.y(),				//	deUint32				bufferImageHeight;
4328 						{
4329 							VK_IMAGE_ASPECT_COLOR_BIT,				//	VkImageAspect		aspect;
4330 							0u,										//	deUint32			mipLevel;
4331 							0u,										//	deUint32			arrayLayer;
4332 							1u,										//	deUint32			arraySize;
4333 						},										//	VkImageSubresourceCopy	imageSubresource;
4334 						{ 0u, 0u, 0u },							//	VkOffset3D				imageOffset;
4335 						{ renderSize.x(), renderSize.y(), 1u }
4336 					};
4337 					vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
4338 
4339 					if (needInterface)
4340 					{
4341 						vk.cmdCopyImageToBuffer(*cmdBuf, *fragOutputImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *fragOutputBuffer, 1u, &copyParams);
4342 					}
4343 				}
4344 
4345 				{
4346 					vector<VkBufferMemoryBarrier>	cpFinishBarriers;
4347 					VkBufferMemoryBarrier			copyFinishBarrier	=
4348 					{
4349 						VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	//	VkStructureType		sType;
4350 						DE_NULL,									//	const void*			pNext;
4351 						VK_ACCESS_TRANSFER_WRITE_BIT,				//	VkMemoryOutputFlags	outputMask;
4352 						VK_ACCESS_HOST_READ_BIT,					//	VkMemoryInputFlags	inputMask;
4353 						queueFamilyIndex,							//	deUint32			srcQueueFamilyIndex;
4354 						queueFamilyIndex,							//	deUint32			destQueueFamilyIndex;
4355 						*readImageBuffer,							//	VkBuffer			buffer;
4356 						0u,											//	VkDeviceSize		offset;
4357 						imageSizeBytes								//	VkDeviceSize		size;
4358 					};
4359 					cpFinishBarriers.push_back(copyFinishBarrier);
4360 
4361 					if (needInterface)
4362 					{
4363 						copyFinishBarrier.buffer	= *fragOutputBuffer;
4364 						copyFinishBarrier.size		= VK_WHOLE_SIZE;
4365 						cpFinishBarriers.push_back(copyFinishBarrier);
4366 
4367 						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);
4368 					}
4369 					else
4370 					{
4371 						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);
4372 					}
4373 				}
4374 				}
4375 
4376 			endCommandBuffer(vk, *cmdBuf);
4377 
4378 			if (firstPass)
4379 			{
4380 				// Upload vertex data
4381 				{
4382 					void* vertexBufPtr = vertexBufferMemory->getHostPtr();
4383 					deMemcpy(vertexBufPtr, &vertexData[0], vertexDataSize);
4384 					flushAlloc(vk, device, *vertexBufferMemory);
4385 				}
4386 
4387 				if (needInterface)
4388 				{
4389 					vector<deUint8> inputBufferBytes;
4390 					instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
4391 
4392 					const deUint32				typNumBytes		= instance.interfaces.getInputType().getNumBytes();
4393 					const deUint32				bufNumBytes		= static_cast<deUint32>(inputBufferBytes.size());
4394 
4395 					// Require that the test instantation provides four output values.
4396 					DE_ASSERT(bufNumBytes == 4 * typNumBytes);
4397 
4398 					// We have four triangles. Because interpolation happens before executing the fragment shader,
4399 					// we need to provide the same vertex attribute for the same triangle. That means, duplicate each
4400 					// value three times for all four values.
4401 
4402 					const deUint8*				provided		= static_cast<const deUint8*>(&inputBufferBytes.front());
4403 					vector<deUint8>				data;
4404 
4405 					data.reserve(3 * bufNumBytes);
4406 
4407 					for (deUint32 offset = 0; offset < bufNumBytes; offset += typNumBytes)
4408 						for (deUint32 vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
4409 							for (deUint32 byteNdx = 0; byteNdx < typNumBytes; ++byteNdx)
4410 								data.push_back(provided[offset + byteNdx]);
4411 
4412 					deMemcpy(vertexInputMemory->getHostPtr(), data.data(), data.size());
4413 
4414 					flushAlloc(vk, device, *vertexInputMemory);
4415 
4416 				}
4417 				firstPass = false;
4418 			}
4419 
4420 			// Submit & wait for completion
4421 			submitCommandsAndWait(vk, device, queue, cmdBuf.get());
4422 		}
4423 	}
4424 
4425 	const void* imagePtr	= readImageBufferMemory->getHostPtr();
4426 	const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
4427 												  renderSize.x(), renderSize.y(), 1, imagePtr);
4428 	// Log image
4429 	invalidateAlloc(vk, device, *readImageBufferMemory);
4430 	context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer);
4431 
4432 	if (needInterface)
4433 		invalidateAlloc(vk, device, *fragOutputMemory);
4434 
4435 	// Make sure all output resources are ready.
4436 	for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
4437 		invalidateAlloc(vk, device, *outResourceMemories[outputNdx]);
4438 
4439 	const RGBA threshold(1, 1, 1, 1);
4440 
4441 	const RGBA upperLeft(pixelBuffer.getPixel(1, 1));
4442 	if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold))
4443 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper left corner mismatch"));
4444 
4445 	const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1));
4446 	if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold))
4447 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper right corner mismatch"));
4448 
4449 	const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1));
4450 	if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold))
4451 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower left corner mismatch"));
4452 
4453 	const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1));
4454 	if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold))
4455 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower right corner mismatch"));
4456 
4457 	// Check that the contents in the ouput variable matches expected.
4458 	if (needInterface)
4459 	{
4460 		vector<deUint8>						inputBufferBytes;
4461 		vector<deUint8>						outputBufferBytes;
4462 
4463 		instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
4464 		instance.interfaces.getOutputBuffer()->getBytes(outputBufferBytes);
4465 
4466 		const IFDataType&					inputType				= instance.interfaces.getInputType();
4467 		const IFDataType&					outputType				= instance.interfaces.getOutputType();
4468 		const void*							inputData				= &inputBufferBytes.front();
4469 		const void*							outputData				= &outputBufferBytes.front();
4470 		vector<std::pair<int, int> >		positions;
4471 		const tcu::ConstPixelBufferAccess	fragOutputBufferAccess	(outputType.getTextureFormat(), renderSize.x(), renderSize.y(), 1, fragOutputMemory->getHostPtr());
4472 
4473 		positions.push_back(std::make_pair(1, 1));
4474 		positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, 1));
4475 		positions.push_back(std::make_pair(1, fragOutputBufferAccess.getHeight() - 1));
4476 		positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, fragOutputBufferAccess.getHeight() - 1));
4477 
4478 		for (deUint32 posNdx = 0; posNdx < positions.size(); ++posNdx)
4479 		{
4480 			const int	x		= positions[posNdx].first;
4481 			const int	y		= positions[posNdx].second;
4482 			bool		equal	= true;
4483 
4484 			if (outputType.elementType == NUMBERTYPE_FLOAT32)
4485 			{
4486 				const float*		expected	= static_cast<const float*>(outputData) + posNdx * outputType.numElements;
4487 				const float*		actual		= static_cast<const float*>(fragOutputBufferAccess.getPixelPtr(x, y));
4488 
4489 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4490 					if (!compare32BitFloat(expected[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4491 						equal = false;
4492 			}
4493 			else if (outputType.elementType == NUMBERTYPE_INT32)
4494 			{
4495 				const deInt32*		expected	= static_cast<const deInt32*>(outputData) + posNdx * outputType.numElements;
4496 				const deInt32*		actual		= static_cast<const deInt32*>(fragOutputBufferAccess.getPixelPtr(x, y));
4497 
4498 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4499 					if (expected[eleNdx] != actual[eleNdx])
4500 						equal = false;
4501 			}
4502 			else if (outputType.elementType == NUMBERTYPE_UINT32)
4503 			{
4504 				const deUint32*		expected	= static_cast<const deUint32*>(outputData) + posNdx * outputType.numElements;
4505 				const deUint32*		actual		= static_cast<const deUint32*>(fragOutputBufferAccess.getPixelPtr(x, y));
4506 
4507 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4508 					if (expected[eleNdx] != actual[eleNdx])
4509 						equal = false;
4510 			}
4511 			else if (outputType.elementType == NUMBERTYPE_FLOAT16 && inputType.elementType == NUMBERTYPE_FLOAT64)
4512 			{
4513 				const double*		original	= static_cast<const double*>(inputData) + posNdx * outputType.numElements;
4514 				const deFloat16*	actual		= static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4515 
4516 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4517 					if (!compare16BitFloat64(original[eleNdx], actual[eleNdx], instance.interfaces.getRoundingMode(), context.getTestContext().getLog()))
4518 						equal = false;
4519 			}
4520 			else if (outputType.elementType == NUMBERTYPE_FLOAT16 && inputType.elementType != NUMBERTYPE_FLOAT64)
4521 			{
4522 				if (inputType.elementType == NUMBERTYPE_FLOAT16)
4523 				{
4524 					const deFloat16*	original	= static_cast<const deFloat16*>(inputData) + posNdx * outputType.numElements;
4525 					const deFloat16*	actual		= static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4526 
4527 					for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4528 						if (!compare16BitFloat(original[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4529 							equal = false;
4530 				}
4531 				else
4532 				{
4533 					const float*		original	= static_cast<const float*>(inputData) + posNdx * outputType.numElements;
4534 					const deFloat16*	actual		= static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4535 
4536 					for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4537 						if (!compare16BitFloat(original[eleNdx], actual[eleNdx], instance.interfaces.getRoundingMode(), context.getTestContext().getLog()))
4538 							equal = false;
4539 				}
4540 			}
4541 			else if (outputType.elementType == NUMBERTYPE_INT16)
4542 			{
4543 				const deInt16*		expected	= static_cast<const deInt16*>(outputData) + posNdx * outputType.numElements;
4544 				const deInt16*		actual		= static_cast<const deInt16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4545 
4546 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4547 					if (expected[eleNdx] != actual[eleNdx])
4548 						equal = false;
4549 			}
4550 			else if (outputType.elementType == NUMBERTYPE_UINT16)
4551 			{
4552 				const deUint16*		expected	= static_cast<const deUint16*>(outputData) + posNdx * outputType.numElements;
4553 				const deUint16*		actual		= static_cast<const deUint16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4554 
4555 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4556 					if (expected[eleNdx] != actual[eleNdx])
4557 						equal = false;
4558 			}
4559 			else if (outputType.elementType == NUMBERTYPE_FLOAT64)
4560 			{
4561 				const double*		expected	= static_cast<const double*>(outputData) + posNdx * outputType.numElements;
4562 				const double*		actual		= static_cast<const double*>(fragOutputBufferAccess.getPixelPtr(x, y));
4563 
4564 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4565 					if (!compare64BitFloat(expected[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4566 						equal = false;
4567 			}
4568 			else {
4569 				DE_ASSERT(0 && "unhandled type");
4570 			}
4571 
4572 			if (!equal)
4573 				return TestStatus(instance.failResult, instance.getSpecializedFailMessage("fragment output dat point #" + numberToString(posNdx) + " mismatch"));
4574 		}
4575 	}
4576 
4577 	// Check the contents in output resources match with expected.
4578 	for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
4579 	{
4580 		const BufferSp& expected = instance.resources.outputs[outputNdx].getBuffer();
4581 
4582 		if (instance.resources.verifyIO != DE_NULL)
4583 		{
4584 			if (!(*instance.resources.verifyIO)(instance.resources.inputs, outResourceMemories, instance.resources.outputs, context.getTestContext().getLog()))
4585 				return tcu::TestStatus::fail("Resource returned doesn't match with expected");
4586 		}
4587 		else
4588 		{
4589 			vector<deUint8> expectedBytes;
4590 			expected->getBytes(expectedBytes);
4591 
4592 			if (deMemCmp(&expectedBytes.front(), outResourceMemories[outputNdx]->getHostPtr(), expectedBytes.size()))
4593 			{
4594 				const size_t	numExpectedEntries	= expectedBytes.size() / sizeof(float);
4595 				float*			expectedFloats		= reinterpret_cast<float*>(&expectedBytes.front());
4596 				float*			outputFloats		= reinterpret_cast<float*>(outResourceMemories[outputNdx]->getHostPtr());
4597 				float			diff				= 0.0f;
4598 				deUint32		bitDiff				= 0;
4599 
4600 				for (size_t expectedNdx = 0; expectedNdx < numExpectedEntries; ++expectedNdx)
4601 				{
4602 					// RTZ and RNE can introduce a difference of a single ULP
4603 					// The RTZ output will always be either equal or lower than the RNE expected,
4604 					// so perform a bitwise subtractraction and check for the ULP difference
4605 					bitDiff = *reinterpret_cast<deUint32*>(&expectedFloats[expectedNdx]) - *reinterpret_cast<deUint32*>(&outputFloats[expectedNdx]);
4606 
4607 					// Allow a maximum of 1 ULP difference to account for RTZ rounding
4608 					if (bitDiff & (~0x1))
4609 					{
4610 						// Note: RTZ/RNE rounding leniency isn't applied for the checks below:
4611 
4612 						// Some *variable_pointers* tests store counters in buffer
4613 						// whose value may vary if the same vertex shader may be executed for multiple times
4614 						// in this case the output value can be expected value + non-negative integer N
4615 						if (instance.customizedStages == VK_SHADER_STAGE_VERTEX_BIT)
4616 						{
4617 							if (deFloatIsInf(outputFloats[expectedNdx]) || deFloatIsNaN(outputFloats[expectedNdx]))
4618 								return tcu::TestStatus::fail("Value returned is invalid");
4619 
4620 							diff = outputFloats[expectedNdx] - expectedFloats[expectedNdx];
4621 
4622 							if ((diff < 0.0f) || (deFloatFloor(diff) != diff))
4623 								return tcu::TestStatus::fail("Value returned should be equal to expected value plus non-negative integer");
4624 						}
4625 						else
4626 						{
4627 							return tcu::TestStatus::fail("Resource returned should be equal to expected, allowing for RTZ/RNE rounding");
4628 						}
4629 					}
4630 				}
4631 			}
4632 
4633 		}
4634 	}
4635 
4636 	return TestStatus::pass("Rendered output matches input");
4637 }
4638 
getVertFragPipelineStages(void)4639 const vector<ShaderElement>& getVertFragPipelineStages (void)
4640 {
4641 	static vector<ShaderElement> vertFragPipelineStages;
4642 	if(vertFragPipelineStages.empty())
4643 	{
4644 		vertFragPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4645 		vertFragPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4646 	};
4647 	return vertFragPipelineStages;
4648 }
4649 
getTessPipelineStages(void)4650 const vector<ShaderElement>& getTessPipelineStages (void)
4651 {
4652 	static vector<ShaderElement> tessPipelineStages;
4653 	if(tessPipelineStages.empty())
4654 	{
4655 		tessPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4656 		tessPipelineStages.push_back(ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
4657 		tessPipelineStages.push_back(ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
4658 		tessPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4659 	};
4660 	return tessPipelineStages;
4661 }
4662 
getGeomPipelineStages(void)4663 const vector<ShaderElement>& getGeomPipelineStages (void)
4664 {
4665 	static vector<ShaderElement> geomPipelineStages;
4666 	if(geomPipelineStages.empty())
4667 	{
4668 		geomPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4669 		geomPipelineStages.push_back(ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT));
4670 		geomPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4671 	};
4672 	return geomPipelineStages;
4673 }
4674 
4675 // Helper structure used by addTestForStage function.
4676 struct StageData
4677 {
4678 	typedef const vector<ShaderElement>& (*GetPipelineStagesFn)();
4679 	typedef void (*AddShaderCodeCustomStageFn)(vk::SourceCollections&, InstanceContext);
4680 
4681 	GetPipelineStagesFn			getPipelineFn;
4682 	AddShaderCodeCustomStageFn	initProgramsFn;
4683 
StageDatavkt::SpirVAssembly::StageData4684 	StageData()
4685 		: getPipelineFn(DE_NULL)
4686 		, initProgramsFn(DE_NULL)
4687 	{
4688 	}
4689 
StageDatavkt::SpirVAssembly::StageData4690 	StageData(GetPipelineStagesFn pipelineGetter, AddShaderCodeCustomStageFn programsInitializer)
4691 		: getPipelineFn(pipelineGetter)
4692 		, initProgramsFn(programsInitializer)
4693 	{
4694 	}
4695 };
4696 
4697 // Helper function used by addTestForStage function.
getStageData(vk::VkShaderStageFlagBits stage)4698 const StageData& getStageData (vk::VkShaderStageFlagBits stage)
4699 {
4700 	// Construct map
4701 	static map<vk::VkShaderStageFlagBits, StageData> testedStageData;
4702 	if(testedStageData.empty())
4703 	{
4704 		testedStageData[VK_SHADER_STAGE_VERTEX_BIT]					 = StageData(getVertFragPipelineStages, addShaderCodeCustomVertex);
4705 		testedStageData[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT]	 = StageData(getTessPipelineStages, addShaderCodeCustomTessControl);
4706 		testedStageData[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = StageData(getTessPipelineStages, addShaderCodeCustomTessEval);
4707 		testedStageData[VK_SHADER_STAGE_GEOMETRY_BIT]				 = StageData(getGeomPipelineStages, addShaderCodeCustomGeometry);
4708 		testedStageData[VK_SHADER_STAGE_FRAGMENT_BIT]				 = StageData(getVertFragPipelineStages, addShaderCodeCustomFragment);
4709 	}
4710 
4711 	return testedStageData[stage];
4712 }
4713 
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)4714 void createTestForStage (vk::VkShaderStageFlagBits	stage,
4715 						 const std::string&			name,
4716 						 const RGBA					(&inputColors)[4],
4717 						 const RGBA					(&outputColors)[4],
4718 						 const map<string, string>&	testCodeFragments,
4719 						 const SpecConstants&		specConstants,
4720 						 const PushConstants&		pushConstants,
4721 						 const GraphicsResources&	resources,
4722 						 const GraphicsInterfaces&	interfaces,
4723 						 const vector<string>&		extensions,
4724 						 VulkanFeatures				vulkanFeatures,
4725 						 tcu::TestCaseGroup*		tests,
4726 						 const qpTestResult			failResult,
4727 						 const string&				failMessageTemplate,
4728 						 const bool					renderFullSquare,
4729 						 const bool					splitRenderArea)
4730 {
4731 	const StageData&				stageData			= getStageData(stage);
4732 	DE_ASSERT(stageData.getPipelineFn || stageData.initProgramsFn);
4733 	const vector<ShaderElement>&	pipeline			= stageData.getPipelineFn();
4734 
4735 	StageToSpecConstantMap			specConstantMap;
4736 	if (!specConstants.empty())
4737 		specConstantMap[stage] = specConstants;
4738 
4739 	InstanceContext					ctx					(inputColors, outputColors, testCodeFragments, specConstantMap, pushConstants, resources, interfaces, extensions, vulkanFeatures, stage);
4740 	ctx.splitRenderArea = splitRenderArea;
4741 	for (size_t i = 0; i < pipeline.size(); ++i)
4742 	{
4743 		ctx.moduleMap[pipeline[i].moduleName].push_back(std::make_pair(pipeline[i].entryName, pipeline[i].stage));
4744 		ctx.requiredStages = static_cast<VkShaderStageFlagBits>(ctx.requiredStages | pipeline[i].stage);
4745 	}
4746 
4747 	ctx.failResult = failResult;
4748 	if (!failMessageTemplate.empty())
4749 		ctx.failMessageTemplate = failMessageTemplate;
4750 
4751 	ctx.renderFullSquare = renderFullSquare;
4752 	ctx.splitRenderArea	= splitRenderArea;
4753 	addFunctionCaseWithPrograms<InstanceContext>(tests, name, "", stageData.initProgramsFn, runAndVerifyDefaultPipeline, ctx);
4754 }
4755 
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)4756 void createTestsForAllStages (const std::string&			name,
4757 							  const RGBA					(&inputColors)[4],
4758 							  const RGBA					(&outputColors)[4],
4759 							  const map<string, string>&	testCodeFragments,
4760 							  const SpecConstants&			specConstants,
4761 							  const PushConstants&			pushConstants,
4762 							  const GraphicsResources&		resources,
4763 							  const GraphicsInterfaces&		interfaces,
4764 							  const vector<string>&			extensions,
4765 							  VulkanFeatures				vulkanFeatures,
4766 							  tcu::TestCaseGroup*			tests,
4767 							  const qpTestResult			failResult,
4768 							  const string&					failMessageTemplate,
4769 							  const bool					splitRenderArea)
4770 {
4771 	createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, name + "_vert",
4772 					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4773 					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4774 
4775 	createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, name + "_tessc",
4776 					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4777 					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4778 
4779 	createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, name + "_tesse",
4780 					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4781 					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4782 
4783 	createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, name + "_geom",
4784 					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4785 					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4786 
4787 	createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, name + "_frag",
4788 					   inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4789 					   interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate, false, splitRenderArea);
4790 }
4791 
addTessCtrlTest(tcu::TestCaseGroup * group,const char * name,const map<string,string> & fragments)4792 void addTessCtrlTest (tcu::TestCaseGroup* group, const char* name, const map<string, string>& fragments)
4793 {
4794 	RGBA defaultColors[4];
4795 	getDefaultColors(defaultColors);
4796 
4797 	createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, name,
4798 					   defaultColors, defaultColors, fragments, SpecConstants(), PushConstants(), GraphicsResources(),
4799 					   GraphicsInterfaces(), vector<string>(), VulkanFeatures(), group);
4800 }
4801 
4802 } // SpirVAssembly
4803 } // vkt
4804