Home | History | Annotate | Download | only in spirv_assembly
      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 
     29 #include "vkDefs.hpp"
     30 #include "vkMemUtil.hpp"
     31 #include "vkPlatform.hpp"
     32 #include "vkQueryUtil.hpp"
     33 #include "vkRefUtil.hpp"
     34 #include "vkTypeUtil.hpp"
     35 
     36 #include "deRandom.hpp"
     37 
     38 namespace vkt
     39 {
     40 namespace SpirVAssembly
     41 {
     42 
     43 using namespace vk;
     44 using std::map;
     45 using std::string;
     46 using std::vector;
     47 using tcu::Float16;
     48 using tcu::Float32;
     49 using tcu::IVec3;
     50 using tcu::IVec4;
     51 using tcu::RGBA;
     52 using tcu::TestLog;
     53 using tcu::TestStatus;
     54 using tcu::Vec4;
     55 using de::UniquePtr;
     56 using tcu::StringTemplate;
     57 using tcu::Vec4;
     58 
     59 deUint32 IFDataType::getElementNumBytes (void) const
     60 {
     61 	if (elementType < NUMBERTYPE_END32)
     62 		return 4;
     63 
     64 	return 2;
     65 }
     66 
     67 VkFormat IFDataType::getVkFormat (void) const
     68 {
     69 	if (numElements == 1)
     70 	{
     71 		switch (elementType)
     72 		{
     73 			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32_SFLOAT;
     74 			case NUMBERTYPE_INT32:		return VK_FORMAT_R32_SINT;
     75 			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32_UINT;
     76 			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16_SFLOAT;
     77 			case NUMBERTYPE_INT16:		return VK_FORMAT_R16_SINT;
     78 			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16_UINT;
     79 			default:					break;
     80 		}
     81 	}
     82 	else if (numElements == 2)
     83 	{
     84 		switch (elementType)
     85 		{
     86 			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32G32_SFLOAT;
     87 			case NUMBERTYPE_INT32:		return VK_FORMAT_R32G32_SINT;
     88 			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32G32_UINT;
     89 			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16G16_SFLOAT;
     90 			case NUMBERTYPE_INT16:		return VK_FORMAT_R16G16_SINT;
     91 			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16G16_UINT;
     92 			default:					break;
     93 		}
     94 	}
     95 	else if (numElements == 3)
     96 	{
     97 		switch (elementType)
     98 		{
     99 			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32G32B32_SFLOAT;
    100 			case NUMBERTYPE_INT32:		return VK_FORMAT_R32G32B32_SINT;
    101 			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32G32B32_UINT;
    102 			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16G16B16_SFLOAT;
    103 			case NUMBERTYPE_INT16:		return VK_FORMAT_R16G16B16_SINT;
    104 			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16G16B16_UINT;
    105 			default:					break;
    106 		}
    107 	}
    108 	else if (numElements == 4)
    109 	{
    110 		switch (elementType)
    111 		{
    112 			case NUMBERTYPE_FLOAT32:	return VK_FORMAT_R32G32B32A32_SFLOAT;
    113 			case NUMBERTYPE_INT32:		return VK_FORMAT_R32G32B32A32_SINT;
    114 			case NUMBERTYPE_UINT32:		return VK_FORMAT_R32G32B32A32_UINT;
    115 			case NUMBERTYPE_FLOAT16:	return VK_FORMAT_R16G16B16A16_SFLOAT;
    116 			case NUMBERTYPE_INT16:		return VK_FORMAT_R16G16B16A16_SINT;
    117 			case NUMBERTYPE_UINT16:		return VK_FORMAT_R16G16B16A16_UINT;
    118 			default:					break;
    119 		}
    120 	}
    121 
    122 	DE_ASSERT(false);
    123 	return VK_FORMAT_UNDEFINED;
    124 }
    125 
    126 tcu::TextureFormat IFDataType::getTextureFormat (void) const
    127 {
    128 	tcu::TextureFormat::ChannelType		ct	= tcu::TextureFormat::CHANNELTYPE_LAST;
    129 	tcu::TextureFormat::ChannelOrder	co	= tcu::TextureFormat::CHANNELORDER_LAST;
    130 
    131 	switch (elementType)
    132 	{
    133 		case NUMBERTYPE_FLOAT32:	ct = tcu::TextureFormat::FLOAT;				break;
    134 		case NUMBERTYPE_INT32:		ct = tcu::TextureFormat::SIGNED_INT32;		break;
    135 		case NUMBERTYPE_UINT32:		ct = tcu::TextureFormat::UNSIGNED_INT32;	break;
    136 		case NUMBERTYPE_FLOAT16:	ct = tcu::TextureFormat::HALF_FLOAT;		break;
    137 		case NUMBERTYPE_INT16:		ct = tcu::TextureFormat::SIGNED_INT16;		break;
    138 		case NUMBERTYPE_UINT16:		ct = tcu::TextureFormat::UNSIGNED_INT16;	break;
    139 		default:					DE_ASSERT(false);
    140 	}
    141 
    142 	switch (numElements)
    143 	{
    144 		case 1:				co = tcu::TextureFormat::R;					break;
    145 		case 2:				co = tcu::TextureFormat::RG;				break;
    146 		case 3:				co = tcu::TextureFormat::RGB;				break;
    147 		case 4:				co = tcu::TextureFormat::RGBA;				break;
    148 		default:			DE_ASSERT(false);
    149 	}
    150 
    151 	return tcu::TextureFormat(co, ct);
    152 }
    153 
    154 string IFDataType::str (void) const
    155 {
    156 	string	ret;
    157 
    158 	switch (elementType)
    159 	{
    160 		case NUMBERTYPE_FLOAT32:	ret = "f32"; break;
    161 		case NUMBERTYPE_INT32:		ret = "i32"; break;
    162 		case NUMBERTYPE_UINT32:		ret = "u32"; break;
    163 		case NUMBERTYPE_FLOAT16:	ret = "f16"; break;
    164 		case NUMBERTYPE_INT16:		ret = "i16"; break;
    165 		case NUMBERTYPE_UINT16:		ret = "u16"; break;
    166 		default:					DE_ASSERT(false);
    167 	}
    168 
    169 	if (numElements == 1)
    170 		return ret;
    171 
    172 	return string("v") + numberToString(numElements) + ret;
    173 }
    174 
    175 VkBufferUsageFlagBits getMatchingBufferUsageFlagBit(VkDescriptorType dType)
    176 {
    177 	switch (dType)
    178 	{
    179 		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
    180 		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
    181 		default:								DE_ASSERT(0 && "not implemented");
    182 	}
    183 	return (VkBufferUsageFlagBits)0;
    184 }
    185 
    186 static void requireFormatUsageSupport(const InstanceInterface& vki, VkPhysicalDevice physicalDevice, VkFormat format, VkImageTiling imageTiling, VkImageUsageFlags requiredUsageFlags)
    187 {
    188 	VkFormatProperties		properties;
    189 	VkFormatFeatureFlags	tilingFeatures	= 0;
    190 
    191 	vki.getPhysicalDeviceFormatProperties(physicalDevice, format, &properties);
    192 
    193 	switch (imageTiling)
    194 	{
    195 		case VK_IMAGE_TILING_LINEAR:
    196 			tilingFeatures = properties.linearTilingFeatures;
    197 			break;
    198 
    199 		case VK_IMAGE_TILING_OPTIMAL:
    200 			tilingFeatures = properties.optimalTilingFeatures;
    201 			break;
    202 
    203 		default:
    204 			DE_ASSERT(false);
    205 			break;
    206 	}
    207 
    208 	if ((requiredUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0)
    209 	{
    210 		if ((tilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)
    211 			TCU_THROW(NotSupportedError, "Image format cannot be used as color attachment");
    212 		requiredUsageFlags ^= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    213 	}
    214 
    215 
    216 	if ((requiredUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) != 0)
    217 	{
    218 		if ((tilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR) == 0)
    219 			TCU_THROW(NotSupportedError, "Image format cannot be used as transfer source");
    220 		requiredUsageFlags ^= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
    221 	}
    222 
    223 
    224 	DE_ASSERT(!requiredUsageFlags && "checking other image usage bits not supported yet");
    225 }
    226 
    227 InstanceContext::InstanceContext (const RGBA						(&inputs)[4],
    228 								  const RGBA						(&outputs)[4],
    229 								  const map<string, string>&		testCodeFragments_,
    230 								  const StageToSpecConstantMap&		specConstants_,
    231 								  const PushConstants&				pushConsants_,
    232 								  const GraphicsResources&			resources_,
    233 								  const GraphicsInterfaces&			interfaces_,
    234 								  const vector<string>&				extensions_,
    235 								  const vector<string>&				features_,
    236 								  VulkanFeatures					vulkanFeatures_,
    237 								  VkShaderStageFlags				customizedStages_)
    238 	: testCodeFragments				(testCodeFragments_)
    239 	, specConstants					(specConstants_)
    240 	, hasTessellation				(false)
    241 	, requiredStages				(static_cast<VkShaderStageFlagBits>(0))
    242 	, requiredDeviceExtensions		(extensions_)
    243 	, requiredDeviceFeatures		(features_)
    244 	, requestedFeatures				(vulkanFeatures_)
    245 	, pushConstants					(pushConsants_)
    246 	, customizedStages				(customizedStages_)
    247 	, resources						(resources_)
    248 	, interfaces					(interfaces_)
    249 	, failResult					(QP_TEST_RESULT_FAIL)
    250 	, failMessageTemplate			("${reason}")
    251 {
    252 	inputColors[0]		= inputs[0];
    253 	inputColors[1]		= inputs[1];
    254 	inputColors[2]		= inputs[2];
    255 	inputColors[3]		= inputs[3];
    256 
    257 	outputColors[0]		= outputs[0];
    258 	outputColors[1]		= outputs[1];
    259 	outputColors[2]		= outputs[2];
    260 	outputColors[3]		= outputs[3];
    261 }
    262 
    263 InstanceContext::InstanceContext (const InstanceContext& other)
    264 	: moduleMap						(other.moduleMap)
    265 	, testCodeFragments				(other.testCodeFragments)
    266 	, specConstants					(other.specConstants)
    267 	, hasTessellation				(other.hasTessellation)
    268 	, requiredStages				(other.requiredStages)
    269 	, requiredDeviceExtensions		(other.requiredDeviceExtensions)
    270 	, requiredDeviceFeatures		(other.requiredDeviceFeatures)
    271 	, requestedFeatures				(other.requestedFeatures)
    272 	, pushConstants					(other.pushConstants)
    273 	, customizedStages				(other.customizedStages)
    274 	, resources						(other.resources)
    275 	, interfaces					(other.interfaces)
    276 	, failResult					(other.failResult)
    277 	, failMessageTemplate			(other.failMessageTemplate)
    278 {
    279 	inputColors[0]		= other.inputColors[0];
    280 	inputColors[1]		= other.inputColors[1];
    281 	inputColors[2]		= other.inputColors[2];
    282 	inputColors[3]		= other.inputColors[3];
    283 
    284 	outputColors[0]		= other.outputColors[0];
    285 	outputColors[1]		= other.outputColors[1];
    286 	outputColors[2]		= other.outputColors[2];
    287 	outputColors[3]		= other.outputColors[3];
    288 }
    289 
    290 string InstanceContext::getSpecializedFailMessage (const string& failureReason)
    291 {
    292 	map<string, string>		parameters;
    293 	parameters["reason"]	= failureReason;
    294 	return StringTemplate(failMessageTemplate).specialize(parameters);
    295 }
    296 
    297 ShaderElement::ShaderElement (const string&				moduleName_,
    298 							  const string&				entryPoint_,
    299 							  VkShaderStageFlagBits		shaderStage_)
    300 		: moduleName(moduleName_)
    301 		, entryName(entryPoint_)
    302 		, stage(shaderStage_)
    303 {
    304 }
    305 
    306 void getDefaultColors (RGBA (&colors)[4])
    307 {
    308 	colors[0] = RGBA::white();
    309 	colors[1] = RGBA::red();
    310 	colors[2] = RGBA::green();
    311 	colors[3] = RGBA::blue();
    312 }
    313 
    314 void getHalfColorsFullAlpha (RGBA (&colors)[4])
    315 {
    316 	colors[0] = RGBA(127, 127, 127, 255);
    317 	colors[1] = RGBA(127, 0,   0,	255);
    318 	colors[2] = RGBA(0,	  127, 0,	255);
    319 	colors[3] = RGBA(0,	  0,   127, 255);
    320 }
    321 
    322 void getInvertedDefaultColors (RGBA (&colors)[4])
    323 {
    324 	colors[0] = RGBA(0,		0,		0,		255);
    325 	colors[1] = RGBA(0,		255,	255,	255);
    326 	colors[2] = RGBA(255,	0,		255,	255);
    327 	colors[3] = RGBA(255,	255,	0,		255);
    328 }
    329 
    330 // For the current InstanceContext, constructs the required modules and shader stage create infos.
    331 void createPipelineShaderStages (const DeviceInterface&						vk,
    332 								 const VkDevice								vkDevice,
    333 								 InstanceContext&							instance,
    334 								 Context&									context,
    335 								 vector<ModuleHandleSp>&					modules,
    336 								 vector<VkPipelineShaderStageCreateInfo>&	createInfos)
    337 {
    338 	for (ModuleMap::const_iterator moduleNdx = instance.moduleMap.begin(); moduleNdx != instance.moduleMap.end(); ++moduleNdx)
    339 	{
    340 		const ModuleHandleSp mod(new Unique<VkShaderModule>(createShaderModule(vk, vkDevice, context.getBinaryCollection().get(moduleNdx->first), 0)));
    341 		modules.push_back(ModuleHandleSp(mod));
    342 		for (vector<EntryToStage>::const_iterator shaderNdx = moduleNdx->second.begin(); shaderNdx != moduleNdx->second.end(); ++shaderNdx)
    343 		{
    344 			const EntryToStage&						stage			= *shaderNdx;
    345 			const VkPipelineShaderStageCreateInfo	shaderParam		=
    346 			{
    347 				VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType			sType;
    348 				DE_NULL,												//	const void*				pNext;
    349 				(VkPipelineShaderStageCreateFlags)0,
    350 				stage.second,											//	VkShaderStageFlagBits	stage;
    351 				**modules.back(),										//	VkShaderModule			module;
    352 				stage.first.c_str(),									//	const char*				pName;
    353 				(const VkSpecializationInfo*)DE_NULL,
    354 			};
    355 			createInfos.push_back(shaderParam);
    356 		}
    357 	}
    358 }
    359 
    360 #define SPIRV_ASSEMBLY_TYPES																	\
    361 	"%void = OpTypeVoid\n"																		\
    362 	"%bool = OpTypeBool\n"																		\
    363 																								\
    364 	"%i32 = OpTypeInt 32 1\n"																	\
    365 	"%u32 = OpTypeInt 32 0\n"																	\
    366 																								\
    367 	"%f32 = OpTypeFloat 32\n"																	\
    368 	"%v2i32 = OpTypeVector %i32 2\n"															\
    369 	"%v2u32 = OpTypeVector %u32 2\n"															\
    370 	"%v2f32 = OpTypeVector %f32 2\n"															\
    371 	"%v3f32 = OpTypeVector %f32 3\n"															\
    372 	"%v4i32 = OpTypeVector %i32 4\n"															\
    373 	"%v4u32 = OpTypeVector %u32 4\n"															\
    374 	"%v4f32 = OpTypeVector %f32 4\n"															\
    375 	"%v4bool = OpTypeVector %bool 4\n"															\
    376 																								\
    377 	"%v4f32_function = OpTypeFunction %v4f32 %v4f32\n"											\
    378 	"%bool_function = OpTypeFunction %bool\n"													\
    379 	"%fun = OpTypeFunction %void\n"																\
    380 																								\
    381 	"%ip_f32 = OpTypePointer Input %f32\n"														\
    382 	"%ip_i32 = OpTypePointer Input %i32\n"														\
    383 	"%ip_u32 = OpTypePointer Input %u32\n"														\
    384 	"%ip_v3f32 = OpTypePointer Input %v3f32\n"													\
    385 	"%ip_v2f32 = OpTypePointer Input %v2f32\n"													\
    386 	"%ip_v2i32 = OpTypePointer Input %v2i32\n"													\
    387 	"%ip_v2u32 = OpTypePointer Input %v2u32\n"													\
    388 	"%ip_v4f32 = OpTypePointer Input %v4f32\n"													\
    389 	"%ip_v4i32 = OpTypePointer Input %v4i32\n"													\
    390 	"%ip_v4u32 = OpTypePointer Input %v4u32\n"													\
    391 																								\
    392 	"%op_f32 = OpTypePointer Output %f32\n"														\
    393 	"%op_i32 = OpTypePointer Output %i32\n"														\
    394 	"%op_u32 = OpTypePointer Output %u32\n"														\
    395 	"%op_v2f32 = OpTypePointer Output %v2f32\n"													\
    396 	"%op_v2i32 = OpTypePointer Output %v2i32\n"													\
    397 	"%op_v2u32 = OpTypePointer Output %v2u32\n"													\
    398 	"%op_v4f32 = OpTypePointer Output %v4f32\n"													\
    399 	"%op_v4i32 = OpTypePointer Output %v4i32\n"													\
    400 	"%op_v4u32 = OpTypePointer Output %v4u32\n"													\
    401 																								\
    402 	"%fp_f32   = OpTypePointer Function %f32\n"													\
    403 	"%fp_i32   = OpTypePointer Function %i32\n"													\
    404 	"%fp_v4f32 = OpTypePointer Function %v4f32\n"
    405 
    406 #define SPIRV_ASSEMBLY_CONSTANTS																\
    407 	"%c_f32_1 = OpConstant %f32 1.0\n"															\
    408 	"%c_f32_0 = OpConstant %f32 0.0\n"															\
    409 	"%c_f32_0_5 = OpConstant %f32 0.5\n"														\
    410 	"%c_f32_n1  = OpConstant %f32 -1.\n"														\
    411 	"%c_f32_7 = OpConstant %f32 7.0\n"															\
    412 	"%c_f32_8 = OpConstant %f32 8.0\n"															\
    413 	"%c_i32_0 = OpConstant %i32 0\n"															\
    414 	"%c_i32_1 = OpConstant %i32 1\n"															\
    415 	"%c_i32_2 = OpConstant %i32 2\n"															\
    416 	"%c_i32_3 = OpConstant %i32 3\n"															\
    417 	"%c_i32_4 = OpConstant %i32 4\n"															\
    418 	"%c_u32_0 = OpConstant %u32 0\n"															\
    419 	"%c_u32_1 = OpConstant %u32 1\n"															\
    420 	"%c_u32_2 = OpConstant %u32 2\n"															\
    421 	"%c_u32_3 = OpConstant %u32 3\n"															\
    422 	"%c_u32_32 = OpConstant %u32 32\n"															\
    423 	"%c_u32_4 = OpConstant %u32 4\n"															\
    424 	"%c_u32_31_bits = OpConstant %u32 0x7FFFFFFF\n"												\
    425 	"%c_v4f32_1_1_1_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_1\n"		\
    426 	"%c_v4f32_1_0_0_1 = OpConstantComposite %v4f32 %c_f32_1 %c_f32_0 %c_f32_0 %c_f32_1\n"		\
    427 	"%c_v4f32_0_5_0_5_0_5_0_5 = OpConstantComposite %v4f32 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5 %c_f32_0_5\n"
    428 
    429 #define SPIRV_ASSEMBLY_ARRAYS																	\
    430 	"%a1f32 = OpTypeArray %f32 %c_u32_1\n"														\
    431 	"%a2f32 = OpTypeArray %f32 %c_u32_2\n"														\
    432 	"%a3v4f32 = OpTypeArray %v4f32 %c_u32_3\n"													\
    433 	"%a4f32 = OpTypeArray %f32 %c_u32_4\n"														\
    434 	"%a32v4f32 = OpTypeArray %v4f32 %c_u32_32\n"												\
    435 	"%ip_a3v4f32 = OpTypePointer Input %a3v4f32\n"												\
    436 	"%ip_a32v4f32 = OpTypePointer Input %a32v4f32\n"											\
    437 	"%op_a2f32 = OpTypePointer Output %a2f32\n"													\
    438 	"%op_a3v4f32 = OpTypePointer Output %a3v4f32\n"												\
    439 	"%op_a4f32 = OpTypePointer Output %a4f32\n"
    440 
    441 // Creates vertex-shader assembly by specializing a boilerplate StringTemplate
    442 // on fragments, which must (at least) map "testfun" to an OpFunction definition
    443 // for %test_code that takes and returns a %v4f32.  Boilerplate IDs are prefixed
    444 // with "BP_" to avoid collisions with fragments.
    445 //
    446 // It corresponds roughly to this GLSL:
    447 //;
    448 // layout(location = 0) in vec4 position;
    449 // layout(location = 1) in vec4 color;
    450 // layout(location = 1) out highp vec4 vtxColor;
    451 // void main (void) { gl_Position = position; vtxColor = test_func(color); }
    452 string makeVertexShaderAssembly(const map<string, string>& fragments)
    453 {
    454 // \todo [2015-11-23 awoloszyn] Remove OpName once these have stabalized
    455 	static const char vertexShaderBoilerplate[] =
    456 		"OpCapability Shader\n"
    457 		"OpCapability ClipDistance\n"
    458 		"OpCapability CullDistance\n"
    459 		"${capability:opt}\n"
    460 		"${extension:opt}\n"
    461 		"OpMemoryModel Logical GLSL450\n"
    462 		"OpEntryPoint Vertex %main \"main\" %BP_stream %BP_position %BP_vtx_color %BP_color %BP_gl_VertexIndex %BP_gl_InstanceIndex ${IF_entrypoint:opt} \n"
    463 		"${debug:opt}\n"
    464 		"OpName %main \"main\"\n"
    465 		"OpName %BP_gl_PerVertex \"gl_PerVertex\"\n"
    466 		"OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n"
    467 		"OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n"
    468 		"OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n"
    469 		"OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n"
    470 		"OpName %test_code \"testfun(vf4;\"\n"
    471 		"OpName %BP_stream \"\"\n"
    472 		"OpName %BP_position \"position\"\n"
    473 		"OpName %BP_vtx_color \"vtxColor\"\n"
    474 		"OpName %BP_color \"color\"\n"
    475 		"OpName %BP_gl_VertexIndex \"gl_VertexIndex\"\n"
    476 		"OpName %BP_gl_InstanceIndex \"gl_InstanceIndex\"\n"
    477 		"${moduleprocessed:opt}\n"
    478 		"OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n"
    479 		"OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n"
    480 		"OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n"
    481 		"OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n"
    482 		"OpDecorate %BP_gl_PerVertex Block\n"
    483 		"OpDecorate %BP_position Location 0\n"
    484 		"OpDecorate %BP_vtx_color Location 1\n"
    485 		"OpDecorate %BP_color Location 1\n"
    486 		"OpDecorate %BP_gl_VertexIndex BuiltIn VertexIndex\n"
    487 		"OpDecorate %BP_gl_InstanceIndex BuiltIn InstanceIndex\n"
    488 		"${IF_decoration:opt}\n"
    489 		"${decoration:opt}\n"
    490 		SPIRV_ASSEMBLY_TYPES
    491 		SPIRV_ASSEMBLY_CONSTANTS
    492 		SPIRV_ASSEMBLY_ARRAYS
    493 		"%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
    494 		"%BP_op_gl_PerVertex = OpTypePointer Output %BP_gl_PerVertex\n"
    495 		"%BP_stream = OpVariable %BP_op_gl_PerVertex Output\n"
    496 		"%BP_position = OpVariable %ip_v4f32 Input\n"
    497 		"%BP_vtx_color = OpVariable %op_v4f32 Output\n"
    498 		"%BP_color = OpVariable %ip_v4f32 Input\n"
    499 		"%BP_gl_VertexIndex = OpVariable %ip_i32 Input\n"
    500 		"%BP_gl_InstanceIndex = OpVariable %ip_i32 Input\n"
    501 		"${pre_main:opt}\n"
    502 		"${IF_variable:opt}\n"
    503 		"%main = OpFunction %void None %fun\n"
    504 		"%BP_label = OpLabel\n"
    505 		"${IF_carryforward:opt}\n"
    506 		"%BP_pos = OpLoad %v4f32 %BP_position\n"
    507 		"%BP_gl_pos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
    508 		"OpStore %BP_gl_pos %BP_pos\n"
    509 		"%BP_col = OpLoad %v4f32 %BP_color\n"
    510 		"%BP_col_transformed = OpFunctionCall %v4f32 %test_code %BP_col\n"
    511 		"OpStore %BP_vtx_color %BP_col_transformed\n"
    512 		"OpReturn\n"
    513 		"OpFunctionEnd\n"
    514 		"${interface_op_func:opt}\n"
    515 
    516 		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
    517 		"%getId_label = OpLabel\n"
    518 		"%vert_id = OpLoad %i32 %BP_gl_VertexIndex\n"
    519 		"%is_id_0 = OpIEqual %bool %vert_id %c_i32_0\n"
    520 		"OpReturnValue %is_id_0\n"
    521 		"OpFunctionEnd\n"
    522 
    523 		"${testfun}\n";
    524 	return tcu::StringTemplate(vertexShaderBoilerplate).specialize(fragments);
    525 }
    526 
    527 // Creates tess-control-shader assembly by specializing a boilerplate
    528 // StringTemplate on fragments, which must (at least) map "testfun" to an
    529 // OpFunction definition for %test_code that takes and returns a %v4f32.
    530 // Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments.
    531 //
    532 // It roughly corresponds to the following GLSL.
    533 //
    534 // #version 450
    535 // layout(vertices = 3) out;
    536 // layout(location = 1) in vec4 in_color[];
    537 // layout(location = 1) out vec4 out_color[];
    538 //
    539 // void main() {
    540 //   out_color[gl_InvocationID] = testfun(in_color[gl_InvocationID]);
    541 //   gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
    542 //   if (gl_InvocationID == 0) {
    543 //     gl_TessLevelOuter[0] = 1.0;
    544 //     gl_TessLevelOuter[1] = 1.0;
    545 //     gl_TessLevelOuter[2] = 1.0;
    546 //     gl_TessLevelInner[0] = 1.0;
    547 //   }
    548 // }
    549 string makeTessControlShaderAssembly (const map<string, string>& fragments)
    550 {
    551 	static const char tessControlShaderBoilerplate[] =
    552 		"OpCapability Tessellation\n"
    553 		"OpCapability ClipDistance\n"
    554 		"OpCapability CullDistance\n"
    555 		"${capability:opt}\n"
    556 		"${extension:opt}\n"
    557 		"OpMemoryModel Logical GLSL450\n"
    558 		"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"
    559 		"OpExecutionMode %BP_main OutputVertices 3\n"
    560 		"${debug:opt}\n"
    561 		"OpName %BP_main \"main\"\n"
    562 		"OpName %test_code \"testfun(vf4;\"\n"
    563 		"OpName %BP_out_color \"out_color\"\n"
    564 		"OpName %BP_gl_InvocationID \"gl_InvocationID\"\n"
    565 		"OpName %BP_gl_PrimitiveID \"gl_PrimitiveID\"\n"
    566 		"OpName %BP_in_color \"in_color\"\n"
    567 		"OpName %BP_gl_PerVertex \"gl_PerVertex\"\n"
    568 		"OpMemberName %BP_gl_PerVertex 0 \"gl_Position\"\n"
    569 		"OpMemberName %BP_gl_PerVertex 1 \"gl_PointSize\"\n"
    570 		"OpMemberName %BP_gl_PerVertex 2 \"gl_ClipDistance\"\n"
    571 		"OpMemberName %BP_gl_PerVertex 3 \"gl_CullDistance\"\n"
    572 		"OpName %BP_gl_out \"gl_out\"\n"
    573 		"OpName %BP_gl_PVOut \"gl_PerVertex\"\n"
    574 		"OpMemberName %BP_gl_PVOut 0 \"gl_Position\"\n"
    575 		"OpMemberName %BP_gl_PVOut 1 \"gl_PointSize\"\n"
    576 		"OpMemberName %BP_gl_PVOut 2 \"gl_ClipDistance\"\n"
    577 		"OpMemberName %BP_gl_PVOut 3 \"gl_CullDistance\"\n"
    578 		"OpName %BP_gl_in \"gl_in\"\n"
    579 		"OpName %BP_gl_TessLevelOuter \"gl_TessLevelOuter\"\n"
    580 		"OpName %BP_gl_TessLevelInner \"gl_TessLevelInner\"\n"
    581 		"${moduleprocessed:opt}\n"
    582 		"OpDecorate %BP_out_color Location 1\n"
    583 		"OpDecorate %BP_gl_InvocationID BuiltIn InvocationId\n"
    584 		"OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n"
    585 		"OpDecorate %BP_in_color Location 1\n"
    586 		"OpMemberDecorate %BP_gl_PerVertex 0 BuiltIn Position\n"
    587 		"OpMemberDecorate %BP_gl_PerVertex 1 BuiltIn PointSize\n"
    588 		"OpMemberDecorate %BP_gl_PerVertex 2 BuiltIn ClipDistance\n"
    589 		"OpMemberDecorate %BP_gl_PerVertex 3 BuiltIn CullDistance\n"
    590 		"OpDecorate %BP_gl_PerVertex Block\n"
    591 		"OpMemberDecorate %BP_gl_PVOut 0 BuiltIn Position\n"
    592 		"OpMemberDecorate %BP_gl_PVOut 1 BuiltIn PointSize\n"
    593 		"OpMemberDecorate %BP_gl_PVOut 2 BuiltIn ClipDistance\n"
    594 		"OpMemberDecorate %BP_gl_PVOut 3 BuiltIn CullDistance\n"
    595 		"OpDecorate %BP_gl_PVOut Block\n"
    596 		"OpDecorate %BP_gl_TessLevelOuter Patch\n"
    597 		"OpDecorate %BP_gl_TessLevelOuter BuiltIn TessLevelOuter\n"
    598 		"OpDecorate %BP_gl_TessLevelInner Patch\n"
    599 		"OpDecorate %BP_gl_TessLevelInner BuiltIn TessLevelInner\n"
    600 		"${IF_decoration:opt}\n"
    601 		"${decoration:opt}\n"
    602 		SPIRV_ASSEMBLY_TYPES
    603 		SPIRV_ASSEMBLY_CONSTANTS
    604 		SPIRV_ASSEMBLY_ARRAYS
    605 		"%BP_out_color = OpVariable %op_a3v4f32 Output\n"
    606 		"%BP_gl_InvocationID = OpVariable %ip_i32 Input\n"
    607 		"%BP_gl_PrimitiveID = OpVariable %ip_i32 Input\n"
    608 		"%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
    609 		"%BP_gl_PerVertex = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
    610 		"%BP_a3_gl_PerVertex = OpTypeArray %BP_gl_PerVertex %c_u32_3\n"
    611 		"%BP_op_a3_gl_PerVertex = OpTypePointer Output %BP_a3_gl_PerVertex\n"
    612 		"%BP_gl_out = OpVariable %BP_op_a3_gl_PerVertex Output\n"
    613 		"%BP_gl_PVOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
    614 		"%BP_a32_gl_PVOut = OpTypeArray %BP_gl_PVOut %c_u32_32\n"
    615 		"%BP_ip_a32_gl_PVOut = OpTypePointer Input %BP_a32_gl_PVOut\n"
    616 		"%BP_gl_in = OpVariable %BP_ip_a32_gl_PVOut Input\n"
    617 		"%BP_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
    618 		"%BP_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
    619 		"${pre_main:opt}\n"
    620 		"${IF_variable:opt}\n"
    621 
    622 		"%BP_main = OpFunction %void None %fun\n"
    623 		"%BP_label = OpLabel\n"
    624 		"%BP_gl_Invoc = OpLoad %i32 %BP_gl_InvocationID\n"
    625 		"${IF_carryforward:opt}\n"
    626 		"%BP_in_col_loc = OpAccessChain %ip_v4f32 %BP_in_color %BP_gl_Invoc\n"
    627 		"%BP_out_col_loc = OpAccessChain %op_v4f32 %BP_out_color %BP_gl_Invoc\n"
    628 		"%BP_in_col_val = OpLoad %v4f32 %BP_in_col_loc\n"
    629 		"%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_in_col_val\n"
    630 		"OpStore %BP_out_col_loc %BP_clr_transformed\n"
    631 
    632 		"%BP_in_pos_loc = OpAccessChain %ip_v4f32 %BP_gl_in %BP_gl_Invoc %c_i32_0\n"
    633 		"%BP_out_pos_loc = OpAccessChain %op_v4f32 %BP_gl_out %BP_gl_Invoc %c_i32_0\n"
    634 		"%BP_in_pos_val = OpLoad %v4f32 %BP_in_pos_loc\n"
    635 		"OpStore %BP_out_pos_loc %BP_in_pos_val\n"
    636 
    637 		"%BP_cmp = OpIEqual %bool %BP_gl_Invoc %c_i32_0\n"
    638 		"OpSelectionMerge %BP_merge_label None\n"
    639 		"OpBranchConditional %BP_cmp %BP_if_label %BP_merge_label\n"
    640 		"%BP_if_label = OpLabel\n"
    641 		"%BP_gl_TessLevelOuterPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_0\n"
    642 		"%BP_gl_TessLevelOuterPos_1 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_1\n"
    643 		"%BP_gl_TessLevelOuterPos_2 = OpAccessChain %op_f32 %BP_gl_TessLevelOuter %c_i32_2\n"
    644 		"%BP_gl_TessLevelInnerPos_0 = OpAccessChain %op_f32 %BP_gl_TessLevelInner %c_i32_0\n"
    645 		"OpStore %BP_gl_TessLevelOuterPos_0 %c_f32_1\n"
    646 		"OpStore %BP_gl_TessLevelOuterPos_1 %c_f32_1\n"
    647 		"OpStore %BP_gl_TessLevelOuterPos_2 %c_f32_1\n"
    648 		"OpStore %BP_gl_TessLevelInnerPos_0 %c_f32_1\n"
    649 		"OpBranch %BP_merge_label\n"
    650 		"%BP_merge_label = OpLabel\n"
    651 		"OpReturn\n"
    652 		"OpFunctionEnd\n"
    653 		"${interface_op_func:opt}\n"
    654 
    655 		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
    656 		"%getId_label = OpLabel\n"
    657 		"%invocation_id = OpLoad %i32 %BP_gl_InvocationID\n"
    658 		"%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n"
    659 		"%is_invocation_0 = OpIEqual %bool %invocation_id %c_i32_0\n"
    660 		"%is_primitive_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
    661 		"%is_id_0 = OpLogicalAnd %bool %is_invocation_0 %is_primitive_0\n"
    662 		"OpReturnValue %is_id_0\n"
    663 		"OpFunctionEnd\n"
    664 
    665 		"${testfun}\n";
    666 	return tcu::StringTemplate(tessControlShaderBoilerplate).specialize(fragments);
    667 }
    668 
    669 // Creates tess-evaluation-shader assembly by specializing a boilerplate
    670 // StringTemplate on fragments, which must (at least) map "testfun" to an
    671 // OpFunction definition for %test_code that takes and returns a %v4f32.
    672 // Boilerplate IDs are prefixed with "BP_" to avoid collisions with fragments.
    673 //
    674 // It roughly corresponds to the following glsl.
    675 //
    676 // #version 450
    677 //
    678 // layout(triangles, equal_spacing, ccw) in;
    679 // layout(location = 1) in vec4 in_color[];
    680 // layout(location = 1) out vec4 out_color;
    681 //
    682 // #define interpolate(val)
    683 //   vec4(gl_TessCoord.x) * val[0] + vec4(gl_TessCoord.y) * val[1] +
    684 //          vec4(gl_TessCoord.z) * val[2]
    685 //
    686 // void main() {
    687 //   gl_Position = vec4(gl_TessCoord.x) * gl_in[0].gl_Position +
    688 //                  vec4(gl_TessCoord.y) * gl_in[1].gl_Position +
    689 //                  vec4(gl_TessCoord.z) * gl_in[2].gl_Position;
    690 //   out_color = testfun(interpolate(in_color));
    691 // }
    692 string makeTessEvalShaderAssembly(const map<string, string>& fragments)
    693 {
    694 	static const char tessEvalBoilerplate[] =
    695 		"OpCapability Tessellation\n"
    696 		"OpCapability ClipDistance\n"
    697 		"OpCapability CullDistance\n"
    698 		"${capability:opt}\n"
    699 		"${extension:opt}\n"
    700 		"OpMemoryModel Logical GLSL450\n"
    701 		"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"
    702 		"OpExecutionMode %BP_main Triangles\n"
    703 		"OpExecutionMode %BP_main SpacingEqual\n"
    704 		"OpExecutionMode %BP_main VertexOrderCcw\n"
    705 		"${debug:opt}\n"
    706 		"OpName %BP_main \"main\"\n"
    707 		"OpName %test_code \"testfun(vf4;\"\n"
    708 		"OpName %BP_gl_PerVertexOut \"gl_PerVertex\"\n"
    709 		"OpMemberName %BP_gl_PerVertexOut 0 \"gl_Position\"\n"
    710 		"OpMemberName %BP_gl_PerVertexOut 1 \"gl_PointSize\"\n"
    711 		"OpMemberName %BP_gl_PerVertexOut 2 \"gl_ClipDistance\"\n"
    712 		"OpMemberName %BP_gl_PerVertexOut 3 \"gl_CullDistance\"\n"
    713 		"OpName %BP_stream \"\"\n"
    714 		"OpName %BP_gl_TessCoord \"gl_TessCoord\"\n"
    715 		"OpName %BP_gl_PerVertexIn \"gl_PerVertex\"\n"
    716 		"OpName %BP_gl_PrimitiveID \"gl_PrimitiveID\"\n"
    717 		"OpMemberName %BP_gl_PerVertexIn 0 \"gl_Position\"\n"
    718 		"OpMemberName %BP_gl_PerVertexIn 1 \"gl_PointSize\"\n"
    719 		"OpMemberName %BP_gl_PerVertexIn 2 \"gl_ClipDistance\"\n"
    720 		"OpMemberName %BP_gl_PerVertexIn 3 \"gl_CullDistance\"\n"
    721 		"OpName %BP_gl_in \"gl_in\"\n"
    722 		"OpName %BP_out_color \"out_color\"\n"
    723 		"OpName %BP_in_color \"in_color\"\n"
    724 		"${moduleprocessed:opt}\n"
    725 		"OpMemberDecorate %BP_gl_PerVertexOut 0 BuiltIn Position\n"
    726 		"OpMemberDecorate %BP_gl_PerVertexOut 1 BuiltIn PointSize\n"
    727 		"OpMemberDecorate %BP_gl_PerVertexOut 2 BuiltIn ClipDistance\n"
    728 		"OpMemberDecorate %BP_gl_PerVertexOut 3 BuiltIn CullDistance\n"
    729 		"OpDecorate %BP_gl_PerVertexOut Block\n"
    730 		"OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n"
    731 		"OpDecorate %BP_gl_TessCoord BuiltIn TessCoord\n"
    732 		"OpMemberDecorate %BP_gl_PerVertexIn 0 BuiltIn Position\n"
    733 		"OpMemberDecorate %BP_gl_PerVertexIn 1 BuiltIn PointSize\n"
    734 		"OpMemberDecorate %BP_gl_PerVertexIn 2 BuiltIn ClipDistance\n"
    735 		"OpMemberDecorate %BP_gl_PerVertexIn 3 BuiltIn CullDistance\n"
    736 		"OpDecorate %BP_gl_PerVertexIn Block\n"
    737 		"OpDecorate %BP_out_color Location 1\n"
    738 		"OpDecorate %BP_in_color Location 1\n"
    739 		"${IF_decoration:opt}\n"
    740 		"${decoration:opt}\n"
    741 		SPIRV_ASSEMBLY_TYPES
    742 		SPIRV_ASSEMBLY_CONSTANTS
    743 		SPIRV_ASSEMBLY_ARRAYS
    744 		"%BP_gl_PerVertexOut = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
    745 		"%BP_op_gl_PerVertexOut = OpTypePointer Output %BP_gl_PerVertexOut\n"
    746 		"%BP_stream = OpVariable %BP_op_gl_PerVertexOut Output\n"
    747 		"%BP_gl_TessCoord = OpVariable %ip_v3f32 Input\n"
    748 		"%BP_gl_PrimitiveID = OpVariable %op_i32 Input\n"
    749 		"%BP_gl_PerVertexIn = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
    750 		"%BP_a32_gl_PerVertexIn = OpTypeArray %BP_gl_PerVertexIn %c_u32_32\n"
    751 		"%BP_ip_a32_gl_PerVertexIn = OpTypePointer Input %BP_a32_gl_PerVertexIn\n"
    752 		"%BP_gl_in = OpVariable %BP_ip_a32_gl_PerVertexIn Input\n"
    753 		"%BP_out_color = OpVariable %op_v4f32 Output\n"
    754 		"%BP_in_color = OpVariable %ip_a32v4f32 Input\n"
    755 		"${pre_main:opt}\n"
    756 		"${IF_variable:opt}\n"
    757 		"%BP_main = OpFunction %void None %fun\n"
    758 		"%BP_label = OpLabel\n"
    759 		"${IF_carryforward:opt}\n"
    760 		"%BP_gl_TC_0 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n"
    761 		"%BP_gl_TC_1 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n"
    762 		"%BP_gl_TC_2 = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n"
    763 		"%BP_gl_in_gl_Pos_0 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n"
    764 		"%BP_gl_in_gl_Pos_1 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n"
    765 		"%BP_gl_in_gl_Pos_2 = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n"
    766 
    767 		"%BP_gl_OPos = OpAccessChain %op_v4f32 %BP_stream %c_i32_0\n"
    768 		"%BP_in_color_0 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
    769 		"%BP_in_color_1 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
    770 		"%BP_in_color_2 = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
    771 
    772 		"%BP_TC_W_0 = OpLoad %f32 %BP_gl_TC_0\n"
    773 		"%BP_TC_W_1 = OpLoad %f32 %BP_gl_TC_1\n"
    774 		"%BP_TC_W_2 = OpLoad %f32 %BP_gl_TC_2\n"
    775 		"%BP_v4f32_TC_0 = OpCompositeConstruct %v4f32 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0 %BP_TC_W_0\n"
    776 		"%BP_v4f32_TC_1 = OpCompositeConstruct %v4f32 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1 %BP_TC_W_1\n"
    777 		"%BP_v4f32_TC_2 = OpCompositeConstruct %v4f32 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2 %BP_TC_W_2\n"
    778 
    779 		"%BP_gl_IP_0 = OpLoad %v4f32 %BP_gl_in_gl_Pos_0\n"
    780 		"%BP_gl_IP_1 = OpLoad %v4f32 %BP_gl_in_gl_Pos_1\n"
    781 		"%BP_gl_IP_2 = OpLoad %v4f32 %BP_gl_in_gl_Pos_2\n"
    782 
    783 		"%BP_IP_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_gl_IP_0\n"
    784 		"%BP_IP_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_gl_IP_1\n"
    785 		"%BP_IP_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_gl_IP_2\n"
    786 
    787 		"%BP_pos_sum_0 = OpFAdd %v4f32 %BP_IP_W_0 %BP_IP_W_1\n"
    788 		"%BP_pos_sum_1 = OpFAdd %v4f32 %BP_pos_sum_0 %BP_IP_W_2\n"
    789 
    790 		"OpStore %BP_gl_OPos %BP_pos_sum_1\n"
    791 
    792 		"%BP_IC_0 = OpLoad %v4f32 %BP_in_color_0\n"
    793 		"%BP_IC_1 = OpLoad %v4f32 %BP_in_color_1\n"
    794 		"%BP_IC_2 = OpLoad %v4f32 %BP_in_color_2\n"
    795 
    796 		"%BP_IC_W_0 = OpFMul %v4f32 %BP_v4f32_TC_0 %BP_IC_0\n"
    797 		"%BP_IC_W_1 = OpFMul %v4f32 %BP_v4f32_TC_1 %BP_IC_1\n"
    798 		"%BP_IC_W_2 = OpFMul %v4f32 %BP_v4f32_TC_2 %BP_IC_2\n"
    799 
    800 		"%BP_col_sum_0 = OpFAdd %v4f32 %BP_IC_W_0 %BP_IC_W_1\n"
    801 		"%BP_col_sum_1 = OpFAdd %v4f32 %BP_col_sum_0 %BP_IC_W_2\n"
    802 
    803 		"%BP_clr_transformed = OpFunctionCall %v4f32 %test_code %BP_col_sum_1\n"
    804 
    805 		"OpStore %BP_out_color %BP_clr_transformed\n"
    806 		"OpReturn\n"
    807 		"OpFunctionEnd\n"
    808 		"${interface_op_func:opt}\n"
    809 
    810 		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
    811 		"%getId_label = OpLabel\n"
    812 		"%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n"
    813 		"%is_primitive_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
    814 		"%TC_0_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_0\n"
    815 		"%TC_1_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_1\n"
    816 		"%TC_2_loc = OpAccessChain %ip_f32 %BP_gl_TessCoord %c_u32_2\n"
    817 		"%TC_W_0 = OpLoad %f32 %TC_0_loc\n"
    818 		"%TC_W_1 = OpLoad %f32 %TC_1_loc\n"
    819 		"%TC_W_2 = OpLoad %f32 %TC_2_loc\n"
    820 		"%is_W_0_1 = OpFOrdEqual %bool %TC_W_0 %c_f32_1\n"
    821 		"%is_W_1_0 = OpFOrdEqual %bool %TC_W_1 %c_f32_0\n"
    822 		"%is_W_2_0 = OpFOrdEqual %bool %TC_W_2 %c_f32_0\n"
    823 		"%is_tessCoord_1_0 = OpLogicalAnd %bool %is_W_0_1 %is_W_1_0\n"
    824 		"%is_tessCoord_1_0_0 = OpLogicalAnd %bool %is_tessCoord_1_0 %is_W_2_0\n"
    825 		"%is_unique_id_0 = OpLogicalAnd %bool %is_tessCoord_1_0_0 %is_primitive_0\n"
    826 		"OpReturnValue %is_unique_id_0\n"
    827 		"OpFunctionEnd\n"
    828 
    829 		"${testfun}\n";
    830 	return tcu::StringTemplate(tessEvalBoilerplate).specialize(fragments);
    831 }
    832 
    833 // Creates geometry-shader assembly by specializing a boilerplate StringTemplate
    834 // on fragments, which must (at least) map "testfun" to an OpFunction definition
    835 // for %test_code that takes and returns a %v4f32.  Boilerplate IDs are prefixed
    836 // with "BP_" to avoid collisions with fragments.
    837 //
    838 // Derived from this GLSL:
    839 //
    840 // #version 450
    841 // layout(triangles) in;
    842 // layout(triangle_strip, max_vertices = 3) out;
    843 //
    844 // layout(location = 1) in vec4 in_color[];
    845 // layout(location = 1) out vec4 out_color;
    846 //
    847 // void main() {
    848 //   gl_Position = gl_in[0].gl_Position;
    849 //   out_color = test_fun(in_color[0]);
    850 //   EmitVertex();
    851 //   gl_Position = gl_in[1].gl_Position;
    852 //   out_color = test_fun(in_color[1]);
    853 //   EmitVertex();
    854 //   gl_Position = gl_in[2].gl_Position;
    855 //   out_color = test_fun(in_color[2]);
    856 //   EmitVertex();
    857 //   EndPrimitive();
    858 // }
    859 string makeGeometryShaderAssembly(const map<string, string>& fragments)
    860 {
    861 	static const char geometryShaderBoilerplate[] =
    862 		"OpCapability Geometry\n"
    863 		"OpCapability ClipDistance\n"
    864 		"OpCapability CullDistance\n"
    865 		"${capability:opt}\n"
    866 		"${extension:opt}\n"
    867 		"OpMemoryModel Logical GLSL450\n"
    868 		"OpEntryPoint Geometry %BP_main \"main\" %BP_out_gl_position %BP_gl_PrimitiveID %BP_gl_in %BP_out_color %BP_in_color ${IF_entrypoint:opt} \n"
    869 		"OpExecutionMode %BP_main Triangles\n"
    870 		"OpExecutionMode %BP_main OutputTriangleStrip\n"
    871 		"OpExecutionMode %BP_main OutputVertices 3\n"
    872 		"${debug:opt}\n"
    873 		"OpName %BP_main \"main\"\n"
    874 		"OpName %BP_gl_PrimitiveID \"gl_PrimitiveID\"\n"
    875 		"OpName %BP_per_vertex_in \"gl_PerVertex\"\n"
    876 		"OpMemberName %BP_per_vertex_in 0 \"gl_Position\"\n"
    877 		"OpMemberName %BP_per_vertex_in 1 \"gl_PointSize\"\n"
    878 		"OpMemberName %BP_per_vertex_in 2 \"gl_ClipDistance\"\n"
    879 		"OpMemberName %BP_per_vertex_in 3 \"gl_CullDistance\"\n"
    880 		"OpName %BP_gl_in \"gl_in\"\n"
    881 		"OpName %BP_out_color \"out_color\"\n"
    882 		"OpName %BP_in_color \"in_color\"\n"
    883 		"OpName %test_code \"testfun(vf4;\"\n"
    884 		"${moduleprocessed:opt}\n"
    885 		"OpDecorate %BP_gl_PrimitiveID BuiltIn PrimitiveId\n"
    886 		"OpDecorate %BP_out_gl_position BuiltIn Position\n"
    887 		"OpMemberDecorate %BP_per_vertex_in 0 BuiltIn Position\n"
    888 		"OpMemberDecorate %BP_per_vertex_in 1 BuiltIn PointSize\n"
    889 		"OpMemberDecorate %BP_per_vertex_in 2 BuiltIn ClipDistance\n"
    890 		"OpMemberDecorate %BP_per_vertex_in 3 BuiltIn CullDistance\n"
    891 		"OpDecorate %BP_per_vertex_in Block\n"
    892 		"OpDecorate %BP_out_color Location 1\n"
    893 		"OpDecorate %BP_in_color Location 1\n"
    894 		"${IF_decoration:opt}\n"
    895 		"${decoration:opt}\n"
    896 		SPIRV_ASSEMBLY_TYPES
    897 		SPIRV_ASSEMBLY_CONSTANTS
    898 		SPIRV_ASSEMBLY_ARRAYS
    899 		"%BP_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
    900 		"%BP_a3_per_vertex_in = OpTypeArray %BP_per_vertex_in %c_u32_3\n"
    901 		"%BP_ip_a3_per_vertex_in = OpTypePointer Input %BP_a3_per_vertex_in\n"
    902 		"%BP_pp_i32 = OpTypePointer Private %i32\n"
    903 		"%BP_pp_v4i32 = OpTypePointer Private %v4i32\n"
    904 
    905 		"%BP_gl_in = OpVariable %BP_ip_a3_per_vertex_in Input\n"
    906 		"%BP_out_color = OpVariable %op_v4f32 Output\n"
    907 		"%BP_in_color = OpVariable %ip_a3v4f32 Input\n"
    908 		"%BP_gl_PrimitiveID = OpVariable %ip_i32 Input\n"
    909 		"%BP_out_gl_position = OpVariable %op_v4f32 Output\n"
    910 		"%BP_vertexIdInCurrentPatch = OpVariable %BP_pp_v4i32 Private\n"
    911 		"${pre_main:opt}\n"
    912 		"${IF_variable:opt}\n"
    913 
    914 		"%BP_main = OpFunction %void None %fun\n"
    915 		"%BP_label = OpLabel\n"
    916 
    917 		"${IF_carryforward:opt}\n"
    918 
    919 		"%BP_primitiveId = OpLoad %i32 %BP_gl_PrimitiveID\n"
    920 		"%BP_addr_vertexIdInCurrentPatch = OpAccessChain %BP_pp_i32 %BP_vertexIdInCurrentPatch %BP_primitiveId\n"
    921 
    922 		"%BP_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_0 %c_i32_0\n"
    923 		"%BP_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_1 %c_i32_0\n"
    924 		"%BP_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %BP_gl_in %c_i32_2 %c_i32_0\n"
    925 
    926 		"%BP_in_position_0 = OpLoad %v4f32 %BP_gl_in_0_gl_position\n"
    927 		"%BP_in_position_1 = OpLoad %v4f32 %BP_gl_in_1_gl_position\n"
    928 		"%BP_in_position_2 = OpLoad %v4f32 %BP_gl_in_2_gl_position \n"
    929 
    930 		"%BP_in_color_0_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_0\n"
    931 		"%BP_in_color_1_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_1\n"
    932 		"%BP_in_color_2_ptr = OpAccessChain %ip_v4f32 %BP_in_color %c_i32_2\n"
    933 
    934 		"%BP_in_color_0 = OpLoad %v4f32 %BP_in_color_0_ptr\n"
    935 		"%BP_in_color_1 = OpLoad %v4f32 %BP_in_color_1_ptr\n"
    936 		"%BP_in_color_2 = OpLoad %v4f32 %BP_in_color_2_ptr\n"
    937 
    938 		"OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_0\n"
    939 		"%BP_transformed_in_color_0 = OpFunctionCall %v4f32 %test_code %BP_in_color_0\n"
    940 		"OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_1\n"
    941 		"%BP_transformed_in_color_1 = OpFunctionCall %v4f32 %test_code %BP_in_color_1\n"
    942 		"OpStore %BP_addr_vertexIdInCurrentPatch %c_i32_2\n"
    943 		"%BP_transformed_in_color_2 = OpFunctionCall %v4f32 %test_code %BP_in_color_2\n"
    944 
    945 
    946 		"OpStore %BP_out_gl_position %BP_in_position_0\n"
    947 		"OpStore %BP_out_color %BP_transformed_in_color_0\n"
    948 		"OpEmitVertex\n"
    949 
    950 		"OpStore %BP_out_gl_position %BP_in_position_1\n"
    951 		"OpStore %BP_out_color %BP_transformed_in_color_1\n"
    952 		"OpEmitVertex\n"
    953 
    954 		"OpStore %BP_out_gl_position %BP_in_position_2\n"
    955 		"OpStore %BP_out_color %BP_transformed_in_color_2\n"
    956 		"OpEmitVertex\n"
    957 
    958 		"OpEndPrimitive\n"
    959 		"OpReturn\n"
    960 		"OpFunctionEnd\n"
    961 		"${interface_op_func:opt}\n"
    962 
    963 		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
    964 		"%getId_label = OpLabel\n"
    965 		"%primitive_id = OpLoad %i32 %BP_gl_PrimitiveID\n"
    966 		"%addr_vertexIdInCurrentPatch = OpAccessChain %BP_pp_i32 %BP_vertexIdInCurrentPatch %primitive_id\n"
    967 		"%vertexIdInCurrentPatch = OpLoad %i32 %addr_vertexIdInCurrentPatch\n"
    968 		"%is_primitive_0 = OpIEqual %bool %primitive_id %c_i32_0\n"
    969 		"%is_vertex_0 = OpIEqual %bool %vertexIdInCurrentPatch %c_i32_0\n"
    970 		"%is_unique_id_0 = OpLogicalAnd %bool %is_primitive_0 %is_vertex_0\n"
    971 		"OpReturnValue %is_unique_id_0\n"
    972 		"OpFunctionEnd\n"
    973 
    974 		"${testfun}\n";
    975 	return tcu::StringTemplate(geometryShaderBoilerplate).specialize(fragments);
    976 }
    977 
    978 // Creates fragment-shader assembly by specializing a boilerplate StringTemplate
    979 // on fragments, which must (at least) map "testfun" to an OpFunction definition
    980 // for %test_code that takes and returns a %v4f32.  Boilerplate IDs are prefixed
    981 // with "BP_" to avoid collisions with fragments.
    982 //
    983 // Derived from this GLSL:
    984 //
    985 // layout(location = 1) in highp vec4 vtxColor;
    986 // layout(location = 0) out highp vec4 fragColor;
    987 // highp vec4 testfun(highp vec4 x) { return x; }
    988 // void main(void) { fragColor = testfun(vtxColor); }
    989 //
    990 // with modifications including passing vtxColor by value and ripping out
    991 // testfun() definition.
    992 string makeFragmentShaderAssembly(const map<string, string>& fragments)
    993 {
    994 	static const char fragmentShaderBoilerplate[] =
    995 		"OpCapability Shader\n"
    996 		"${capability:opt}\n"
    997 		"${extension:opt}\n"
    998 		"OpMemoryModel Logical GLSL450\n"
    999 		"OpEntryPoint Fragment %BP_main \"main\" %BP_vtxColor %BP_fragColor %BP_gl_FragCoord ${IF_entrypoint:opt} \n"
   1000 		"OpExecutionMode %BP_main OriginUpperLeft\n"
   1001 		"${debug:opt}\n"
   1002 		"OpName %BP_main \"main\"\n"
   1003 		"OpName %BP_gl_FragCoord \"fragCoord\"\n"
   1004 		"OpName %BP_fragColor \"fragColor\"\n"
   1005 		"OpName %BP_vtxColor \"vtxColor\"\n"
   1006 		"OpName %test_code \"testfun(vf4;\"\n"
   1007 		"${moduleprocessed:opt}\n"
   1008 		"OpDecorate %BP_fragColor Location 0\n"
   1009 		"OpDecorate %BP_vtxColor Location 1\n"
   1010 		"OpDecorate %BP_gl_FragCoord BuiltIn FragCoord\n"
   1011 		"${IF_decoration:opt}\n"
   1012 		"${decoration:opt}\n"
   1013 		SPIRV_ASSEMBLY_TYPES
   1014 		SPIRV_ASSEMBLY_CONSTANTS
   1015 		SPIRV_ASSEMBLY_ARRAYS
   1016 		"%BP_gl_FragCoord = OpVariable %ip_v4f32 Input\n"
   1017 		"%BP_fragColor = OpVariable %op_v4f32 Output\n"
   1018 		"%BP_vtxColor = OpVariable %ip_v4f32 Input\n"
   1019 		"${pre_main:opt}\n"
   1020 		"${IF_variable:opt}\n"
   1021 		"%BP_main = OpFunction %void None %fun\n"
   1022 		"%BP_label_main = OpLabel\n"
   1023 		"${IF_carryforward:opt}\n"
   1024 		"%BP_tmp1 = OpLoad %v4f32 %BP_vtxColor\n"
   1025 		"%BP_tmp2 = OpFunctionCall %v4f32 %test_code %BP_tmp1\n"
   1026 		"OpStore %BP_fragColor %BP_tmp2\n"
   1027 		"OpReturn\n"
   1028 		"OpFunctionEnd\n"
   1029 		"${interface_op_func:opt}\n"
   1030 
   1031 		"%isUniqueIdZero = OpFunction %bool None %bool_function\n"
   1032 		"%getId_label = OpLabel\n"
   1033 		"%loc_x_coord = OpAccessChain %ip_f32 %BP_gl_FragCoord %c_i32_0\n"
   1034 		"%loc_y_coord = OpAccessChain %ip_f32 %BP_gl_FragCoord %c_i32_1\n"
   1035 		"%x_coord = OpLoad %f32 %loc_x_coord\n"
   1036 		"%y_coord = OpLoad %f32 %loc_y_coord\n"
   1037 		"%is_x_idx0 = OpFOrdEqual %bool %x_coord %c_f32_0_5\n"
   1038 		"%is_y_idx0 = OpFOrdEqual %bool %y_coord %c_f32_0_5\n"
   1039 		"%is_frag_0 = OpLogicalAnd %bool %is_x_idx0 %is_y_idx0\n"
   1040 		"OpReturnValue %is_frag_0\n"
   1041 		"OpFunctionEnd\n"
   1042 
   1043 		"${testfun}\n";
   1044 	return tcu::StringTemplate(fragmentShaderBoilerplate).specialize(fragments);
   1045 }
   1046 
   1047 // Creates mappings from placeholders to pass-through shader code which copies
   1048 // the input to the output faithfully.
   1049 map<string, string> passthruInterface(const IFDataType& data_type)
   1050 {
   1051 	const string		var_type	= data_type.str();
   1052 	map<string, string>	fragments	= passthruFragments();
   1053 	const string		functype	= string("%") + var_type + "_" + var_type + "_function";
   1054 
   1055 	fragments["interface_op_func"]	=
   1056 		string("%interface_op_func = OpFunction %") + var_type + " None " + functype + "\n"
   1057 		"               %io_param1 = OpFunctionParameter %" + var_type + "\n"
   1058 		"                %IF_label = OpLabel\n"
   1059 		"                            OpReturnValue %io_param1\n"
   1060 		"                            OpFunctionEnd\n";
   1061 	fragments["input_type"]			= var_type;
   1062 	fragments["output_type"]		= var_type;
   1063 	fragments["pre_main"]			= "";
   1064 
   1065 	if (!data_type.elementIs32bit())
   1066 	{
   1067 		if (data_type.elementType == NUMBERTYPE_FLOAT16)
   1068 		{
   1069 			fragments["pre_main"]	+= "%f16 = OpTypeFloat 16\n";
   1070 		}
   1071 		else if (data_type.elementType == NUMBERTYPE_INT16)
   1072 		{
   1073 			fragments["pre_main"]	+= "%i16 = OpTypeInt 16 1\n";
   1074 		}
   1075 		else
   1076 		{
   1077 			fragments["pre_main"]	+= "%u16 = OpTypeInt 16 0\n";
   1078 		}
   1079 
   1080 		fragments["capability"]		= "OpCapability StorageInputOutput16\n";
   1081 		fragments["extension"]		= "OpExtension \"SPV_KHR_16bit_storage\"\n";
   1082 
   1083 		if (data_type.isVector())
   1084 		{
   1085 			fragments["pre_main"]	+= "%" + var_type + " = OpTypeVector %" + IFDataType(1, data_type.elementType).str() + " " + numberToString(data_type.numElements) + "\n";
   1086 		}
   1087 
   1088 		fragments["pre_main"]		+=
   1089 			"%ip_" + var_type + " = OpTypePointer Input %" + var_type + "\n"
   1090 			"%op_" + var_type + " = OpTypePointer Output %" + var_type + "\n";
   1091 	}
   1092 
   1093 	fragments["pre_main"]			+=
   1094 		functype + " = OpTypeFunction %" + var_type + " %" + var_type + "\n"
   1095 		"%a3" + var_type + " = OpTypeArray %" + var_type + " %c_i32_3\n"
   1096 		"%ip_a3" + var_type + " = OpTypePointer Input %a3" + var_type + "\n"
   1097 		"%op_a3" + var_type + " = OpTypePointer Output %a3" + var_type + "\n";
   1098 
   1099 	return fragments;
   1100 }
   1101 
   1102 // Returns mappings from interface placeholders to their concrete values.
   1103 //
   1104 // The concrete values should be specialized again to provide ${input_type}
   1105 // and ${output_type}.
   1106 //
   1107 // %ip_${input_type} and %op_${output_type} should also be defined in the final code.
   1108 map<string, string> fillInterfacePlaceholderVert (void)
   1109 {
   1110 	map<string, string>	fragments	;
   1111 
   1112 	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
   1113 	fragments["IF_variable"]		=
   1114 		" %IF_input = OpVariable %ip_${input_type} Input\n"
   1115 		"%IF_output = OpVariable %op_${output_type} Output\n";
   1116 	fragments["IF_decoration"]		=
   1117 		"OpDecorate  %IF_input Location 2\n"
   1118 		"OpDecorate %IF_output Location 2\n";
   1119 	fragments["IF_carryforward"]	=
   1120 		"%IF_input_val = OpLoad %${input_type} %IF_input\n"
   1121 		"   %IF_result = OpFunctionCall %${output_type} %interface_op_func %IF_input_val\n"
   1122 		"                OpStore %IF_output %IF_result\n";
   1123 
   1124 	// Make sure the rest still need to be instantialized.
   1125 	fragments["capability"]			= "${capability:opt}";
   1126 	fragments["extension"]			= "${extension:opt}";
   1127 	fragments["debug"]				= "${debug:opt}";
   1128 	fragments["decoration"]			= "${decoration:opt}";
   1129 	fragments["pre_main"]			= "${pre_main:opt}";
   1130 	fragments["testfun"]			= "${testfun}";
   1131 	fragments["interface_op_func"]	= "${interface_op_func}";
   1132 
   1133 	return fragments;
   1134 }
   1135 
   1136 // Returns mappings from interface placeholders to their concrete values.
   1137 //
   1138 // The concrete values should be specialized again to provide ${input_type}
   1139 // and ${output_type}.
   1140 //
   1141 // %ip_${input_type} and %op_${output_type} should also be defined in the final code.
   1142 map<string, string> fillInterfacePlaceholderFrag (void)
   1143 {
   1144 	map<string, string>	fragments	;
   1145 
   1146 	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
   1147 	fragments["IF_variable"]		=
   1148 		" %IF_input = OpVariable %ip_${input_type} Input\n"
   1149 		"%IF_output = OpVariable %op_${output_type} Output\n";
   1150 	fragments["IF_decoration"]		=
   1151 		"OpDecorate %IF_input Flat\n"
   1152 		"OpDecorate %IF_input Location 2\n"
   1153 		"OpDecorate %IF_output Location 1\n";  // Fragment shader should write to location #1.
   1154 	fragments["IF_carryforward"]	=
   1155 		"%IF_input_val = OpLoad %${input_type} %IF_input\n"
   1156 		"   %IF_result = OpFunctionCall %${output_type} %interface_op_func %IF_input_val\n"
   1157 		"                OpStore %IF_output %IF_result\n";
   1158 
   1159 	// Make sure the rest still need to be instantialized.
   1160 	fragments["capability"]			= "${capability:opt}";
   1161 	fragments["extension"]			= "${extension:opt}";
   1162 	fragments["debug"]				= "${debug:opt}";
   1163 	fragments["decoration"]			= "${decoration:opt}";
   1164 	fragments["pre_main"]			= "${pre_main:opt}";
   1165 	fragments["testfun"]			= "${testfun}";
   1166 	fragments["interface_op_func"]	= "${interface_op_func}";
   1167 
   1168 	return fragments;
   1169 }
   1170 
   1171 // Returns mappings from interface placeholders to their concrete values.
   1172 //
   1173 // The concrete values should be specialized again to provide ${input_type}
   1174 // and ${output_type}.
   1175 //
   1176 // %ip_${input_type}, %op_${output_type}, %ip_a3${input_type}, and $op_a3${output_type}
   1177 // should also be defined in the final code.
   1178 map<string, string> fillInterfacePlaceholderTessCtrl (void)
   1179 {
   1180 	map<string, string>	fragments	;
   1181 
   1182 	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
   1183 	fragments["IF_variable"]		=
   1184 		" %IF_input = OpVariable %ip_a3${input_type} Input\n"
   1185 		"%IF_output = OpVariable %op_a3${output_type} Output\n";
   1186 	fragments["IF_decoration"]		=
   1187 		"OpDecorate  %IF_input Location 2\n"
   1188 		"OpDecorate %IF_output Location 2\n";
   1189 	fragments["IF_carryforward"]	=
   1190 		" %IF_input_ptr0 = OpAccessChain %ip_${input_type} %IF_input %c_i32_0\n"
   1191 		" %IF_input_ptr1 = OpAccessChain %ip_${input_type} %IF_input %c_i32_1\n"
   1192 		" %IF_input_ptr2 = OpAccessChain %ip_${input_type} %IF_input %c_i32_2\n"
   1193 		"%IF_output_ptr0 = OpAccessChain %op_${output_type} %IF_output %c_i32_0\n"
   1194 		"%IF_output_ptr1 = OpAccessChain %op_${output_type} %IF_output %c_i32_1\n"
   1195 		"%IF_output_ptr2 = OpAccessChain %op_${output_type} %IF_output %c_i32_2\n"
   1196 		"%IF_input_val0 = OpLoad %${input_type} %IF_input_ptr0\n"
   1197 		"%IF_input_val1 = OpLoad %${input_type} %IF_input_ptr1\n"
   1198 		"%IF_input_val2 = OpLoad %${input_type} %IF_input_ptr2\n"
   1199 		"%IF_input_res0 = OpFunctionCall %${output_type} %interface_op_func %IF_input_val0\n"
   1200 		"%IF_input_res1 = OpFunctionCall %${output_type} %interface_op_func %IF_input_val1\n"
   1201 		"%IF_input_res2 = OpFunctionCall %${output_type} %interface_op_func %IF_input_val2\n"
   1202 		"OpStore %IF_output_ptr0 %IF_input_res0\n"
   1203 		"OpStore %IF_output_ptr1 %IF_input_res1\n"
   1204 		"OpStore %IF_output_ptr2 %IF_input_res2\n";
   1205 
   1206 	// Make sure the rest still need to be instantialized.
   1207 	fragments["capability"]			= "${capability:opt}";
   1208 	fragments["extension"]			= "${extension:opt}";
   1209 	fragments["debug"]				= "${debug:opt}";
   1210 	fragments["decoration"]			= "${decoration:opt}";
   1211 	fragments["pre_main"]			= "${pre_main:opt}";
   1212 	fragments["testfun"]			= "${testfun}";
   1213 	fragments["interface_op_func"]	= "${interface_op_func}";
   1214 
   1215 	return fragments;
   1216 }
   1217 
   1218 // Returns mappings from interface placeholders to their concrete values.
   1219 //
   1220 // The concrete values should be specialized again to provide ${input_type}
   1221 // and ${output_type}.
   1222 //
   1223 // %ip_${input_type}, %op_${output_type}, %ip_a3${input_type}, and $op_a3${output_type}
   1224 // should also be defined in the final code.
   1225 map<string, string> fillInterfacePlaceholderTessEvalGeom (void)
   1226 {
   1227 	map<string, string>	fragments	;
   1228 
   1229 	fragments["IF_entrypoint"]		= "%IF_input %IF_output";
   1230 	fragments["IF_variable"]		=
   1231 		" %IF_input = OpVariable %ip_a3${input_type} Input\n"
   1232 		"%IF_output = OpVariable %op_${output_type} Output\n";
   1233 	fragments["IF_decoration"]		=
   1234 		"OpDecorate  %IF_input Location 2\n"
   1235 		"OpDecorate %IF_output Location 2\n";
   1236 	fragments["IF_carryforward"]	=
   1237 		// Only get the first value since all three values are the same anyway.
   1238 		" %IF_input_ptr0 = OpAccessChain %ip_${input_type} %IF_input %c_i32_0\n"
   1239 		" %IF_input_val0 = OpLoad %${input_type} %IF_input_ptr0\n"
   1240 		" %IF_input_res0 = OpFunctionCall %${output_type} %interface_op_func %IF_input_val0\n"
   1241 		"OpStore %IF_output %IF_input_res0\n";
   1242 
   1243 	// Make sure the rest still need to be instantialized.
   1244 	fragments["capability"]			= "${capability:opt}";
   1245 	fragments["extension"]			= "${extension:opt}";
   1246 	fragments["debug"]				= "${debug:opt}";
   1247 	fragments["decoration"]			= "${decoration:opt}";
   1248 	fragments["pre_main"]			= "${pre_main:opt}";
   1249 	fragments["testfun"]			= "${testfun}";
   1250 	fragments["interface_op_func"]	= "${interface_op_func}";
   1251 
   1252 	return fragments;
   1253 }
   1254 
   1255 map<string, string> passthruFragments(void)
   1256 {
   1257 	map<string, string> fragments;
   1258 	fragments["testfun"] =
   1259 		// A %test_code function that returns its argument unchanged.
   1260 		"%test_code = OpFunction %v4f32 None %v4f32_function\n"
   1261 		"%param1 = OpFunctionParameter %v4f32\n"
   1262 		"%label_testfun = OpLabel\n"
   1263 		"OpReturnValue %param1\n"
   1264 		"OpFunctionEnd\n";
   1265 	return fragments;
   1266 }
   1267 
   1268 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
   1269 // Vertex shader gets custom code from context, the rest are pass-through.
   1270 void addShaderCodeCustomVertex (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
   1271 {
   1272 	SpirvVersion targetSpirvVersion;
   1273 
   1274 	if (spirVAsmBuildOptions == DE_NULL)
   1275 		targetSpirvVersion = context.resources.spirvVersion;
   1276 	else
   1277 		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
   1278 
   1279 	if (!context.interfaces.empty())
   1280 	{
   1281 		// Inject boilerplate code to wire up additional input/output variables between stages.
   1282 		// Just copy the contents in input variable to output variable in all stages except
   1283 		// the customized stage.
   1284 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(targetSpirvVersion);
   1285 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(targetSpirvVersion);
   1286 	} else {
   1287 		map<string, string> passthru = passthruFragments();
   1288 
   1289 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(targetSpirvVersion);
   1290 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(targetSpirvVersion);
   1291 	}
   1292 }
   1293 
   1294 void addShaderCodeCustomVertex (vk::SourceCollections& dst, InstanceContext context)
   1295 {
   1296 	addShaderCodeCustomVertex(dst, context, DE_NULL);
   1297 }
   1298 
   1299 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
   1300 // Tessellation control shader gets custom code from context, the rest are
   1301 // pass-through.
   1302 void addShaderCodeCustomTessControl(vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
   1303 {
   1304 	SpirvVersion targetSpirvVersion;
   1305 
   1306 	if (spirVAsmBuildOptions == DE_NULL)
   1307 		targetSpirvVersion = context.resources.spirvVersion;
   1308 	else
   1309 		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
   1310 
   1311 	if (!context.interfaces.empty())
   1312 	{
   1313 		// Inject boilerplate code to wire up additional input/output variables between stages.
   1314 		// Just copy the contents in input variable to output variable in all stages except
   1315 		// the customized stage.
   1316 		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(targetSpirvVersion);
   1317 		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(targetSpirvVersion);
   1318 		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(targetSpirvVersion);
   1319 		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(targetSpirvVersion);
   1320 	}
   1321 	else
   1322 	{
   1323 		map<string, string> passthru = passthruFragments();
   1324 
   1325 		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(targetSpirvVersion);
   1326 		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << makeTessControlShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(targetSpirvVersion);
   1327 		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << makeTessEvalShaderAssembly(passthru) << SpirVAsmBuildOptions(targetSpirvVersion);
   1328 		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(targetSpirvVersion);
   1329 	}
   1330 }
   1331 
   1332 void addShaderCodeCustomTessControl (vk::SourceCollections& dst, InstanceContext context)
   1333 {
   1334 	addShaderCodeCustomTessControl(dst, context, DE_NULL);
   1335 }
   1336 
   1337 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
   1338 // Tessellation evaluation shader gets custom code from context, the rest are
   1339 // pass-through.
   1340 void addShaderCodeCustomTessEval(vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
   1341 {
   1342 	SpirvVersion targetSpirvVersion;
   1343 
   1344 	if (spirVAsmBuildOptions == DE_NULL)
   1345 		targetSpirvVersion = context.resources.spirvVersion;
   1346 	else
   1347 		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
   1348 
   1349 	if (!context.interfaces.empty())
   1350 	{
   1351 		// Inject boilerplate code to wire up additional input/output variables between stages.
   1352 		// Just copy the contents in input variable to output variable in all stages except
   1353 		// the customized stage.
   1354 		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(targetSpirvVersion);
   1355 		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << StringTemplate(makeTessControlShaderAssembly(fillInterfacePlaceholderTessCtrl())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(targetSpirvVersion);
   1356 		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << StringTemplate(makeTessEvalShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(targetSpirvVersion);
   1357 		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(targetSpirvVersion);
   1358 	}
   1359 	else
   1360 	{
   1361 		map<string, string> passthru = passthruFragments();
   1362 		dst.spirvAsmSources.add("vert",  spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(targetSpirvVersion);
   1363 		dst.spirvAsmSources.add("tessc", spirVAsmBuildOptions) << makeTessControlShaderAssembly(passthru) << SpirVAsmBuildOptions(targetSpirvVersion);
   1364 		dst.spirvAsmSources.add("tesse", spirVAsmBuildOptions) << makeTessEvalShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(targetSpirvVersion);
   1365 		dst.spirvAsmSources.add("frag",  spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(targetSpirvVersion);
   1366 	}
   1367 }
   1368 
   1369 void addShaderCodeCustomTessEval (vk::SourceCollections& dst, InstanceContext context)
   1370 {
   1371 	addShaderCodeCustomTessEval(dst, context, DE_NULL);
   1372 }
   1373 
   1374 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
   1375 // Geometry shader gets custom code from context, the rest are pass-through.
   1376 void addShaderCodeCustomGeometry (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
   1377 {
   1378 	SpirvVersion targetSpirvVersion;
   1379 
   1380 	if (spirVAsmBuildOptions == DE_NULL)
   1381 		targetSpirvVersion = context.resources.spirvVersion;
   1382 	else
   1383 		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
   1384 
   1385 	if (!context.interfaces.empty())
   1386 	{
   1387 		// Inject boilerplate code to wire up additional input/output variables between stages.
   1388 		// Just copy the contents in input variable to output variable in all stages except
   1389 		// the customized stage.
   1390 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(targetSpirvVersion);
   1391 		dst.spirvAsmSources.add("geom", spirVAsmBuildOptions) << StringTemplate(makeGeometryShaderAssembly(fillInterfacePlaceholderTessEvalGeom())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(targetSpirvVersion);
   1392 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(passthruInterface(context.interfaces.getOutputType())) << SpirVAsmBuildOptions(targetSpirvVersion);
   1393 	}
   1394 	else
   1395 	{
   1396 		map<string, string> passthru = passthruFragments();
   1397 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(targetSpirvVersion);
   1398 		dst.spirvAsmSources.add("geom", spirVAsmBuildOptions) << makeGeometryShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(targetSpirvVersion);
   1399 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(passthru) << SpirVAsmBuildOptions(targetSpirvVersion);
   1400 	}
   1401 }
   1402 
   1403 void addShaderCodeCustomGeometry (vk::SourceCollections& dst, InstanceContext context)
   1404 {
   1405 	addShaderCodeCustomGeometry(dst, context, DE_NULL);
   1406 }
   1407 
   1408 // Adds shader assembly text to dst.spirvAsmSources for all shader kinds.
   1409 // Fragment shader gets custom code from context, the rest are pass-through.
   1410 void addShaderCodeCustomFragment (vk::SourceCollections& dst, InstanceContext& context, const SpirVAsmBuildOptions* spirVAsmBuildOptions)
   1411 {
   1412 	SpirvVersion targetSpirvVersion;
   1413 
   1414 	if (spirVAsmBuildOptions == DE_NULL)
   1415 		targetSpirvVersion = context.resources.spirvVersion;
   1416 	else
   1417 		targetSpirvVersion = spirVAsmBuildOptions->targetVersion;
   1418 
   1419 	if (!context.interfaces.empty())
   1420 	{
   1421 		// Inject boilerplate code to wire up additional input/output variables between stages.
   1422 		// Just copy the contents in input variable to output variable in all stages except
   1423 		// the customized stage.
   1424 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << StringTemplate(makeVertexShaderAssembly(fillInterfacePlaceholderVert())).specialize(passthruInterface(context.interfaces.getInputType())) << SpirVAsmBuildOptions(targetSpirvVersion);
   1425 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << StringTemplate(makeFragmentShaderAssembly(fillInterfacePlaceholderFrag())).specialize(context.testCodeFragments) << SpirVAsmBuildOptions(targetSpirvVersion);
   1426 	}
   1427 	else
   1428 	{
   1429 		map<string, string> passthru = passthruFragments();
   1430 		dst.spirvAsmSources.add("vert", spirVAsmBuildOptions) << makeVertexShaderAssembly(passthru) << SpirVAsmBuildOptions(targetSpirvVersion);
   1431 		dst.spirvAsmSources.add("frag", spirVAsmBuildOptions) << makeFragmentShaderAssembly(context.testCodeFragments) << SpirVAsmBuildOptions(targetSpirvVersion);
   1432 	}
   1433 }
   1434 
   1435 void addShaderCodeCustomFragment (vk::SourceCollections& dst, InstanceContext context)
   1436 {
   1437 	addShaderCodeCustomFragment(dst, context, DE_NULL);
   1438 }
   1439 
   1440 void createCombinedModule(vk::SourceCollections& dst, InstanceContext)
   1441 {
   1442 	// \todo [2015-12-07 awoloszyn] Make tessellation / geometry conditional
   1443 	// \todo [2015-12-07 awoloszyn] Remove OpName and OpMemberName at some point
   1444 	dst.spirvAsmSources.add("module") <<
   1445 		"OpCapability Shader\n"
   1446 		"OpCapability ClipDistance\n"
   1447 		"OpCapability CullDistance\n"
   1448 		"OpCapability Geometry\n"
   1449 		"OpCapability Tessellation\n"
   1450 		"OpMemoryModel Logical GLSL450\n"
   1451 
   1452 		"OpEntryPoint Vertex %vert_main \"main\" %vert_Position %vert_vtxColor %vert_color %vert_vtxPosition %vert_vertex_id %vert_instance_id\n"
   1453 		"OpEntryPoint Geometry %geom_main \"main\" %geom_out_gl_position %geom_gl_in %geom_out_color %geom_in_color\n"
   1454 		"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"
   1455 		"OpEntryPoint TessellationEvaluation %tesse_main \"main\" %tesse_stream %tesse_gl_tessCoord %tesse_in_position %tesse_out_color %tesse_in_color \n"
   1456 		"OpEntryPoint Fragment %frag_main \"main\" %frag_vtxColor %frag_fragColor\n"
   1457 
   1458 		"OpExecutionMode %geom_main Triangles\n"
   1459 		"OpExecutionMode %geom_main OutputTriangleStrip\n"
   1460 		"OpExecutionMode %geom_main OutputVertices 3\n"
   1461 
   1462 		"OpExecutionMode %tessc_main OutputVertices 3\n"
   1463 
   1464 		"OpExecutionMode %tesse_main Triangles\n"
   1465 		"OpExecutionMode %tesse_main SpacingEqual\n"
   1466 		"OpExecutionMode %tesse_main VertexOrderCcw\n"
   1467 
   1468 		"OpExecutionMode %frag_main OriginUpperLeft\n"
   1469 
   1470 		"OpName %vert_main \"main\"\n"
   1471 		"OpName %vert_vtxPosition \"vtxPosition\"\n"
   1472 		"OpName %vert_Position \"position\"\n"
   1473 		"OpName %vert_vtxColor \"vtxColor\"\n"
   1474 		"OpName %vert_color \"color\"\n"
   1475 		"OpName %vert_vertex_id \"gl_VertexIndex\"\n"
   1476 		"OpName %vert_instance_id \"gl_InstanceIndex\"\n"
   1477 		"OpName %geom_main \"main\"\n"
   1478 		"OpName %geom_per_vertex_in \"gl_PerVertex\"\n"
   1479 		"OpMemberName %geom_per_vertex_in 0 \"gl_Position\"\n"
   1480 		"OpMemberName %geom_per_vertex_in 1 \"gl_PointSize\"\n"
   1481 		"OpMemberName %geom_per_vertex_in 2 \"gl_ClipDistance\"\n"
   1482 		"OpMemberName %geom_per_vertex_in 3 \"gl_CullDistance\"\n"
   1483 		"OpName %geom_gl_in \"gl_in\"\n"
   1484 		"OpName %geom_out_color \"out_color\"\n"
   1485 		"OpName %geom_in_color \"in_color\"\n"
   1486 		"OpName %tessc_main \"main\"\n"
   1487 		"OpName %tessc_out_color \"out_color\"\n"
   1488 		"OpName %tessc_gl_InvocationID \"gl_InvocationID\"\n"
   1489 		"OpName %tessc_in_color \"in_color\"\n"
   1490 		"OpName %tessc_out_position \"out_position\"\n"
   1491 		"OpName %tessc_in_position \"in_position\"\n"
   1492 		"OpName %tessc_gl_TessLevelOuter \"gl_TessLevelOuter\"\n"
   1493 		"OpName %tessc_gl_TessLevelInner \"gl_TessLevelInner\"\n"
   1494 		"OpName %tesse_main \"main\"\n"
   1495 		"OpName %tesse_per_vertex_out \"gl_PerVertex\"\n"
   1496 		"OpMemberName %tesse_per_vertex_out 0 \"gl_Position\"\n"
   1497 		"OpMemberName %tesse_per_vertex_out 1 \"gl_PointSize\"\n"
   1498 		"OpMemberName %tesse_per_vertex_out 2 \"gl_ClipDistance\"\n"
   1499 		"OpMemberName %tesse_per_vertex_out 3 \"gl_CullDistance\"\n"
   1500 		"OpName %tesse_stream \"\"\n"
   1501 		"OpName %tesse_gl_tessCoord \"gl_TessCoord\"\n"
   1502 		"OpName %tesse_in_position \"in_position\"\n"
   1503 		"OpName %tesse_out_color \"out_color\"\n"
   1504 		"OpName %tesse_in_color \"in_color\"\n"
   1505 		"OpName %frag_main \"main\"\n"
   1506 		"OpName %frag_fragColor \"fragColor\"\n"
   1507 		"OpName %frag_vtxColor \"vtxColor\"\n"
   1508 
   1509 		"; Vertex decorations\n"
   1510 		"OpDecorate %vert_vtxPosition Location 2\n"
   1511 		"OpDecorate %vert_Position Location 0\n"
   1512 		"OpDecorate %vert_vtxColor Location 1\n"
   1513 		"OpDecorate %vert_color Location 1\n"
   1514 		"OpDecorate %vert_vertex_id BuiltIn VertexIndex\n"
   1515 		"OpDecorate %vert_instance_id BuiltIn InstanceIndex\n"
   1516 
   1517 		"; Geometry decorations\n"
   1518 		"OpDecorate %geom_out_gl_position BuiltIn Position\n"
   1519 		"OpMemberDecorate %geom_per_vertex_in 0 BuiltIn Position\n"
   1520 		"OpMemberDecorate %geom_per_vertex_in 1 BuiltIn PointSize\n"
   1521 		"OpMemberDecorate %geom_per_vertex_in 2 BuiltIn ClipDistance\n"
   1522 		"OpMemberDecorate %geom_per_vertex_in 3 BuiltIn CullDistance\n"
   1523 		"OpDecorate %geom_per_vertex_in Block\n"
   1524 		"OpDecorate %geom_out_color Location 1\n"
   1525 		"OpDecorate %geom_in_color Location 1\n"
   1526 
   1527 		"; Tessellation Control decorations\n"
   1528 		"OpDecorate %tessc_out_color Location 1\n"
   1529 		"OpDecorate %tessc_gl_InvocationID BuiltIn InvocationId\n"
   1530 		"OpDecorate %tessc_in_color Location 1\n"
   1531 		"OpDecorate %tessc_out_position Location 2\n"
   1532 		"OpDecorate %tessc_in_position Location 2\n"
   1533 		"OpDecorate %tessc_gl_TessLevelOuter Patch\n"
   1534 		"OpDecorate %tessc_gl_TessLevelOuter BuiltIn TessLevelOuter\n"
   1535 		"OpDecorate %tessc_gl_TessLevelInner Patch\n"
   1536 		"OpDecorate %tessc_gl_TessLevelInner BuiltIn TessLevelInner\n"
   1537 
   1538 		"; Tessellation Evaluation decorations\n"
   1539 		"OpMemberDecorate %tesse_per_vertex_out 0 BuiltIn Position\n"
   1540 		"OpMemberDecorate %tesse_per_vertex_out 1 BuiltIn PointSize\n"
   1541 		"OpMemberDecorate %tesse_per_vertex_out 2 BuiltIn ClipDistance\n"
   1542 		"OpMemberDecorate %tesse_per_vertex_out 3 BuiltIn CullDistance\n"
   1543 		"OpDecorate %tesse_per_vertex_out Block\n"
   1544 		"OpDecorate %tesse_gl_tessCoord BuiltIn TessCoord\n"
   1545 		"OpDecorate %tesse_in_position Location 2\n"
   1546 		"OpDecorate %tesse_out_color Location 1\n"
   1547 		"OpDecorate %tesse_in_color Location 1\n"
   1548 
   1549 		"; Fragment decorations\n"
   1550 		"OpDecorate %frag_fragColor Location 0\n"
   1551 		"OpDecorate %frag_vtxColor Location 1\n"
   1552 
   1553 		SPIRV_ASSEMBLY_TYPES
   1554 		SPIRV_ASSEMBLY_CONSTANTS
   1555 		SPIRV_ASSEMBLY_ARRAYS
   1556 
   1557 		"; Vertex Variables\n"
   1558 		"%vert_vtxPosition = OpVariable %op_v4f32 Output\n"
   1559 		"%vert_Position = OpVariable %ip_v4f32 Input\n"
   1560 		"%vert_vtxColor = OpVariable %op_v4f32 Output\n"
   1561 		"%vert_color = OpVariable %ip_v4f32 Input\n"
   1562 		"%vert_vertex_id = OpVariable %ip_i32 Input\n"
   1563 		"%vert_instance_id = OpVariable %ip_i32 Input\n"
   1564 
   1565 		"; Geometry Variables\n"
   1566 		"%geom_per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
   1567 		"%geom_a3_per_vertex_in = OpTypeArray %geom_per_vertex_in %c_u32_3\n"
   1568 		"%geom_ip_a3_per_vertex_in = OpTypePointer Input %geom_a3_per_vertex_in\n"
   1569 		"%geom_gl_in = OpVariable %geom_ip_a3_per_vertex_in Input\n"
   1570 		"%geom_out_color = OpVariable %op_v4f32 Output\n"
   1571 		"%geom_in_color = OpVariable %ip_a3v4f32 Input\n"
   1572 		"%geom_out_gl_position = OpVariable %op_v4f32 Output\n"
   1573 
   1574 		"; Tessellation Control Variables\n"
   1575 		"%tessc_out_color = OpVariable %op_a3v4f32 Output\n"
   1576 		"%tessc_gl_InvocationID = OpVariable %ip_i32 Input\n"
   1577 		"%tessc_in_color = OpVariable %ip_a32v4f32 Input\n"
   1578 		"%tessc_out_position = OpVariable %op_a3v4f32 Output\n"
   1579 		"%tessc_in_position = OpVariable %ip_a32v4f32 Input\n"
   1580 		"%tessc_gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
   1581 		"%tessc_gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
   1582 
   1583 		"; Tessellation Evaluation Decorations\n"
   1584 		"%tesse_per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
   1585 		"%tesse_op_per_vertex_out = OpTypePointer Output %tesse_per_vertex_out\n"
   1586 		"%tesse_stream = OpVariable %tesse_op_per_vertex_out Output\n"
   1587 		"%tesse_gl_tessCoord = OpVariable %ip_v3f32 Input\n"
   1588 		"%tesse_in_position = OpVariable %ip_a32v4f32 Input\n"
   1589 		"%tesse_out_color = OpVariable %op_v4f32 Output\n"
   1590 		"%tesse_in_color = OpVariable %ip_a32v4f32 Input\n"
   1591 
   1592 		"; Fragment Variables\n"
   1593 		"%frag_fragColor = OpVariable %op_v4f32 Output\n"
   1594 		"%frag_vtxColor = OpVariable %ip_v4f32 Input\n"
   1595 
   1596 		"; Vertex Entry\n"
   1597 		"%vert_main = OpFunction %void None %fun\n"
   1598 		"%vert_label = OpLabel\n"
   1599 		"%vert_tmp_position = OpLoad %v4f32 %vert_Position\n"
   1600 		"OpStore %vert_vtxPosition %vert_tmp_position\n"
   1601 		"%vert_tmp_color = OpLoad %v4f32 %vert_color\n"
   1602 		"OpStore %vert_vtxColor %vert_tmp_color\n"
   1603 		"OpReturn\n"
   1604 		"OpFunctionEnd\n"
   1605 
   1606 		"; Geometry Entry\n"
   1607 		"%geom_main = OpFunction %void None %fun\n"
   1608 		"%geom_label = OpLabel\n"
   1609 		"%geom_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_0 %c_i32_0\n"
   1610 		"%geom_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_1 %c_i32_0\n"
   1611 		"%geom_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %geom_gl_in %c_i32_2 %c_i32_0\n"
   1612 		"%geom_in_position_0 = OpLoad %v4f32 %geom_gl_in_0_gl_position\n"
   1613 		"%geom_in_position_1 = OpLoad %v4f32 %geom_gl_in_1_gl_position\n"
   1614 		"%geom_in_position_2 = OpLoad %v4f32 %geom_gl_in_2_gl_position \n"
   1615 		"%geom_in_color_0_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_0\n"
   1616 		"%geom_in_color_1_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_1\n"
   1617 		"%geom_in_color_2_ptr = OpAccessChain %ip_v4f32 %geom_in_color %c_i32_2\n"
   1618 		"%geom_in_color_0 = OpLoad %v4f32 %geom_in_color_0_ptr\n"
   1619 		"%geom_in_color_1 = OpLoad %v4f32 %geom_in_color_1_ptr\n"
   1620 		"%geom_in_color_2 = OpLoad %v4f32 %geom_in_color_2_ptr\n"
   1621 		"OpStore %geom_out_gl_position %geom_in_position_0\n"
   1622 		"OpStore %geom_out_color %geom_in_color_0\n"
   1623 		"OpEmitVertex\n"
   1624 		"OpStore %geom_out_gl_position %geom_in_position_1\n"
   1625 		"OpStore %geom_out_color %geom_in_color_1\n"
   1626 		"OpEmitVertex\n"
   1627 		"OpStore %geom_out_gl_position %geom_in_position_2\n"
   1628 		"OpStore %geom_out_color %geom_in_color_2\n"
   1629 		"OpEmitVertex\n"
   1630 		"OpEndPrimitive\n"
   1631 		"OpReturn\n"
   1632 		"OpFunctionEnd\n"
   1633 
   1634 		"; Tessellation Control Entry\n"
   1635 		"%tessc_main = OpFunction %void None %fun\n"
   1636 		"%tessc_label = OpLabel\n"
   1637 		"%tessc_invocation_id = OpLoad %i32 %tessc_gl_InvocationID\n"
   1638 		"%tessc_in_color_ptr = OpAccessChain %ip_v4f32 %tessc_in_color %tessc_invocation_id\n"
   1639 		"%tessc_in_position_ptr = OpAccessChain %ip_v4f32 %tessc_in_position %tessc_invocation_id\n"
   1640 		"%tessc_in_color_val = OpLoad %v4f32 %tessc_in_color_ptr\n"
   1641 		"%tessc_in_position_val = OpLoad %v4f32 %tessc_in_position_ptr\n"
   1642 		"%tessc_out_color_ptr = OpAccessChain %op_v4f32 %tessc_out_color %tessc_invocation_id\n"
   1643 		"%tessc_out_position_ptr = OpAccessChain %op_v4f32 %tessc_out_position %tessc_invocation_id\n"
   1644 		"OpStore %tessc_out_color_ptr %tessc_in_color_val\n"
   1645 		"OpStore %tessc_out_position_ptr %tessc_in_position_val\n"
   1646 		"%tessc_is_first_invocation = OpIEqual %bool %tessc_invocation_id %c_i32_0\n"
   1647 		"OpSelectionMerge %tessc_merge_label None\n"
   1648 		"OpBranchConditional %tessc_is_first_invocation %tessc_first_invocation %tessc_merge_label\n"
   1649 		"%tessc_first_invocation = OpLabel\n"
   1650 		"%tessc_tess_outer_0 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_0\n"
   1651 		"%tessc_tess_outer_1 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_1\n"
   1652 		"%tessc_tess_outer_2 = OpAccessChain %op_f32 %tessc_gl_TessLevelOuter %c_i32_2\n"
   1653 		"%tessc_tess_inner = OpAccessChain %op_f32 %tessc_gl_TessLevelInner %c_i32_0\n"
   1654 		"OpStore %tessc_tess_outer_0 %c_f32_1\n"
   1655 		"OpStore %tessc_tess_outer_1 %c_f32_1\n"
   1656 		"OpStore %tessc_tess_outer_2 %c_f32_1\n"
   1657 		"OpStore %tessc_tess_inner %c_f32_1\n"
   1658 		"OpBranch %tessc_merge_label\n"
   1659 		"%tessc_merge_label = OpLabel\n"
   1660 		"OpReturn\n"
   1661 		"OpFunctionEnd\n"
   1662 
   1663 		"; Tessellation Evaluation Entry\n"
   1664 		"%tesse_main = OpFunction %void None %fun\n"
   1665 		"%tesse_label = OpLabel\n"
   1666 		"%tesse_tc_0_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_0\n"
   1667 		"%tesse_tc_1_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_1\n"
   1668 		"%tesse_tc_2_ptr = OpAccessChain %ip_f32 %tesse_gl_tessCoord %c_u32_2\n"
   1669 		"%tesse_tc_0 = OpLoad %f32 %tesse_tc_0_ptr\n"
   1670 		"%tesse_tc_1 = OpLoad %f32 %tesse_tc_1_ptr\n"
   1671 		"%tesse_tc_2 = OpLoad %f32 %tesse_tc_2_ptr\n"
   1672 		"%tesse_in_pos_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_0\n"
   1673 		"%tesse_in_pos_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_1\n"
   1674 		"%tesse_in_pos_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_position %c_i32_2\n"
   1675 		"%tesse_in_pos_0 = OpLoad %v4f32 %tesse_in_pos_0_ptr\n"
   1676 		"%tesse_in_pos_1 = OpLoad %v4f32 %tesse_in_pos_1_ptr\n"
   1677 		"%tesse_in_pos_2 = OpLoad %v4f32 %tesse_in_pos_2_ptr\n"
   1678 		"%tesse_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_0 %tesse_tc_0\n"
   1679 		"%tesse_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_1 %tesse_tc_1\n"
   1680 		"%tesse_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_pos_2 %tesse_tc_2\n"
   1681 		"%tesse_out_pos_ptr = OpAccessChain %op_v4f32 %tesse_stream %c_i32_0\n"
   1682 		"%tesse_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse_in_pos_0_weighted %tesse_in_pos_1_weighted\n"
   1683 		"%tesse_computed_out = OpFAdd %v4f32 %tesse_in_pos_0_plus_pos_1 %tesse_in_pos_2_weighted\n"
   1684 		"OpStore %tesse_out_pos_ptr %tesse_computed_out\n"
   1685 		"%tesse_in_clr_0_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_0\n"
   1686 		"%tesse_in_clr_1_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_1\n"
   1687 		"%tesse_in_clr_2_ptr = OpAccessChain %ip_v4f32 %tesse_in_color %c_i32_2\n"
   1688 		"%tesse_in_clr_0 = OpLoad %v4f32 %tesse_in_clr_0_ptr\n"
   1689 		"%tesse_in_clr_1 = OpLoad %v4f32 %tesse_in_clr_1_ptr\n"
   1690 		"%tesse_in_clr_2 = OpLoad %v4f32 %tesse_in_clr_2_ptr\n"
   1691 		"%tesse_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_0 %tesse_tc_0\n"
   1692 		"%tesse_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_1 %tesse_tc_1\n"
   1693 		"%tesse_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse_in_clr_2 %tesse_tc_2\n"
   1694 		"%tesse_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse_in_clr_0_weighted %tesse_in_clr_1_weighted\n"
   1695 		"%tesse_computed_clr = OpFAdd %v4f32 %tesse_in_clr_0_plus_col_1 %tesse_in_clr_2_weighted\n"
   1696 		"OpStore %tesse_out_color %tesse_computed_clr\n"
   1697 		"OpReturn\n"
   1698 		"OpFunctionEnd\n"
   1699 
   1700 		"; Fragment Entry\n"
   1701 		"%frag_main = OpFunction %void None %fun\n"
   1702 		"%frag_label_main = OpLabel\n"
   1703 		"%frag_tmp1 = OpLoad %v4f32 %frag_vtxColor\n"
   1704 		"OpStore %frag_fragColor %frag_tmp1\n"
   1705 		"OpReturn\n"
   1706 		"OpFunctionEnd\n";
   1707 }
   1708 
   1709 void createMultipleEntries(vk::SourceCollections& dst, InstanceContext)
   1710 {
   1711 	dst.spirvAsmSources.add("vert") <<
   1712 	// This module contains 2 vertex shaders. One that is a passthrough
   1713 	// and a second that inverts the color of the output (1.0 - color).
   1714 		"OpCapability Shader\n"
   1715 		"OpMemoryModel Logical GLSL450\n"
   1716 		"OpEntryPoint Vertex %main \"vert1\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
   1717 		"OpEntryPoint Vertex %main2 \"vert2\" %Position %vtxColor %color %vtxPosition %vertex_id %instance_id\n"
   1718 
   1719 		"OpName %main \"vert1\"\n"
   1720 		"OpName %main2 \"vert2\"\n"
   1721 		"OpName %vtxPosition \"vtxPosition\"\n"
   1722 		"OpName %Position \"position\"\n"
   1723 		"OpName %vtxColor \"vtxColor\"\n"
   1724 		"OpName %color \"color\"\n"
   1725 		"OpName %vertex_id \"gl_VertexIndex\"\n"
   1726 		"OpName %instance_id \"gl_InstanceIndex\"\n"
   1727 
   1728 		"OpDecorate %vtxPosition Location 2\n"
   1729 		"OpDecorate %Position Location 0\n"
   1730 		"OpDecorate %vtxColor Location 1\n"
   1731 		"OpDecorate %color Location 1\n"
   1732 		"OpDecorate %vertex_id BuiltIn VertexIndex\n"
   1733 		"OpDecorate %instance_id BuiltIn InstanceIndex\n"
   1734 		SPIRV_ASSEMBLY_TYPES
   1735 		SPIRV_ASSEMBLY_CONSTANTS
   1736 		SPIRV_ASSEMBLY_ARRAYS
   1737 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
   1738 		"%vtxPosition = OpVariable %op_v4f32 Output\n"
   1739 		"%Position = OpVariable %ip_v4f32 Input\n"
   1740 		"%vtxColor = OpVariable %op_v4f32 Output\n"
   1741 		"%color = OpVariable %ip_v4f32 Input\n"
   1742 		"%vertex_id = OpVariable %ip_i32 Input\n"
   1743 		"%instance_id = OpVariable %ip_i32 Input\n"
   1744 
   1745 		"%main = OpFunction %void None %fun\n"
   1746 		"%label = OpLabel\n"
   1747 		"%tmp_position = OpLoad %v4f32 %Position\n"
   1748 		"OpStore %vtxPosition %tmp_position\n"
   1749 		"%tmp_color = OpLoad %v4f32 %color\n"
   1750 		"OpStore %vtxColor %tmp_color\n"
   1751 		"OpReturn\n"
   1752 		"OpFunctionEnd\n"
   1753 
   1754 		"%main2 = OpFunction %void None %fun\n"
   1755 		"%label2 = OpLabel\n"
   1756 		"%tmp_position2 = OpLoad %v4f32 %Position\n"
   1757 		"OpStore %vtxPosition %tmp_position2\n"
   1758 		"%tmp_color2 = OpLoad %v4f32 %color\n"
   1759 		"%tmp_color3 = OpFSub %v4f32 %cval %tmp_color2\n"
   1760 		"%tmp_color4 = OpVectorInsertDynamic %v4f32 %tmp_color3 %c_f32_1 %c_i32_3\n"
   1761 		"OpStore %vtxColor %tmp_color4\n"
   1762 		"OpReturn\n"
   1763 		"OpFunctionEnd\n";
   1764 
   1765 	dst.spirvAsmSources.add("frag") <<
   1766 		// This is a single module that contains 2 fragment shaders.
   1767 		// One that passes color through and the other that inverts the output
   1768 		// color (1.0 - color).
   1769 		"OpCapability Shader\n"
   1770 		"OpMemoryModel Logical GLSL450\n"
   1771 		"OpEntryPoint Fragment %main \"frag1\" %vtxColor %fragColor\n"
   1772 		"OpEntryPoint Fragment %main2 \"frag2\" %vtxColor %fragColor\n"
   1773 		"OpExecutionMode %main OriginUpperLeft\n"
   1774 		"OpExecutionMode %main2 OriginUpperLeft\n"
   1775 
   1776 		"OpName %main \"frag1\"\n"
   1777 		"OpName %main2 \"frag2\"\n"
   1778 		"OpName %fragColor \"fragColor\"\n"
   1779 		"OpName %vtxColor \"vtxColor\"\n"
   1780 		"OpDecorate %fragColor Location 0\n"
   1781 		"OpDecorate %vtxColor Location 1\n"
   1782 		SPIRV_ASSEMBLY_TYPES
   1783 		SPIRV_ASSEMBLY_CONSTANTS
   1784 		SPIRV_ASSEMBLY_ARRAYS
   1785 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
   1786 		"%fragColor = OpVariable %op_v4f32 Output\n"
   1787 		"%vtxColor = OpVariable %ip_v4f32 Input\n"
   1788 
   1789 		"%main = OpFunction %void None %fun\n"
   1790 		"%label_main = OpLabel\n"
   1791 		"%tmp1 = OpLoad %v4f32 %vtxColor\n"
   1792 		"OpStore %fragColor %tmp1\n"
   1793 		"OpReturn\n"
   1794 		"OpFunctionEnd\n"
   1795 
   1796 		"%main2 = OpFunction %void None %fun\n"
   1797 		"%label_main2 = OpLabel\n"
   1798 		"%tmp2 = OpLoad %v4f32 %vtxColor\n"
   1799 		"%tmp3 = OpFSub %v4f32 %cval %tmp2\n"
   1800 		"%tmp4 = OpVectorInsertDynamic %v4f32 %tmp3 %c_f32_1 %c_i32_3\n"
   1801 		"OpStore %fragColor %tmp4\n"
   1802 		"OpReturn\n"
   1803 		"OpFunctionEnd\n";
   1804 
   1805 	dst.spirvAsmSources.add("geom") <<
   1806 		"OpCapability Geometry\n"
   1807 		"OpCapability ClipDistance\n"
   1808 		"OpCapability CullDistance\n"
   1809 		"OpMemoryModel Logical GLSL450\n"
   1810 		"OpEntryPoint Geometry %geom1_main \"geom1\" %out_gl_position %gl_in %out_color %in_color\n"
   1811 		"OpEntryPoint Geometry %geom2_main \"geom2\" %out_gl_position %gl_in %out_color %in_color\n"
   1812 		"OpExecutionMode %geom1_main Triangles\n"
   1813 		"OpExecutionMode %geom2_main Triangles\n"
   1814 		"OpExecutionMode %geom1_main OutputTriangleStrip\n"
   1815 		"OpExecutionMode %geom2_main OutputTriangleStrip\n"
   1816 		"OpExecutionMode %geom1_main OutputVertices 3\n"
   1817 		"OpExecutionMode %geom2_main OutputVertices 3\n"
   1818 		"OpName %geom1_main \"geom1\"\n"
   1819 		"OpName %geom2_main \"geom2\"\n"
   1820 		"OpName %per_vertex_in \"gl_PerVertex\"\n"
   1821 		"OpMemberName %per_vertex_in 0 \"gl_Position\"\n"
   1822 		"OpMemberName %per_vertex_in 1 \"gl_PointSize\"\n"
   1823 		"OpMemberName %per_vertex_in 2 \"gl_ClipDistance\"\n"
   1824 		"OpMemberName %per_vertex_in 3 \"gl_CullDistance\"\n"
   1825 		"OpName %gl_in \"gl_in\"\n"
   1826 		"OpName %out_color \"out_color\"\n"
   1827 		"OpName %in_color \"in_color\"\n"
   1828 		"OpDecorate %out_gl_position BuiltIn Position\n"
   1829 		"OpMemberDecorate %per_vertex_in 0 BuiltIn Position\n"
   1830 		"OpMemberDecorate %per_vertex_in 1 BuiltIn PointSize\n"
   1831 		"OpMemberDecorate %per_vertex_in 2 BuiltIn ClipDistance\n"
   1832 		"OpMemberDecorate %per_vertex_in 3 BuiltIn CullDistance\n"
   1833 		"OpDecorate %per_vertex_in Block\n"
   1834 		"OpDecorate %out_color Location 1\n"
   1835 		"OpDecorate %in_color Location 1\n"
   1836 		SPIRV_ASSEMBLY_TYPES
   1837 		SPIRV_ASSEMBLY_CONSTANTS
   1838 		SPIRV_ASSEMBLY_ARRAYS
   1839 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
   1840 		"%per_vertex_in = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
   1841 		"%a3_per_vertex_in = OpTypeArray %per_vertex_in %c_u32_3\n"
   1842 		"%ip_a3_per_vertex_in = OpTypePointer Input %a3_per_vertex_in\n"
   1843 		"%gl_in = OpVariable %ip_a3_per_vertex_in Input\n"
   1844 		"%out_color = OpVariable %op_v4f32 Output\n"
   1845 		"%in_color = OpVariable %ip_a3v4f32 Input\n"
   1846 		"%out_gl_position = OpVariable %op_v4f32 Output\n"
   1847 
   1848 		"%geom1_main = OpFunction %void None %fun\n"
   1849 		"%geom1_label = OpLabel\n"
   1850 		"%geom1_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
   1851 		"%geom1_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
   1852 		"%geom1_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
   1853 		"%geom1_in_position_0 = OpLoad %v4f32 %geom1_gl_in_0_gl_position\n"
   1854 		"%geom1_in_position_1 = OpLoad %v4f32 %geom1_gl_in_1_gl_position\n"
   1855 		"%geom1_in_position_2 = OpLoad %v4f32 %geom1_gl_in_2_gl_position \n"
   1856 		"%geom1_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
   1857 		"%geom1_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
   1858 		"%geom1_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
   1859 		"%geom1_in_color_0 = OpLoad %v4f32 %geom1_in_color_0_ptr\n"
   1860 		"%geom1_in_color_1 = OpLoad %v4f32 %geom1_in_color_1_ptr\n"
   1861 		"%geom1_in_color_2 = OpLoad %v4f32 %geom1_in_color_2_ptr\n"
   1862 		"OpStore %out_gl_position %geom1_in_position_0\n"
   1863 		"OpStore %out_color %geom1_in_color_0\n"
   1864 		"OpEmitVertex\n"
   1865 		"OpStore %out_gl_position %geom1_in_position_1\n"
   1866 		"OpStore %out_color %geom1_in_color_1\n"
   1867 		"OpEmitVertex\n"
   1868 		"OpStore %out_gl_position %geom1_in_position_2\n"
   1869 		"OpStore %out_color %geom1_in_color_2\n"
   1870 		"OpEmitVertex\n"
   1871 		"OpEndPrimitive\n"
   1872 		"OpReturn\n"
   1873 		"OpFunctionEnd\n"
   1874 
   1875 		"%geom2_main = OpFunction %void None %fun\n"
   1876 		"%geom2_label = OpLabel\n"
   1877 		"%geom2_gl_in_0_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_0 %c_i32_0\n"
   1878 		"%geom2_gl_in_1_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_1 %c_i32_0\n"
   1879 		"%geom2_gl_in_2_gl_position = OpAccessChain %ip_v4f32 %gl_in %c_i32_2 %c_i32_0\n"
   1880 		"%geom2_in_position_0 = OpLoad %v4f32 %geom2_gl_in_0_gl_position\n"
   1881 		"%geom2_in_position_1 = OpLoad %v4f32 %geom2_gl_in_1_gl_position\n"
   1882 		"%geom2_in_position_2 = OpLoad %v4f32 %geom2_gl_in_2_gl_position \n"
   1883 		"%geom2_in_color_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
   1884 		"%geom2_in_color_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
   1885 		"%geom2_in_color_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
   1886 		"%geom2_in_color_0 = OpLoad %v4f32 %geom2_in_color_0_ptr\n"
   1887 		"%geom2_in_color_1 = OpLoad %v4f32 %geom2_in_color_1_ptr\n"
   1888 		"%geom2_in_color_2 = OpLoad %v4f32 %geom2_in_color_2_ptr\n"
   1889 		"%geom2_transformed_in_color_0 = OpFSub %v4f32 %cval %geom2_in_color_0\n"
   1890 		"%geom2_transformed_in_color_1 = OpFSub %v4f32 %cval %geom2_in_color_1\n"
   1891 		"%geom2_transformed_in_color_2 = OpFSub %v4f32 %cval %geom2_in_color_2\n"
   1892 		"%geom2_transformed_in_color_0_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_0 %c_f32_1 %c_i32_3\n"
   1893 		"%geom2_transformed_in_color_1_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_1 %c_f32_1 %c_i32_3\n"
   1894 		"%geom2_transformed_in_color_2_a = OpVectorInsertDynamic %v4f32 %geom2_transformed_in_color_2 %c_f32_1 %c_i32_3\n"
   1895 		"OpStore %out_gl_position %geom2_in_position_0\n"
   1896 		"OpStore %out_color %geom2_transformed_in_color_0_a\n"
   1897 		"OpEmitVertex\n"
   1898 		"OpStore %out_gl_position %geom2_in_position_1\n"
   1899 		"OpStore %out_color %geom2_transformed_in_color_1_a\n"
   1900 		"OpEmitVertex\n"
   1901 		"OpStore %out_gl_position %geom2_in_position_2\n"
   1902 		"OpStore %out_color %geom2_transformed_in_color_2_a\n"
   1903 		"OpEmitVertex\n"
   1904 		"OpEndPrimitive\n"
   1905 		"OpReturn\n"
   1906 		"OpFunctionEnd\n";
   1907 
   1908 	dst.spirvAsmSources.add("tessc") <<
   1909 		"OpCapability Tessellation\n"
   1910 		"OpMemoryModel Logical GLSL450\n"
   1911 		"OpEntryPoint TessellationControl %tessc1_main \"tessc1\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
   1912 		"OpEntryPoint TessellationControl %tessc2_main \"tessc2\" %out_color %gl_InvocationID %in_color %out_position %in_position %gl_TessLevelOuter %gl_TessLevelInner\n"
   1913 		"OpExecutionMode %tessc1_main OutputVertices 3\n"
   1914 		"OpExecutionMode %tessc2_main OutputVertices 3\n"
   1915 		"OpName %tessc1_main \"tessc1\"\n"
   1916 		"OpName %tessc2_main \"tessc2\"\n"
   1917 		"OpName %out_color \"out_color\"\n"
   1918 		"OpName %gl_InvocationID \"gl_InvocationID\"\n"
   1919 		"OpName %in_color \"in_color\"\n"
   1920 		"OpName %out_position \"out_position\"\n"
   1921 		"OpName %in_position \"in_position\"\n"
   1922 		"OpName %gl_TessLevelOuter \"gl_TessLevelOuter\"\n"
   1923 		"OpName %gl_TessLevelInner \"gl_TessLevelInner\"\n"
   1924 		"OpDecorate %out_color Location 1\n"
   1925 		"OpDecorate %gl_InvocationID BuiltIn InvocationId\n"
   1926 		"OpDecorate %in_color Location 1\n"
   1927 		"OpDecorate %out_position Location 2\n"
   1928 		"OpDecorate %in_position Location 2\n"
   1929 		"OpDecorate %gl_TessLevelOuter Patch\n"
   1930 		"OpDecorate %gl_TessLevelOuter BuiltIn TessLevelOuter\n"
   1931 		"OpDecorate %gl_TessLevelInner Patch\n"
   1932 		"OpDecorate %gl_TessLevelInner BuiltIn TessLevelInner\n"
   1933 		SPIRV_ASSEMBLY_TYPES
   1934 		SPIRV_ASSEMBLY_CONSTANTS
   1935 		SPIRV_ASSEMBLY_ARRAYS
   1936 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
   1937 		"%out_color = OpVariable %op_a3v4f32 Output\n"
   1938 		"%gl_InvocationID = OpVariable %ip_i32 Input\n"
   1939 		"%in_color = OpVariable %ip_a32v4f32 Input\n"
   1940 		"%out_position = OpVariable %op_a3v4f32 Output\n"
   1941 		"%in_position = OpVariable %ip_a32v4f32 Input\n"
   1942 		"%gl_TessLevelOuter = OpVariable %op_a4f32 Output\n"
   1943 		"%gl_TessLevelInner = OpVariable %op_a2f32 Output\n"
   1944 
   1945 		"%tessc1_main = OpFunction %void None %fun\n"
   1946 		"%tessc1_label = OpLabel\n"
   1947 		"%tessc1_invocation_id = OpLoad %i32 %gl_InvocationID\n"
   1948 		"%tessc1_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc1_invocation_id\n"
   1949 		"%tessc1_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc1_invocation_id\n"
   1950 		"%tessc1_in_color_val = OpLoad %v4f32 %tessc1_in_color_ptr\n"
   1951 		"%tessc1_in_position_val = OpLoad %v4f32 %tessc1_in_position_ptr\n"
   1952 		"%tessc1_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc1_invocation_id\n"
   1953 		"%tessc1_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc1_invocation_id\n"
   1954 		"OpStore %tessc1_out_color_ptr %tessc1_in_color_val\n"
   1955 		"OpStore %tessc1_out_position_ptr %tessc1_in_position_val\n"
   1956 		"%tessc1_is_first_invocation = OpIEqual %bool %tessc1_invocation_id %c_i32_0\n"
   1957 		"OpSelectionMerge %tessc1_merge_label None\n"
   1958 		"OpBranchConditional %tessc1_is_first_invocation %tessc1_first_invocation %tessc1_merge_label\n"
   1959 		"%tessc1_first_invocation = OpLabel\n"
   1960 		"%tessc1_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
   1961 		"%tessc1_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
   1962 		"%tessc1_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
   1963 		"%tessc1_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n"
   1964 		"OpStore %tessc1_tess_outer_0 %c_f32_1\n"
   1965 		"OpStore %tessc1_tess_outer_1 %c_f32_1\n"
   1966 		"OpStore %tessc1_tess_outer_2 %c_f32_1\n"
   1967 		"OpStore %tessc1_tess_inner %c_f32_1\n"
   1968 		"OpBranch %tessc1_merge_label\n"
   1969 		"%tessc1_merge_label = OpLabel\n"
   1970 		"OpReturn\n"
   1971 		"OpFunctionEnd\n"
   1972 
   1973 		"%tessc2_main = OpFunction %void None %fun\n"
   1974 		"%tessc2_label = OpLabel\n"
   1975 		"%tessc2_invocation_id = OpLoad %i32 %gl_InvocationID\n"
   1976 		"%tessc2_in_color_ptr = OpAccessChain %ip_v4f32 %in_color %tessc2_invocation_id\n"
   1977 		"%tessc2_in_position_ptr = OpAccessChain %ip_v4f32 %in_position %tessc2_invocation_id\n"
   1978 		"%tessc2_in_color_val = OpLoad %v4f32 %tessc2_in_color_ptr\n"
   1979 		"%tessc2_in_position_val = OpLoad %v4f32 %tessc2_in_position_ptr\n"
   1980 		"%tessc2_out_color_ptr = OpAccessChain %op_v4f32 %out_color %tessc2_invocation_id\n"
   1981 		"%tessc2_out_position_ptr = OpAccessChain %op_v4f32 %out_position %tessc2_invocation_id\n"
   1982 		"%tessc2_transformed_color = OpFSub %v4f32 %cval %tessc2_in_color_val\n"
   1983 		"%tessc2_transformed_color_a = OpVectorInsertDynamic %v4f32 %tessc2_transformed_color %c_f32_1 %c_i32_3\n"
   1984 		"OpStore %tessc2_out_color_ptr %tessc2_transformed_color_a\n"
   1985 		"OpStore %tessc2_out_position_ptr %tessc2_in_position_val\n"
   1986 		"%tessc2_is_first_invocation = OpIEqual %bool %tessc2_invocation_id %c_i32_0\n"
   1987 		"OpSelectionMerge %tessc2_merge_label None\n"
   1988 		"OpBranchConditional %tessc2_is_first_invocation %tessc2_first_invocation %tessc2_merge_label\n"
   1989 		"%tessc2_first_invocation = OpLabel\n"
   1990 		"%tessc2_tess_outer_0 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_0\n"
   1991 		"%tessc2_tess_outer_1 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_1\n"
   1992 		"%tessc2_tess_outer_2 = OpAccessChain %op_f32 %gl_TessLevelOuter %c_i32_2\n"
   1993 		"%tessc2_tess_inner = OpAccessChain %op_f32 %gl_TessLevelInner %c_i32_0\n"
   1994 		"OpStore %tessc2_tess_outer_0 %c_f32_1\n"
   1995 		"OpStore %tessc2_tess_outer_1 %c_f32_1\n"
   1996 		"OpStore %tessc2_tess_outer_2 %c_f32_1\n"
   1997 		"OpStore %tessc2_tess_inner %c_f32_1\n"
   1998 		"OpBranch %tessc2_merge_label\n"
   1999 		"%tessc2_merge_label = OpLabel\n"
   2000 		"OpReturn\n"
   2001 		"OpFunctionEnd\n";
   2002 
   2003 	dst.spirvAsmSources.add("tesse") <<
   2004 		"OpCapability Tessellation\n"
   2005 		"OpCapability ClipDistance\n"
   2006 		"OpCapability CullDistance\n"
   2007 		"OpMemoryModel Logical GLSL450\n"
   2008 		"OpEntryPoint TessellationEvaluation %tesse1_main \"tesse1\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
   2009 		"OpEntryPoint TessellationEvaluation %tesse2_main \"tesse2\" %stream %gl_tessCoord %in_position %out_color %in_color \n"
   2010 		"OpExecutionMode %tesse1_main Triangles\n"
   2011 		"OpExecutionMode %tesse1_main SpacingEqual\n"
   2012 		"OpExecutionMode %tesse1_main VertexOrderCcw\n"
   2013 		"OpExecutionMode %tesse2_main Triangles\n"
   2014 		"OpExecutionMode %tesse2_main SpacingEqual\n"
   2015 		"OpExecutionMode %tesse2_main VertexOrderCcw\n"
   2016 		"OpName %tesse1_main \"tesse1\"\n"
   2017 		"OpName %tesse2_main \"tesse2\"\n"
   2018 		"OpName %per_vertex_out \"gl_PerVertex\"\n"
   2019 		"OpMemberName %per_vertex_out 0 \"gl_Position\"\n"
   2020 		"OpMemberName %per_vertex_out 1 \"gl_PointSize\"\n"
   2021 		"OpMemberName %per_vertex_out 2 \"gl_ClipDistance\"\n"
   2022 		"OpMemberName %per_vertex_out 3 \"gl_CullDistance\"\n"
   2023 		"OpName %stream \"\"\n"
   2024 		"OpName %gl_tessCoord \"gl_TessCoord\"\n"
   2025 		"OpName %in_position \"in_position\"\n"
   2026 		"OpName %out_color \"out_color\"\n"
   2027 		"OpName %in_color \"in_color\"\n"
   2028 		"OpMemberDecorate %per_vertex_out 0 BuiltIn Position\n"
   2029 		"OpMemberDecorate %per_vertex_out 1 BuiltIn PointSize\n"
   2030 		"OpMemberDecorate %per_vertex_out 2 BuiltIn ClipDistance\n"
   2031 		"OpMemberDecorate %per_vertex_out 3 BuiltIn CullDistance\n"
   2032 		"OpDecorate %per_vertex_out Block\n"
   2033 		"OpDecorate %gl_tessCoord BuiltIn TessCoord\n"
   2034 		"OpDecorate %in_position Location 2\n"
   2035 		"OpDecorate %out_color Location 1\n"
   2036 		"OpDecorate %in_color Location 1\n"
   2037 		SPIRV_ASSEMBLY_TYPES
   2038 		SPIRV_ASSEMBLY_CONSTANTS
   2039 		SPIRV_ASSEMBLY_ARRAYS
   2040 		"%cval = OpConstantComposite %v4f32 %c_f32_1 %c_f32_1 %c_f32_1 %c_f32_0\n"
   2041 		"%per_vertex_out = OpTypeStruct %v4f32 %f32 %a1f32 %a1f32\n"
   2042 		"%op_per_vertex_out = OpTypePointer Output %per_vertex_out\n"
   2043 		"%stream = OpVariable %op_per_vertex_out Output\n"
   2044 		"%gl_tessCoord = OpVariable %ip_v3f32 Input\n"
   2045 		"%in_position = OpVariable %ip_a32v4f32 Input\n"
   2046 		"%out_color = OpVariable %op_v4f32 Output\n"
   2047 		"%in_color = OpVariable %ip_a32v4f32 Input\n"
   2048 
   2049 		"%tesse1_main = OpFunction %void None %fun\n"
   2050 		"%tesse1_label = OpLabel\n"
   2051 		"%tesse1_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
   2052 		"%tesse1_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
   2053 		"%tesse1_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
   2054 		"%tesse1_tc_0 = OpLoad %f32 %tesse1_tc_0_ptr\n"
   2055 		"%tesse1_tc_1 = OpLoad %f32 %tesse1_tc_1_ptr\n"
   2056 		"%tesse1_tc_2 = OpLoad %f32 %tesse1_tc_2_ptr\n"
   2057 		"%tesse1_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
   2058 		"%tesse1_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
   2059 		"%tesse1_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
   2060 		"%tesse1_in_pos_0 = OpLoad %v4f32 %tesse1_in_pos_0_ptr\n"
   2061 		"%tesse1_in_pos_1 = OpLoad %v4f32 %tesse1_in_pos_1_ptr\n"
   2062 		"%tesse1_in_pos_2 = OpLoad %v4f32 %tesse1_in_pos_2_ptr\n"
   2063 		"%tesse1_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_0 %tesse1_tc_0\n"
   2064 		"%tesse1_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_1 %tesse1_tc_1\n"
   2065 		"%tesse1_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_pos_2 %tesse1_tc_2\n"
   2066 		"%tesse1_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
   2067 		"%tesse1_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse1_in_pos_0_weighted %tesse1_in_pos_1_weighted\n"
   2068 		"%tesse1_computed_out = OpFAdd %v4f32 %tesse1_in_pos_0_plus_pos_1 %tesse1_in_pos_2_weighted\n"
   2069 		"OpStore %tesse1_out_pos_ptr %tesse1_computed_out\n"
   2070 		"%tesse1_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
   2071 		"%tesse1_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
   2072 		"%tesse1_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
   2073 		"%tesse1_in_clr_0 = OpLoad %v4f32 %tesse1_in_clr_0_ptr\n"
   2074 		"%tesse1_in_clr_1 = OpLoad %v4f32 %tesse1_in_clr_1_ptr\n"
   2075 		"%tesse1_in_clr_2 = OpLoad %v4f32 %tesse1_in_clr_2_ptr\n"
   2076 		"%tesse1_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_0 %tesse1_tc_0\n"
   2077 		"%tesse1_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_1 %tesse1_tc_1\n"
   2078 		"%tesse1_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse1_in_clr_2 %tesse1_tc_2\n"
   2079 		"%tesse1_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse1_in_clr_0_weighted %tesse1_in_clr_1_weighted\n"
   2080 		"%tesse1_computed_clr = OpFAdd %v4f32 %tesse1_in_clr_0_plus_col_1 %tesse1_in_clr_2_weighted\n"
   2081 		"OpStore %out_color %tesse1_computed_clr\n"
   2082 		"OpReturn\n"
   2083 		"OpFunctionEnd\n"
   2084 
   2085 		"%tesse2_main = OpFunction %void None %fun\n"
   2086 		"%tesse2_label = OpLabel\n"
   2087 		"%tesse2_tc_0_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_0\n"
   2088 		"%tesse2_tc_1_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_1\n"
   2089 		"%tesse2_tc_2_ptr = OpAccessChain %ip_f32 %gl_tessCoord %c_u32_2\n"
   2090 		"%tesse2_tc_0 = OpLoad %f32 %tesse2_tc_0_ptr\n"
   2091 		"%tesse2_tc_1 = OpLoad %f32 %tesse2_tc_1_ptr\n"
   2092 		"%tesse2_tc_2 = OpLoad %f32 %tesse2_tc_2_ptr\n"
   2093 		"%tesse2_in_pos_0_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_0\n"
   2094 		"%tesse2_in_pos_1_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_1\n"
   2095 		"%tesse2_in_pos_2_ptr = OpAccessChain %ip_v4f32 %in_position %c_i32_2\n"
   2096 		"%tesse2_in_pos_0 = OpLoad %v4f32 %tesse2_in_pos_0_ptr\n"
   2097 		"%tesse2_in_pos_1 = OpLoad %v4f32 %tesse2_in_pos_1_ptr\n"
   2098 		"%tesse2_in_pos_2 = OpLoad %v4f32 %tesse2_in_pos_2_ptr\n"
   2099 		"%tesse2_in_pos_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_0 %tesse2_tc_0\n"
   2100 		"%tesse2_in_pos_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_1 %tesse2_tc_1\n"
   2101 		"%tesse2_in_pos_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_pos_2 %tesse2_tc_2\n"
   2102 		"%tesse2_out_pos_ptr = OpAccessChain %op_v4f32 %stream %c_i32_0\n"
   2103 		"%tesse2_in_pos_0_plus_pos_1 = OpFAdd %v4f32 %tesse2_in_pos_0_weighted %tesse2_in_pos_1_weighted\n"
   2104 		"%tesse2_computed_out = OpFAdd %v4f32 %tesse2_in_pos_0_plus_pos_1 %tesse2_in_pos_2_weighted\n"
   2105 		"OpStore %tesse2_out_pos_ptr %tesse2_computed_out\n"
   2106 		"%tesse2_in_clr_0_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_0\n"
   2107 		"%tesse2_in_clr_1_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_1\n"
   2108 		"%tesse2_in_clr_2_ptr = OpAccessChain %ip_v4f32 %in_color %c_i32_2\n"
   2109 		"%tesse2_in_clr_0 = OpLoad %v4f32 %tesse2_in_clr_0_ptr\n"
   2110 		"%tesse2_in_clr_1 = OpLoad %v4f32 %tesse2_in_clr_1_ptr\n"
   2111 		"%tesse2_in_clr_2 = OpLoad %v4f32 %tesse2_in_clr_2_ptr\n"
   2112 		"%tesse2_in_clr_0_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_0 %tesse2_tc_0\n"
   2113 		"%tesse2_in_clr_1_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_1 %tesse2_tc_1\n"
   2114 		"%tesse2_in_clr_2_weighted = OpVectorTimesScalar %v4f32 %tesse2_in_clr_2 %tesse2_tc_2\n"
   2115 		"%tesse2_in_clr_0_plus_col_1 = OpFAdd %v4f32 %tesse2_in_clr_0_weighted %tesse2_in_clr_1_weighted\n"
   2116 		"%tesse2_computed_clr = OpFAdd %v4f32 %tesse2_in_clr_0_plus_col_1 %tesse2_in_clr_2_weighted\n"
   2117 		"%tesse2_clr_transformed = OpFSub %v4f32 %cval %tesse2_computed_clr\n"
   2118 		"%tesse2_clr_transformed_a = OpVectorInsertDynamic %v4f32 %tesse2_clr_transformed %c_f32_1 %c_i32_3\n"
   2119 		"OpStore %out_color %tesse2_clr_transformed_a\n"
   2120 		"OpReturn\n"
   2121 		"OpFunctionEnd\n";
   2122 }
   2123 
   2124 bool compare16BitFloat (float original, deUint16 returned, RoundingModeFlags flags, tcu::TestLog& log)
   2125 {
   2126 	// We only support RTE, RTZ, or both.
   2127 	DE_ASSERT(static_cast<int>(flags) > 0 && static_cast<int>(flags) < 4);
   2128 
   2129 	const Float32	originalFloat	(original);
   2130 	const Float16	returnedFloat	(returned);
   2131 
   2132 	// Zero are turned into zero under both RTE and RTZ.
   2133 	if (originalFloat.isZero())
   2134 	{
   2135 		if (returnedFloat.isZero())
   2136 			return true;
   2137 
   2138 		log << TestLog::Message << "Error: expected zero but returned " << returned << TestLog::EndMessage;
   2139 		return false;
   2140 	}
   2141 
   2142 	// Any denormalized value input into a shader may be flushed to 0.
   2143 	if (originalFloat.isDenorm() && returnedFloat.isZero())
   2144 		return true;
   2145 
   2146 	// Inf are always turned into Inf with the same sign, too.
   2147 	if (originalFloat.isInf())
   2148 	{
   2149 		if (returnedFloat.isInf() && originalFloat.signBit() == returnedFloat.signBit())
   2150 			return true;
   2151 
   2152 		log << TestLog::Message << "Error: expected Inf but returned " << returned << TestLog::EndMessage;
   2153 		return false;
   2154 	}
   2155 
   2156 	// NaN are always turned into NaN, too.
   2157 	if (originalFloat.isNaN())
   2158 	{
   2159 		if (returnedFloat.isNaN())
   2160 			return true;
   2161 
   2162 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
   2163 		return false;
   2164 	}
   2165 
   2166 	// Check all rounding modes
   2167 	for (int bitNdx = 0; bitNdx < 2; ++bitNdx)
   2168 	{
   2169 		if ((flags & (1u << bitNdx)) == 0)
   2170 			continue;	// This rounding mode is not selected.
   2171 
   2172 		const Float16	expectedFloat	(deFloat32To16Round(original, deRoundingMode(bitNdx)));
   2173 
   2174 		// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
   2175 		if (expectedFloat.isDenorm() && returnedFloat.isZero())
   2176 			return true;
   2177 
   2178 		// If not matched in the above cases, they should have the same bit pattern.
   2179 		if (expectedFloat.bits() == returnedFloat.bits())
   2180 			return true;
   2181 	}
   2182 
   2183 	log << TestLog::Message << "Error: found unmatched 32-bit and 16-bit floats: " << originalFloat.bits() << " vs " << returned << TestLog::EndMessage;
   2184 	return false;
   2185 }
   2186 
   2187 bool compare32BitFloat (float expected, float returned, tcu::TestLog& log)
   2188 {
   2189 	const Float32	expectedFloat	(expected);
   2190 	const Float32	returnedFloat	(returned);
   2191 
   2192 	// Any denormalized value potentially generated by any instruction in a shader may be flushed to 0.
   2193 	if (expectedFloat.isDenorm() && returnedFloat.isZero())
   2194 		return true;
   2195 
   2196 	{
   2197 		const Float16	originalFloat	(deFloat32To16(expected));
   2198 
   2199 		// Any denormalized value input into a shader may be flushed to 0.
   2200 		if (originalFloat.isDenorm() && returnedFloat.isZero())
   2201 			return true;
   2202 	}
   2203 
   2204 	if (expectedFloat.isNaN())
   2205 	{
   2206 		if (returnedFloat.isNaN())
   2207 			return true;
   2208 
   2209 		log << TestLog::Message << "Error: expected NaN but returned " << returned << TestLog::EndMessage;
   2210 		return false;
   2211 	}
   2212 
   2213 	if (returned == expected)
   2214 		return true;
   2215 
   2216 	log << TestLog::Message << "Error: found unmatched 32-bit float: expected " << expectedFloat.bits() << " vs. returned " << returnedFloat.bits() << TestLog::EndMessage;
   2217 	return false;
   2218 }
   2219 
   2220 Move<VkBuffer> createBufferForResource(const DeviceInterface& vk, const VkDevice vkDevice, const Resource& resource, deUint32 queueFamilyIndex)
   2221 {
   2222 	vector<deUint8>	resourceBytes;
   2223 	resource.second->getBytes(resourceBytes);
   2224 
   2225 	const VkBufferCreateInfo	resourceBufferParams	=
   2226 	{
   2227 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,								// sType
   2228 		DE_NULL,															// pNext
   2229 		(VkBufferCreateFlags)0,												// flags
   2230 		(VkDeviceSize)resourceBytes.size(),									// size
   2231 		(VkBufferUsageFlags)getMatchingBufferUsageFlagBit(resource.first),	// usage
   2232 		VK_SHARING_MODE_EXCLUSIVE,											// sharingMode
   2233 		1u,																	// queueFamilyCount
   2234 		&queueFamilyIndex,													// pQueueFamilyIndices
   2235 	};
   2236 
   2237 	return createBuffer(vk, vkDevice, &resourceBufferParams);
   2238 }
   2239 
   2240 TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance)
   2241 {
   2242 	if (getMinRequiredVulkanVersion(instance.resources.spirvVersion) > context.getUsedApiVersion())
   2243 	{
   2244 		TCU_THROW(NotSupportedError, string("Vulkan higher than or equal to " + getVulkanName(getMinRequiredVulkanVersion(instance.resources.spirvVersion)) + " is required for this test to run").c_str());
   2245 	}
   2246 
   2247 	const InstanceInterface&					vkInstance				= context.getInstanceInterface();
   2248 	const VkPhysicalDevice						vkPhysicalDevice		= context.getPhysicalDevice();
   2249 	const deUint32								queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
   2250 	// Create a dedicated logic device with required extensions enabled for this test case.
   2251 	const tcu::UVec2							renderSize				(256, 256);
   2252 	const int									testSpecificSeed		= 31354125;
   2253 	const int									seed					= context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed;
   2254 	bool										supportsGeometry		= false;
   2255 	bool										supportsTessellation	= false;
   2256 	bool										hasTessellation         = false;
   2257 	const bool									hasPushConstants		= !instance.pushConstants.empty();
   2258 	const deUint32								numResources			= static_cast<deUint32>(instance.resources.inputs.size() + instance.resources.outputs.size());
   2259 	const bool									needInterface			= !instance.interfaces.empty();
   2260 	const VkPhysicalDeviceFeatures&				features				= context.getDeviceFeatures();
   2261 
   2262 
   2263 	supportsGeometry		= features.geometryShader == VK_TRUE;
   2264 	supportsTessellation	= features.tessellationShader == VK_TRUE;
   2265 	hasTessellation			= (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) ||
   2266 								(instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
   2267 
   2268 	if (hasTessellation && !supportsTessellation)
   2269 	{
   2270 		TCU_THROW(NotSupportedError, "Tessellation not supported");
   2271 	}
   2272 
   2273 	if ((instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT) &&
   2274 		!supportsGeometry)
   2275 	{
   2276 		TCU_THROW(NotSupportedError, "Geometry not supported");
   2277 	}
   2278 
   2279 	{
   2280 		for (deUint32 featureNdx = 0; featureNdx < instance.requiredDeviceFeatures.size(); ++featureNdx)
   2281 		{
   2282 			const string& feature = instance.requiredDeviceFeatures[featureNdx];
   2283 
   2284 			if (feature == "shaderInt16")
   2285 			{
   2286 				if (features.shaderInt16 != VK_TRUE)
   2287 					TCU_THROW(NotSupportedError, "Device feature not supported: shaderInt16");
   2288 			}
   2289 			else if (feature == "shaderInt64")
   2290 			{
   2291 				if (features.shaderInt64 != VK_TRUE)
   2292 					TCU_THROW(NotSupportedError, "Device feature not supported: shaderInt64");
   2293 			}
   2294 			else
   2295 			{
   2296 				TCU_THROW(InternalError, (std::string("Unimplemented physical device feature: ") + feature).c_str());
   2297 			}
   2298 		}
   2299 	}
   2300 
   2301 	// 16bit storage features
   2302 	{
   2303 		if (!is16BitStorageFeaturesSupported(context.getUsedApiVersion(), vkInstance, vkPhysicalDevice, context.getInstanceExtensions(), instance.requestedFeatures.ext16BitStorage))
   2304 			TCU_THROW(NotSupportedError, "Requested 16bit storage features not supported");
   2305 	}
   2306 
   2307 	// Variable Pointers features
   2308 	{
   2309 		if (!isVariablePointersFeaturesSupported(context.getUsedApiVersion(), vkInstance, vkPhysicalDevice, context.getInstanceExtensions(), instance.requestedFeatures.extVariablePointers))
   2310 			TCU_THROW(NotSupportedError, "Requested Variable Pointer features not supported");
   2311 
   2312 		if (instance.requestedFeatures.extVariablePointers)
   2313 		{
   2314 			// The device doesn't have the vertexPipelineStoresAndAtomics feature, but the test requires the feature for
   2315 			// vertex, tesselation, and geometry stages.
   2316 			if (features.vertexPipelineStoresAndAtomics == DE_FALSE &&
   2317 				instance.requestedFeatures.coreFeatures.vertexPipelineStoresAndAtomics == DE_TRUE &&
   2318 			    (instance.customizedStages & vk::VK_SHADER_STAGE_VERTEX_BIT ||
   2319 				 instance.customizedStages & vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT ||
   2320 				 instance.customizedStages & vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
   2321 				 instance.customizedStages & vk::VK_SHADER_STAGE_GEOMETRY_BIT))
   2322 				TCU_THROW(NotSupportedError, "This VK_KHR_variable_pointers extension test requires vertexPipelineStoresAndAtomics device feature.");
   2323 
   2324 			// The device doesn't have the fragmentStoresAndAtomics feature, but the test requires this feature for the fragment stage.
   2325 			if (features.fragmentStoresAndAtomics == DE_FALSE &&
   2326 			    instance.requestedFeatures.coreFeatures.fragmentStoresAndAtomics == DE_TRUE &&
   2327 				instance.customizedStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT)
   2328 				TCU_THROW(NotSupportedError, "This VK_KHR_variable_pointers extension test requires fragmentStoresAndAtomics device feature.");
   2329 		}
   2330 	}
   2331 
   2332 	// defer device and other resource creation until after feature checks
   2333 	const Unique<VkDevice>						vkDevice				(createDeviceWithExtensions(context, queueFamilyIndex, context.getDeviceExtensions(), instance.requiredDeviceExtensions));
   2334 	const DeviceDriver							vk						(vkInstance, *vkDevice);
   2335 	const VkQueue								queue					= getDeviceQueue(vk, *vkDevice, queueFamilyIndex, 0);
   2336 	const de::UniquePtr<Allocator>				allocatorUptr			(createAllocator(vkInstance, vkPhysicalDevice, vk, *vkDevice));
   2337 	Allocator&									allocator				= *allocatorUptr;
   2338 	vector<ModuleHandleSp>						modules;
   2339 	map<VkShaderStageFlagBits, VkShaderModule>	moduleByStage;
   2340 
   2341 
   2342 	de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4);
   2343 	de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4);
   2344 	const Vec4								vertexData[]			=
   2345 	{
   2346 		// Upper left corner:
   2347 		Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
   2348 		Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
   2349 		Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(),
   2350 
   2351 		// Upper right corner:
   2352 		Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
   2353 		Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
   2354 		Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(),
   2355 
   2356 		// Lower left corner:
   2357 		Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
   2358 		Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
   2359 		Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(),
   2360 
   2361 		// Lower right corner:
   2362 		Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(),
   2363 		Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(),
   2364 		Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec()
   2365 	};
   2366 	const size_t							singleVertexDataSize	= 2 * sizeof(Vec4);
   2367 	const size_t							vertexCount				= sizeof(vertexData) / singleVertexDataSize;
   2368 
   2369 	Move<VkBuffer>							vertexInputBuffer		;
   2370 	de::MovePtr<Allocation>					vertexInputMemory		;
   2371 	Move<VkBuffer>							fragOutputBuffer		;
   2372 	de::MovePtr<Allocation>					fragOutputMemory		;
   2373 	Move<VkImage>							fragOutputImage			;
   2374 	de::MovePtr<Allocation>					fragOutputImageMemory	;
   2375 	Move<VkImageView>						fragOutputImageView		;
   2376 
   2377 	const VkBufferCreateInfo				vertexBufferParams		=
   2378 	{
   2379 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	//	VkStructureType		sType;
   2380 		DE_NULL,								//	const void*			pNext;
   2381 		0u,										//	VkBufferCreateFlags	flags;
   2382 		(VkDeviceSize)sizeof(vertexData),		//	VkDeviceSize		size;
   2383 		VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,		//	VkBufferUsageFlags	usage;
   2384 		VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode		sharingMode;
   2385 		1u,										//	deUint32			queueFamilyCount;
   2386 		&queueFamilyIndex,						//	const deUint32*		pQueueFamilyIndices;
   2387 	};
   2388 	const Unique<VkBuffer>					vertexBuffer			(createBuffer(vk, *vkDevice, &vertexBufferParams));
   2389 	const UniquePtr<Allocation>				vertexBufferMemory		(allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *vertexBuffer), MemoryRequirement::HostVisible));
   2390 
   2391 	VK_CHECK(vk.bindBufferMemory(*vkDevice, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
   2392 
   2393 	const VkDeviceSize						imageSizeBytes			= (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y());
   2394 	const VkBufferCreateInfo				readImageBufferParams	=
   2395 	{
   2396 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
   2397 		DE_NULL,									//	const void*			pNext;
   2398 		0u,											//	VkBufferCreateFlags	flags;
   2399 		imageSizeBytes,								//	VkDeviceSize		size;
   2400 		VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//	VkBufferUsageFlags	usage;
   2401 		VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
   2402 		1u,											//	deUint32			queueFamilyCount;
   2403 		&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
   2404 	};
   2405 	const Unique<VkBuffer>					readImageBuffer			(createBuffer(vk, *vkDevice, &readImageBufferParams));
   2406 	const UniquePtr<Allocation>				readImageBufferMemory	(allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *readImageBuffer), MemoryRequirement::HostVisible));
   2407 
   2408 	VK_CHECK(vk.bindBufferMemory(*vkDevice, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
   2409 
   2410 	VkImageCreateInfo						imageParams				=
   2411 	{
   2412 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									//	VkStructureType		sType;
   2413 		DE_NULL,																//	const void*			pNext;
   2414 		0u,																		//	VkImageCreateFlags	flags;
   2415 		VK_IMAGE_TYPE_2D,														//	VkImageType			imageType;
   2416 		VK_FORMAT_R8G8B8A8_UNORM,												//	VkFormat			format;
   2417 		{ renderSize.x(), renderSize.y(), 1 },									//	VkExtent3D			extent;
   2418 		1u,																		//	deUint32			mipLevels;
   2419 		1u,																		//	deUint32			arraySize;
   2420 		VK_SAMPLE_COUNT_1_BIT,													//	deUint32			samples;
   2421 		VK_IMAGE_TILING_OPTIMAL,												//	VkImageTiling		tiling;
   2422 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT,	//	VkImageUsageFlags	usage;
   2423 		VK_SHARING_MODE_EXCLUSIVE,												//	VkSharingMode		sharingMode;
   2424 		1u,																		//	deUint32			queueFamilyCount;
   2425 		&queueFamilyIndex,														//	const deUint32*		pQueueFamilyIndices;
   2426 		VK_IMAGE_LAYOUT_UNDEFINED,												//	VkImageLayout		initialLayout;
   2427 	};
   2428 
   2429 	const Unique<VkImage>					image					(createImage(vk, *vkDevice, &imageParams));
   2430 	const UniquePtr<Allocation>				imageMemory				(allocator.allocate(getImageMemoryRequirements(vk, *vkDevice, *image), MemoryRequirement::Any));
   2431 
   2432 	VK_CHECK(vk.bindImageMemory(*vkDevice, *image, imageMemory->getMemory(), imageMemory->getOffset()));
   2433 
   2434 	if (needInterface)
   2435 	{
   2436 		// The pipeline renders four triangles, each with three vertexes.
   2437 		// Test instantialization only provides four data points, each
   2438 		// for one triangle. So we need allocate space of three times of
   2439 		// input buffer's size.
   2440 		vector<deUint8>							inputBufferBytes;
   2441 		instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
   2442 
   2443 		const deUint32							inputNumBytes			= deUint32(inputBufferBytes.size() * 3);
   2444 		// Create an additional buffer and backing memory for one input variable.
   2445 		const VkBufferCreateInfo				vertexInputParams		=
   2446 		{
   2447 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
   2448 			DE_NULL,									//	const void*			pNext;
   2449 			0u,											//	VkBufferCreateFlags	flags;
   2450 			inputNumBytes,								//	VkDeviceSize		size;
   2451 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,			//	VkBufferUsageFlags	usage;
   2452 			VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
   2453 			1u,											//	deUint32			queueFamilyCount;
   2454 			&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
   2455 		};
   2456 
   2457 		vertexInputBuffer = createBuffer(vk, *vkDevice, &vertexInputParams);
   2458 		vertexInputMemory = allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *vertexInputBuffer), MemoryRequirement::HostVisible);
   2459 		VK_CHECK(vk.bindBufferMemory(*vkDevice, *vertexInputBuffer, vertexInputMemory->getMemory(), vertexInputMemory->getOffset()));
   2460 
   2461 		// Create an additional buffer and backing memory for an output variable.
   2462 		const VkDeviceSize						fragOutputImgSize		= (VkDeviceSize)(instance.interfaces.getOutputType().getNumBytes() * renderSize.x() * renderSize.y());
   2463 		const VkBufferCreateInfo				fragOutputParams		=
   2464 		{
   2465 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		//	VkStructureType		sType;
   2466 			DE_NULL,									//	const void*			pNext;
   2467 			0u,											//	VkBufferCreateFlags	flags;
   2468 			fragOutputImgSize,							//	VkDeviceSize		size;
   2469 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			//	VkBufferUsageFlags	usage;
   2470 			VK_SHARING_MODE_EXCLUSIVE,					//	VkSharingMode		sharingMode;
   2471 			1u,											//	deUint32			queueFamilyCount;
   2472 			&queueFamilyIndex,							//	const deUint32*		pQueueFamilyIndices;
   2473 		};
   2474 		fragOutputBuffer = createBuffer(vk, *vkDevice, &fragOutputParams);
   2475 		fragOutputMemory = allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *fragOutputBuffer), MemoryRequirement::HostVisible);
   2476 		VK_CHECK(vk.bindBufferMemory(*vkDevice, *fragOutputBuffer, fragOutputMemory->getMemory(), fragOutputMemory->getOffset()));
   2477 
   2478 		// Create an additional image and backing memory for attachment.
   2479 		// Reuse the previous imageParams since we only need to change the image format.
   2480 		imageParams.format		= instance.interfaces.getOutputType().getVkFormat();
   2481 
   2482 		// Check the usage bits on the given image format are supported.
   2483 		requireFormatUsageSupport(vkInstance, vkPhysicalDevice, imageParams.format, imageParams.tiling, imageParams.usage);
   2484 
   2485 		fragOutputImage			= createImage(vk, *vkDevice, &imageParams);
   2486 		fragOutputImageMemory	= allocator.allocate(getImageMemoryRequirements(vk, *vkDevice, *fragOutputImage), MemoryRequirement::Any);
   2487 
   2488 		VK_CHECK(vk.bindImageMemory(*vkDevice, *fragOutputImage, fragOutputImageMemory->getMemory(), fragOutputImageMemory->getOffset()));
   2489 	}
   2490 
   2491 	vector<VkAttachmentDescription>			colorAttDescs			;
   2492 	vector<VkAttachmentReference>			colorAttRefs			;
   2493 	{
   2494 		const VkAttachmentDescription		attDesc					=
   2495 		{
   2496 			0u,												//	VkAttachmentDescriptionFlags	flags;
   2497 			VK_FORMAT_R8G8B8A8_UNORM,						//	VkFormat						format;
   2498 			VK_SAMPLE_COUNT_1_BIT,							//	deUint32						samples;
   2499 			VK_ATTACHMENT_LOAD_OP_CLEAR,					//	VkAttachmentLoadOp				loadOp;
   2500 			VK_ATTACHMENT_STORE_OP_STORE,					//	VkAttachmentStoreOp				storeOp;
   2501 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,				//	VkAttachmentLoadOp				stencilLoadOp;
   2502 			VK_ATTACHMENT_STORE_OP_DONT_CARE,				//	VkAttachmentStoreOp				stencilStoreOp;
   2503 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout					initialLayout;
   2504 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout					finalLayout;
   2505 		};
   2506 		colorAttDescs.push_back(attDesc);
   2507 
   2508 		const VkAttachmentReference			attRef					=
   2509 		{
   2510 			0u,												//	deUint32		attachment;
   2511 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout	layout;
   2512 		};
   2513 		colorAttRefs.push_back(attRef);
   2514 	}
   2515 
   2516 	if (needInterface)
   2517 	{
   2518 		const VkAttachmentDescription		attDesc					=
   2519 		{
   2520 			0u,													//	VkAttachmentDescriptionFlags	flags;
   2521 			instance.interfaces.getOutputType().getVkFormat(),	//	VkFormat						format;
   2522 			VK_SAMPLE_COUNT_1_BIT,								//	deUint32						samples;
   2523 			VK_ATTACHMENT_LOAD_OP_CLEAR,						//	VkAttachmentLoadOp				loadOp;
   2524 			VK_ATTACHMENT_STORE_OP_STORE,						//	VkAttachmentStoreOp				storeOp;
   2525 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,					//	VkAttachmentLoadOp				stencilLoadOp;
   2526 			VK_ATTACHMENT_STORE_OP_DONT_CARE,					//	VkAttachmentStoreOp				stencilStoreOp;
   2527 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			//	VkImageLayout					initialLayout;
   2528 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			//	VkImageLayout					finalLayout;
   2529 		};
   2530 		colorAttDescs.push_back(attDesc);
   2531 
   2532 		const VkAttachmentReference			attRef					=
   2533 		{
   2534 			1u,												//	deUint32		attachment;
   2535 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		//	VkImageLayout	layout;
   2536 		};
   2537 		colorAttRefs.push_back(attRef);
   2538 	}
   2539 
   2540 	VkSubpassDescription					subpassDesc				=
   2541 	{
   2542 		0u,												//	VkSubpassDescriptionFlags		flags;
   2543 		VK_PIPELINE_BIND_POINT_GRAPHICS,				//	VkPipelineBindPoint				pipelineBindPoint;
   2544 		0u,												//	deUint32						inputCount;
   2545 		DE_NULL,										//	const VkAttachmentReference*	pInputAttachments;
   2546 		1u,												//	deUint32						colorCount;
   2547 		colorAttRefs.data(),							//	const VkAttachmentReference*	pColorAttachments;
   2548 		DE_NULL,										//	const VkAttachmentReference*	pResolveAttachments;
   2549 		DE_NULL,										//	const VkAttachmentReference*	pDepthStencilAttachment;
   2550 		0u,												//	deUint32						preserveCount;
   2551 		DE_NULL,										//	const VkAttachmentReference*	pPreserveAttachments;
   2552 
   2553 	};
   2554 	VkRenderPassCreateInfo					renderPassParams		=
   2555 	{
   2556 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,		//	VkStructureType					sType;
   2557 		DE_NULL,										//	const void*						pNext;
   2558 		(VkRenderPassCreateFlags)0,
   2559 		1u,												//	deUint32						attachmentCount;
   2560 		colorAttDescs.data(),							//	const VkAttachmentDescription*	pAttachments;
   2561 		1u,												//	deUint32						subpassCount;
   2562 		&subpassDesc,									//	const VkSubpassDescription*		pSubpasses;
   2563 		0u,												//	deUint32						dependencyCount;
   2564 		DE_NULL,										//	const VkSubpassDependency*		pDependencies;
   2565 	};
   2566 
   2567 	if (needInterface)
   2568 	{
   2569 		subpassDesc.colorAttachmentCount += 1;
   2570 		renderPassParams.attachmentCount += 1;
   2571 	}
   2572 
   2573 	const Unique<VkRenderPass>				renderPass				(createRenderPass(vk, *vkDevice, &renderPassParams));
   2574 
   2575 	const VkImageViewCreateInfo				colorAttViewParams		=
   2576 	{
   2577 		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		//	VkStructureType				sType;
   2578 		DE_NULL,										//	const void*					pNext;
   2579 		0u,												//	VkImageViewCreateFlags		flags;
   2580 		*image,											//	VkImage						image;
   2581 		VK_IMAGE_VIEW_TYPE_2D,							//	VkImageViewType				viewType;
   2582 		VK_FORMAT_R8G8B8A8_UNORM,						//	VkFormat					format;
   2583 		{
   2584 			VK_COMPONENT_SWIZZLE_R,
   2585 			VK_COMPONENT_SWIZZLE_G,
   2586 			VK_COMPONENT_SWIZZLE_B,
   2587 			VK_COMPONENT_SWIZZLE_A
   2588 		},												//	VkChannelMapping			channels;
   2589 		{
   2590 			VK_IMAGE_ASPECT_COLOR_BIT,						//	VkImageAspectFlags	aspectMask;
   2591 			0u,												//	deUint32			baseMipLevel;
   2592 			1u,												//	deUint32			mipLevels;
   2593 			0u,												//	deUint32			baseArrayLayer;
   2594 			1u,												//	deUint32			arraySize;
   2595 		},												//	VkImageSubresourceRange		subresourceRange;
   2596 	};
   2597 	const Unique<VkImageView>				colorAttView			(createImageView(vk, *vkDevice, &colorAttViewParams));
   2598 
   2599 	vector<VkImageView>						attViews				;
   2600 	attViews.push_back(*colorAttView);
   2601 
   2602 	// Handle resources requested by the test instantiation.
   2603 	const deUint32							numInResources			= static_cast<deUint32>(instance.resources.inputs.size());
   2604 	const deUint32							numOutResources			= static_cast<deUint32>(instance.resources.outputs.size());
   2605 	// These variables should be placed out of the following if block to avoid deallocation after out of scope.
   2606 	vector<AllocationSp>					inResourceMemories		;
   2607 	vector<AllocationSp>					outResourceMemories		;
   2608 	vector<BufferHandleSp>					inResourceBuffers		;
   2609 	vector<BufferHandleSp>					outResourceBuffers		;
   2610 	Move<VkDescriptorPool>					descriptorPool			;
   2611 	Move<VkDescriptorSetLayout>				setLayout				;
   2612 	VkDescriptorSetLayout					rawSetLayout			= DE_NULL;
   2613 	VkDescriptorSet							rawSet					= DE_NULL;
   2614 
   2615 	if (numResources != 0)
   2616 	{
   2617 		vector<VkDescriptorSetLayoutBinding>	setLayoutBindings	;
   2618 		vector<VkDescriptorPoolSize>			poolSizes			;
   2619 
   2620 		setLayoutBindings.reserve(numResources);
   2621 		poolSizes.reserve(numResources);
   2622 
   2623 		// Process all input resources.
   2624 		for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
   2625 		{
   2626 			const Resource&					resource				= instance.resources.inputs[inputNdx];
   2627 			// Create buffer and allocate memory.
   2628 			Move<VkBuffer>					resourceBuffer			= createBufferForResource(vk, *vkDevice, resource, queueFamilyIndex);
   2629 			de::MovePtr<Allocation>			resourceMemory			= allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *resourceBuffer), MemoryRequirement::HostVisible);
   2630 			vector<deUint8>					resourceBytes;
   2631 
   2632 			VK_CHECK(vk.bindBufferMemory(*vkDevice, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
   2633 
   2634 			// Copy data to memory.
   2635 			const VkMappedMemoryRange		range					=
   2636 			{
   2637 				VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,				//	VkStructureType	sType;
   2638 				DE_NULL,											//	const void*		pNext;
   2639 				resourceMemory->getMemory(),						//	VkDeviceMemory	mem;
   2640 				0,													//	VkDeviceSize	offset;
   2641 				VK_WHOLE_SIZE,										//	VkDeviceSize	size;
   2642 			};
   2643 
   2644 			resource.second->getBytes(resourceBytes);
   2645 			deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
   2646 			VK_CHECK(vk.flushMappedMemoryRanges(*vkDevice, 1u, &range));
   2647 
   2648 			inResourceMemories.push_back(AllocationSp(resourceMemory.release()));
   2649 			inResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
   2650 
   2651 			// Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool.
   2652 			const VkDescriptorSetLayoutBinding	binding				=
   2653 			{
   2654 				inputNdx,											// binding
   2655 				resource.first,										// descriptorType
   2656 				1u,													// descriptorCount
   2657 				VK_SHADER_STAGE_ALL_GRAPHICS,						// stageFlags
   2658 				DE_NULL,											// pImmutableSamplers
   2659 			};
   2660 			setLayoutBindings.push_back(binding);
   2661 
   2662 			// Note: the following code doesn't check and unify descriptors of the same type.
   2663 			const VkDescriptorPoolSize		poolSize				=
   2664 			{
   2665 				resource.first,										// type
   2666 				1u,													// descriptorCount
   2667 			};
   2668 			poolSizes.push_back(poolSize);
   2669 		}
   2670 
   2671 		// Process all output resources.
   2672 		for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
   2673 		{
   2674 			const Resource&					resource				= instance.resources.outputs[outputNdx];
   2675 			// Create buffer and allocate memory.
   2676 			Move<VkBuffer>					resourceBuffer			= createBufferForResource(vk, *vkDevice, resource, queueFamilyIndex);
   2677 			de::MovePtr<Allocation>			resourceMemory			= allocator.allocate(getBufferMemoryRequirements(vk, *vkDevice, *resourceBuffer), MemoryRequirement::HostVisible);
   2678 			vector<deUint8>					resourceBytes;
   2679 
   2680 			VK_CHECK(vk.bindBufferMemory(*vkDevice, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
   2681 
   2682 			// Fill memory with all ones.
   2683 			const VkMappedMemoryRange		range					=
   2684 			{
   2685 				VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,				//	VkStructureType	sType;
   2686 				DE_NULL,											//	const void*		pNext;
   2687 				resourceMemory->getMemory(),						//	VkDeviceMemory	mem;
   2688 				0,													//	VkDeviceSize	offset;
   2689 				VK_WHOLE_SIZE,										//	VkDeviceSize	size;
   2690 			};
   2691 
   2692 			resource.second->getBytes(resourceBytes);
   2693 			deMemset((deUint8*)resourceMemory->getHostPtr(), 0xff, resourceBytes.size());
   2694 			VK_CHECK(vk.flushMappedMemoryRanges(*vkDevice, 1u, &range));
   2695 
   2696 			outResourceMemories.push_back(AllocationSp(resourceMemory.release()));
   2697 			outResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
   2698 
   2699 			// Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool.
   2700 			const VkDescriptorSetLayoutBinding	binding				=
   2701 			{
   2702 				numInResources  + outputNdx,						// binding
   2703 				resource.first,										// descriptorType
   2704 				1u,													// descriptorCount
   2705 				VK_SHADER_STAGE_ALL_GRAPHICS,						// stageFlags
   2706 				DE_NULL,											// pImmutableSamplers
   2707 			};
   2708 			setLayoutBindings.push_back(binding);
   2709 
   2710 			// Note: the following code doesn't check and unify descriptors of the same type.
   2711 			const VkDescriptorPoolSize		poolSize				=
   2712 			{
   2713 				resource.first,										// type
   2714 				1u,													// descriptorCount
   2715 			};
   2716 			poolSizes.push_back(poolSize);
   2717 		}
   2718 
   2719 		// Create descriptor set layout, descriptor pool, and allocate descriptor set.
   2720 		const VkDescriptorSetLayoutCreateInfo	setLayoutParams		=
   2721 		{
   2722 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
   2723 			DE_NULL,												// pNext
   2724 			(VkDescriptorSetLayoutCreateFlags)0,					// flags
   2725 			numResources,											// bindingCount
   2726 			setLayoutBindings.data(),								// pBindings
   2727 		};
   2728 		setLayout													= createDescriptorSetLayout(vk, *vkDevice, &setLayoutParams);
   2729 		rawSetLayout												= *setLayout;
   2730 
   2731 		const VkDescriptorPoolCreateInfo		poolParams			=
   2732 		{
   2733 			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,			// sType
   2734 			DE_NULL,												// pNext
   2735 			(VkDescriptorPoolCreateFlags)0,							// flags
   2736 			1u,														// maxSets
   2737 			numResources,											// poolSizeCount
   2738 			poolSizes.data(),										// pPoolSizes
   2739 		};
   2740 		descriptorPool												= createDescriptorPool(vk, *vkDevice, &poolParams);
   2741 
   2742 		const VkDescriptorSetAllocateInfo		setAllocParams		=
   2743 		{
   2744 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,			// sType
   2745 			DE_NULL,												// pNext
   2746 			*descriptorPool,										// descriptorPool
   2747 			1u,														// descriptorSetCount
   2748 			&rawSetLayout,											// pSetLayouts
   2749 		};
   2750 		VK_CHECK(vk.allocateDescriptorSets(*vkDevice, &setAllocParams, &rawSet));
   2751 
   2752 		// Update descriptor set.
   2753 		vector<VkWriteDescriptorSet>			writeSpecs			;
   2754 		vector<VkDescriptorBufferInfo>			dBufferInfos		;
   2755 
   2756 		writeSpecs.reserve(numResources);
   2757 		dBufferInfos.reserve(numResources);
   2758 
   2759 		for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
   2760 		{
   2761 			const VkDescriptorBufferInfo		bufInfo				=
   2762 			{
   2763 				**inResourceBuffers[inputNdx],						// buffer
   2764 				0,													// offset
   2765 				VK_WHOLE_SIZE,										// size
   2766 			};
   2767 			dBufferInfos.push_back(bufInfo);
   2768 
   2769 			const VkWriteDescriptorSet			writeSpec			= {
   2770 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,				// sType
   2771 				DE_NULL,											// pNext
   2772 				rawSet,												// dstSet
   2773 				inputNdx,											// binding
   2774 				0,													// dstArrayElement
   2775 				1u,													// descriptorCount
   2776 				instance.resources.inputs[inputNdx].first,			// descriptorType
   2777 				DE_NULL,											// pImageInfo
   2778 				&dBufferInfos.back(),								// pBufferInfo
   2779 				DE_NULL,											// pTexelBufferView
   2780 			};
   2781 			writeSpecs.push_back(writeSpec);
   2782 		}
   2783 		for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
   2784 		{
   2785 			const VkDescriptorBufferInfo		bufInfo				=
   2786 			{
   2787 				**outResourceBuffers[outputNdx],					// buffer
   2788 				0,													// offset
   2789 				VK_WHOLE_SIZE,										// size
   2790 			};
   2791 			dBufferInfos.push_back(bufInfo);
   2792 
   2793 			const VkWriteDescriptorSet			writeSpec			= {
   2794 				VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,				// sType
   2795 				DE_NULL,											// pNext
   2796 				rawSet,												// dstSet
   2797 				numInResources + outputNdx,							// binding
   2798 				0,													// dstArrayElement
   2799 				1u,													// descriptorCount
   2800 				instance.resources.outputs[outputNdx].first,		// descriptorType
   2801 				DE_NULL,											// pImageInfo
   2802 				&dBufferInfos.back(),								// pBufferInfo
   2803 				DE_NULL,											// pTexelBufferView
   2804 			};
   2805 			writeSpecs.push_back(writeSpec);
   2806 		}
   2807 		vk.updateDescriptorSets(*vkDevice, numResources, writeSpecs.data(), 0, DE_NULL);
   2808 	}
   2809 
   2810 	// Pipeline layout
   2811 	VkPipelineLayoutCreateInfo				pipelineLayoutParams	=
   2812 	{
   2813 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,			//	VkStructureType					sType;
   2814 		DE_NULL,												//	const void*						pNext;
   2815 		(VkPipelineLayoutCreateFlags)0,
   2816 		0u,														//	deUint32						descriptorSetCount;
   2817 		DE_NULL,												//	const VkDescriptorSetLayout*	pSetLayouts;
   2818 		0u,														//	deUint32						pushConstantRangeCount;
   2819 		DE_NULL,												//	const VkPushConstantRange*		pPushConstantRanges;
   2820 	};
   2821 
   2822 	VkPushConstantRange						pushConstantRange		=
   2823 	{
   2824 		VK_SHADER_STAGE_ALL_GRAPHICS,							// VkShaderStageFlags    stageFlags;
   2825 		0,														// uint32_t              offset;
   2826 		0,														// uint32_t              size;
   2827 	};
   2828 	if (hasPushConstants)
   2829 	{
   2830 		vector<deUint8> pushConstantsBytes;
   2831 		instance.pushConstants.getBuffer()->getBytes(pushConstantsBytes);
   2832 
   2833 		pushConstantRange.size						= static_cast<deUint32>(pushConstantsBytes.size());
   2834 		pipelineLayoutParams.pushConstantRangeCount	= 1;
   2835 		pipelineLayoutParams.pPushConstantRanges	= &pushConstantRange;
   2836 	}
   2837 	if (numResources != 0)
   2838 	{
   2839 		// Update pipeline layout with the descriptor set layout.
   2840 		pipelineLayoutParams.setLayoutCount								= 1;
   2841 		pipelineLayoutParams.pSetLayouts								= &rawSetLayout;
   2842 	}
   2843 	const Unique<VkPipelineLayout>			pipelineLayout			(createPipelineLayout(vk, *vkDevice, &pipelineLayoutParams));
   2844 
   2845 	// Pipeline
   2846 	vector<VkPipelineShaderStageCreateInfo>		shaderStageParams;
   2847 	// We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline().
   2848 	vector<vector<VkSpecializationMapEntry> >	specConstantEntries;
   2849 	vector<VkSpecializationInfo>				specializationInfos;
   2850 	if (DE_NULL != instance.resources.verifyBinary)
   2851 	{
   2852 		std::string shaderName;
   2853 		switch(instance.customizedStages)
   2854 		{
   2855 		case	VK_SHADER_STAGE_VERTEX_BIT:
   2856 			shaderName= "vert";
   2857 			break;
   2858 		case	VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
   2859 			shaderName= "tessc";
   2860 			break;
   2861 		case	VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
   2862 			shaderName= "tesse";
   2863 			break;
   2864 		case	VK_SHADER_STAGE_GEOMETRY_BIT:
   2865 			shaderName= "geom";
   2866 			break;
   2867 		case	VK_SHADER_STAGE_FRAGMENT_BIT:
   2868 			shaderName= "frag";
   2869 			break;
   2870 		default:
   2871 			DE_ASSERT(0);
   2872 			break;
   2873 		}
   2874 		const ProgramBinary& binary  = context.getBinaryCollection().get(shaderName);
   2875 		if (!instance.resources.verifyBinary(binary))
   2876 			return tcu::TestStatus::fail("Binary verification of SPIR-V in the test failed");
   2877 
   2878 	}
   2879 	createPipelineShaderStages(vk, *vkDevice, instance, context, modules, shaderStageParams);
   2880 
   2881 	// And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents.
   2882 	specConstantEntries.reserve(shaderStageParams.size());
   2883 	specializationInfos.reserve(shaderStageParams.size());
   2884 
   2885 	// Patch the specialization info field in PipelineShaderStageCreateInfos.
   2886 	for (vector<VkPipelineShaderStageCreateInfo>::iterator stageInfo = shaderStageParams.begin(); stageInfo != shaderStageParams.end(); ++stageInfo)
   2887 	{
   2888 		const StageToSpecConstantMap::const_iterator stageIt = instance.specConstants.find(stageInfo->stage);
   2889 
   2890 		if (stageIt != instance.specConstants.end())
   2891 		{
   2892 			const size_t						numSpecConstants	= stageIt->second.size();
   2893 			vector<VkSpecializationMapEntry>	entries;
   2894 			VkSpecializationInfo				specInfo;
   2895 
   2896 			entries.resize(numSpecConstants);
   2897 
   2898 			// Only support 32-bit integers as spec constants now. And their constant IDs are numbered sequentially starting from 0.
   2899 			for (size_t ndx = 0; ndx < numSpecConstants; ++ndx)
   2900 			{
   2901 				entries[ndx].constantID	= (deUint32)ndx;
   2902 				entries[ndx].offset		= deUint32(ndx * sizeof(deInt32));
   2903 				entries[ndx].size		= sizeof(deInt32);
   2904 			}
   2905 
   2906 			specConstantEntries.push_back(entries);
   2907 
   2908 			specInfo.mapEntryCount	= (deUint32)numSpecConstants;
   2909 			specInfo.pMapEntries	= specConstantEntries.back().data();
   2910 			specInfo.dataSize		= numSpecConstants * sizeof(deInt32);
   2911 			specInfo.pData			= stageIt->second.data();
   2912 			specializationInfos.push_back(specInfo);
   2913 
   2914 			stageInfo->pSpecializationInfo = &specializationInfos.back();
   2915 		}
   2916 	}
   2917 	const VkPipelineDepthStencilStateCreateInfo	depthStencilParams		=
   2918 	{
   2919 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	//	VkStructureType		sType;
   2920 		DE_NULL,													//	const void*			pNext;
   2921 		(VkPipelineDepthStencilStateCreateFlags)0,
   2922 		DE_FALSE,													//	deUint32			depthTestEnable;
   2923 		DE_FALSE,													//	deUint32			depthWriteEnable;
   2924 		VK_COMPARE_OP_ALWAYS,										//	VkCompareOp			depthCompareOp;
   2925 		DE_FALSE,													//	deUint32			depthBoundsTestEnable;
   2926 		DE_FALSE,													//	deUint32			stencilTestEnable;
   2927 		{
   2928 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilFailOp;
   2929 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilPassOp;
   2930 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilDepthFailOp;
   2931 			VK_COMPARE_OP_ALWAYS,										//	VkCompareOp	stencilCompareOp;
   2932 			0u,															//	deUint32	stencilCompareMask;
   2933 			0u,															//	deUint32	stencilWriteMask;
   2934 			0u,															//	deUint32	stencilReference;
   2935 		},															//	VkStencilOpState	front;
   2936 		{
   2937 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilFailOp;
   2938 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilPassOp;
   2939 			VK_STENCIL_OP_KEEP,											//	VkStencilOp	stencilDepthFailOp;
   2940 			VK_COMPARE_OP_ALWAYS,										//	VkCompareOp	stencilCompareOp;
   2941 			0u,															//	deUint32	stencilCompareMask;
   2942 			0u,															//	deUint32	stencilWriteMask;
   2943 			0u,															//	deUint32	stencilReference;
   2944 		},															//	VkStencilOpState	back;
   2945 		-1.0f,														//	float				minDepthBounds;
   2946 		+1.0f,														//	float				maxDepthBounds;
   2947 	};
   2948 	const VkViewport						viewport0				=
   2949 	{
   2950 		0.0f,														//	float	originX;
   2951 		0.0f,														//	float	originY;
   2952 		(float)renderSize.x(),										//	float	width;
   2953 		(float)renderSize.y(),										//	float	height;
   2954 		0.0f,														//	float	minDepth;
   2955 		1.0f,														//	float	maxDepth;
   2956 	};
   2957 	const VkRect2D							scissor0				=
   2958 	{
   2959 		{
   2960 			0u,															//	deInt32	x;
   2961 			0u,															//	deInt32	y;
   2962 		},															//	VkOffset2D	offset;
   2963 		{
   2964 			renderSize.x(),												//	deInt32	width;
   2965 			renderSize.y(),												//	deInt32	height;
   2966 		},															//	VkExtent2D	extent;
   2967 	};
   2968 	const VkPipelineViewportStateCreateInfo		viewportParams			=
   2969 	{
   2970 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,		//	VkStructureType		sType;
   2971 		DE_NULL,													//	const void*			pNext;
   2972 		(VkPipelineViewportStateCreateFlags)0,
   2973 		1u,															//	deUint32			viewportCount;
   2974 		&viewport0,
   2975 		1u,
   2976 		&scissor0
   2977 	};
   2978 	const VkSampleMask							sampleMask				= ~0u;
   2979 	const VkPipelineMultisampleStateCreateInfo	multisampleParams		=
   2980 	{
   2981 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType			sType;
   2982 		DE_NULL,													//	const void*				pNext;
   2983 		(VkPipelineMultisampleStateCreateFlags)0,
   2984 		VK_SAMPLE_COUNT_1_BIT,										//	VkSampleCountFlagBits	rasterSamples;
   2985 		DE_FALSE,													//	deUint32				sampleShadingEnable;
   2986 		0.0f,														//	float					minSampleShading;
   2987 		&sampleMask,												//	const VkSampleMask*		pSampleMask;
   2988 		DE_FALSE,													//	VkBool32				alphaToCoverageEnable;
   2989 		DE_FALSE,													//	VkBool32				alphaToOneEnable;
   2990 	};
   2991 	const VkPipelineRasterizationStateCreateInfo	rasterParams		=
   2992 	{
   2993 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//	VkStructureType	sType;
   2994 		DE_NULL,													//	const void*		pNext;
   2995 		(VkPipelineRasterizationStateCreateFlags)0,
   2996 		DE_FALSE,													//	deUint32		depthClampEnable;
   2997 		DE_FALSE,													//	deUint32		rasterizerDiscardEnable;
   2998 		VK_POLYGON_MODE_FILL,										//	VkFillMode		fillMode;
   2999 		VK_CULL_MODE_NONE,											//	VkCullMode		cullMode;
   3000 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							//	VkFrontFace		frontFace;
   3001 		VK_FALSE,													//	VkBool32		depthBiasEnable;
   3002 		0.0f,														//	float			depthBias;
   3003 		0.0f,														//	float			depthBiasClamp;
   3004 		0.0f,														//	float			slopeScaledDepthBias;
   3005 		1.0f,														//	float			lineWidth;
   3006 	};
   3007 	const VkPrimitiveTopology topology = hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
   3008 	const VkPipelineInputAssemblyStateCreateInfo	inputAssemblyParams	=
   3009 	{
   3010 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	//	VkStructureType		sType;
   3011 		DE_NULL,														//	const void*			pNext;
   3012 		(VkPipelineInputAssemblyStateCreateFlags)0,
   3013 		topology,														//	VkPrimitiveTopology	topology;
   3014 		DE_FALSE,														//	deUint32			primitiveRestartEnable;
   3015 	};
   3016 
   3017 	vector<VkVertexInputBindingDescription>		vertexBindings;
   3018 	vector<VkVertexInputAttributeDescription>	vertexAttribs;
   3019 
   3020 	const VkVertexInputBindingDescription		vertexBinding0			=
   3021 	{
   3022 		0u,									// deUint32					binding;
   3023 		deUint32(singleVertexDataSize),		// deUint32					strideInBytes;
   3024 		VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	stepRate;
   3025 	};
   3026 	vertexBindings.push_back(vertexBinding0);
   3027 
   3028 	{
   3029 		VkVertexInputAttributeDescription		attr0					=
   3030 		{
   3031 			0u,									// deUint32	location;
   3032 			0u,									// deUint32	binding;
   3033 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
   3034 			0u									// deUint32	offsetInBytes;
   3035 		};
   3036 		vertexAttribs.push_back(attr0);
   3037 
   3038 		VkVertexInputAttributeDescription		attr1					=
   3039 		{
   3040 			1u,									// deUint32	location;
   3041 			0u,									// deUint32	binding;
   3042 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat	format;
   3043 			sizeof(Vec4),						// deUint32	offsetInBytes;
   3044 		};
   3045 		vertexAttribs.push_back(attr1);
   3046 	};
   3047 
   3048 	// If the test instantiation has additional input/output interface variables, we need to create additional bindings.
   3049 	// Right now we only support one additional input varible for the vertex stage, and that will be bound to binding #1
   3050 	// with location #2.
   3051 	if (needInterface)
   3052 	{
   3053 		const VkVertexInputBindingDescription	vertexBinding1			=
   3054 		{
   3055 			1u,													// deUint32					binding;
   3056 			instance.interfaces.getInputType().getNumBytes(),	// deUint32					strideInBytes;
   3057 			VK_VERTEX_INPUT_RATE_VERTEX							// VkVertexInputStepRate	stepRate;
   3058 		};
   3059 		vertexBindings.push_back(vertexBinding1);
   3060 
   3061 		VkVertexInputAttributeDescription		attr					=
   3062 		{
   3063 			2u,													// deUint32	location;
   3064 			1u,													// deUint32	binding;
   3065 			instance.interfaces.getInputType().getVkFormat(),	// VkFormat	format;
   3066 			0,													// deUint32	offsetInBytes;
   3067 		};
   3068 		vertexAttribs.push_back(attr);
   3069 	}
   3070 
   3071 	VkPipelineVertexInputStateCreateInfo		vertexInputStateParams	=
   3072 	{
   3073 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	//	VkStructureType								sType;
   3074 		DE_NULL,													//	const void*									pNext;
   3075 		(VkPipelineVertexInputStateCreateFlags)0,
   3076 		1u,															//	deUint32									bindingCount;
   3077 		vertexBindings.data(),										//	const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
   3078 		2u,															//	deUint32									attributeCount;
   3079 		vertexAttribs.data(),										//	const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
   3080 	};
   3081 
   3082 	if (needInterface)
   3083 	{
   3084 		vertexInputStateParams.vertexBindingDescriptionCount += 1;
   3085 		vertexInputStateParams.vertexAttributeDescriptionCount += 1;
   3086 	}
   3087 
   3088 	vector<VkPipelineColorBlendAttachmentState>	attBlendStates			;
   3089 	const VkPipelineColorBlendAttachmentState	attBlendState			=
   3090 	{
   3091 		DE_FALSE,													//	deUint32		blendEnable;
   3092 		VK_BLEND_FACTOR_ONE,										//	VkBlend			srcBlendColor;
   3093 		VK_BLEND_FACTOR_ZERO,										//	VkBlend			destBlendColor;
   3094 		VK_BLEND_OP_ADD,											//	VkBlendOp		blendOpColor;
   3095 		VK_BLEND_FACTOR_ONE,										//	VkBlend			srcBlendAlpha;
   3096 		VK_BLEND_FACTOR_ZERO,										//	VkBlend			destBlendAlpha;
   3097 		VK_BLEND_OP_ADD,											//	VkBlendOp		blendOpAlpha;
   3098 		(VK_COLOR_COMPONENT_R_BIT|
   3099 		 VK_COLOR_COMPONENT_G_BIT|
   3100 		 VK_COLOR_COMPONENT_B_BIT|
   3101 		 VK_COLOR_COMPONENT_A_BIT),									//	VkChannelFlags	channelWriteMask;
   3102 	};
   3103 	attBlendStates.push_back(attBlendState);
   3104 
   3105 	if (needInterface)
   3106 		attBlendStates.push_back(attBlendState);
   3107 
   3108 	VkPipelineColorBlendStateCreateInfo		blendParams				=
   3109 	{
   3110 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	//	VkStructureType								sType;
   3111 		DE_NULL,													//	const void*									pNext;
   3112 		(VkPipelineColorBlendStateCreateFlags)0,
   3113 		DE_FALSE,													//	VkBool32									logicOpEnable;
   3114 		VK_LOGIC_OP_COPY,											//	VkLogicOp									logicOp;
   3115 		1u,															//	deUint32									attachmentCount;
   3116 		attBlendStates.data(),										//	const VkPipelineColorBlendAttachmentState*	pAttachments;
   3117 		{ 0.0f, 0.0f, 0.0f, 0.0f },									//	float										blendConst[4];
   3118 	};
   3119 	if (needInterface)
   3120 	{
   3121 		blendParams.attachmentCount += 1;
   3122 	}
   3123 	const VkPipelineTessellationStateCreateInfo	tessellationState	=
   3124 	{
   3125 		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
   3126 		DE_NULL,
   3127 		(VkPipelineTessellationStateCreateFlags)0,
   3128 		3u
   3129 	};
   3130 
   3131 	const VkPipelineTessellationStateCreateInfo* tessellationInfo	=	hasTessellation ? &tessellationState: DE_NULL;
   3132 	const VkGraphicsPipelineCreateInfo		pipelineParams			=
   3133 	{
   3134 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,		//	VkStructureType									sType;
   3135 		DE_NULL,												//	const void*										pNext;
   3136 		0u,														//	VkPipelineCreateFlags							flags;
   3137 		(deUint32)shaderStageParams.size(),						//	deUint32										stageCount;
   3138 		&shaderStageParams[0],									//	const VkPipelineShaderStageCreateInfo*			pStages;
   3139 		&vertexInputStateParams,								//	const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
   3140 		&inputAssemblyParams,									//	const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
   3141 		tessellationInfo,										//	const VkPipelineTessellationStateCreateInfo*	pTessellationState;
   3142 		&viewportParams,										//	const VkPipelineViewportStateCreateInfo*		pViewportState;
   3143 		&rasterParams,											//	const VkPipelineRasterStateCreateInfo*			pRasterState;
   3144 		&multisampleParams,										//	const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
   3145 		&depthStencilParams,									//	const VkPipelineDepthStencilStateCreateInfo*	pDepthStencilState;
   3146 		&blendParams,											//	const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
   3147 		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,		//	const VkPipelineDynamicStateCreateInfo*			pDynamicState;
   3148 		*pipelineLayout,										//	VkPipelineLayout								layout;
   3149 		*renderPass,											//	VkRenderPass									renderPass;
   3150 		0u,														//	deUint32										subpass;
   3151 		DE_NULL,												//	VkPipeline										basePipelineHandle;
   3152 		0u,														//	deInt32											basePipelineIndex;
   3153 	};
   3154 
   3155 	const Unique<VkPipeline>				pipeline				(createGraphicsPipeline(vk, *vkDevice, DE_NULL, &pipelineParams));
   3156 
   3157 	if (needInterface)
   3158 	{
   3159 		const VkImageViewCreateInfo			fragOutputViewParams	=
   3160 		{
   3161 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			//	VkStructureType				sType;
   3162 			DE_NULL,											//	const void*					pNext;
   3163 			0u,													//	VkImageViewCreateFlags		flags;
   3164 			*fragOutputImage,									//	VkImage						image;
   3165 			VK_IMAGE_VIEW_TYPE_2D,								//	VkImageViewType				viewType;
   3166 			instance.interfaces.getOutputType().getVkFormat(),	//	VkFormat					format;
   3167 			{
   3168 				VK_COMPONENT_SWIZZLE_R,
   3169 				VK_COMPONENT_SWIZZLE_G,
   3170 				VK_COMPONENT_SWIZZLE_B,
   3171 				VK_COMPONENT_SWIZZLE_A
   3172 			},													//	VkChannelMapping			channels;
   3173 			{
   3174 				VK_IMAGE_ASPECT_COLOR_BIT,						//	VkImageAspectFlags	aspectMask;
   3175 				0u,												//	deUint32			baseMipLevel;
   3176 				1u,												//	deUint32			mipLevels;
   3177 				0u,												//	deUint32			baseArrayLayer;
   3178 				1u,												//	deUint32			arraySize;
   3179 			},													//	VkImageSubresourceRange		subresourceRange;
   3180 		};
   3181 		fragOutputImageView = createImageView(vk, *vkDevice, &fragOutputViewParams);
   3182 		attViews.push_back(*fragOutputImageView);
   3183 	}
   3184 
   3185 	// Framebuffer
   3186 	VkFramebufferCreateInfo					framebufferParams		=
   3187 	{
   3188 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,				//	VkStructureType		sType;
   3189 		DE_NULL,												//	const void*			pNext;
   3190 		(VkFramebufferCreateFlags)0,
   3191 		*renderPass,											//	VkRenderPass		renderPass;
   3192 		1u,														//	deUint32			attachmentCount;
   3193 		attViews.data(),										//	const VkImageView*	pAttachments;
   3194 		(deUint32)renderSize.x(),								//	deUint32			width;
   3195 		(deUint32)renderSize.y(),								//	deUint32			height;
   3196 		1u,														//	deUint32			layers;
   3197 	};
   3198 
   3199 	if (needInterface)
   3200 		framebufferParams.attachmentCount += 1;
   3201 
   3202 	const Unique<VkFramebuffer>				framebuffer				(createFramebuffer(vk, *vkDevice, &framebufferParams));
   3203 
   3204 	const Unique<VkCommandPool>				cmdPool					(createCommandPool(vk, *vkDevice, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
   3205 
   3206 	// Command buffer
   3207 	const Unique<VkCommandBuffer>			cmdBuf					(allocateCommandBuffer(vk, *vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
   3208 
   3209 	const VkCommandBufferBeginInfo			cmdBufBeginParams		=
   3210 	{
   3211 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			//	VkStructureType				sType;
   3212 		DE_NULL,												//	const void*					pNext;
   3213 		(VkCommandBufferUsageFlags)0,
   3214 		(const VkCommandBufferInheritanceInfo*)DE_NULL,
   3215 	};
   3216 
   3217 	// Record commands
   3218 	VK_CHECK(vk.beginCommandBuffer(*cmdBuf, &cmdBufBeginParams));
   3219 
   3220 	{
   3221 		const VkMemoryBarrier			vertFlushBarrier	=
   3222 		{
   3223 			VK_STRUCTURE_TYPE_MEMORY_BARRIER,			//	VkStructureType		sType;
   3224 			DE_NULL,									//	const void*			pNext;
   3225 			VK_ACCESS_HOST_WRITE_BIT,					//	VkMemoryOutputFlags	outputMask;
   3226 			VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,		//	VkMemoryInputFlags	inputMask;
   3227 		};
   3228 		vector<VkImageMemoryBarrier>	colorAttBarriers	;
   3229 
   3230 		VkImageMemoryBarrier			imgBarrier          =
   3231 		{
   3232 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		//	VkStructureType			sType;
   3233 			DE_NULL,									//	const void*				pNext;
   3234 			0u,											//	VkMemoryOutputFlags		outputMask;
   3235 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		//	VkMemoryInputFlags		inputMask;
   3236 			VK_IMAGE_LAYOUT_UNDEFINED,					//	VkImageLayout			oldLayout;
   3237 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout			newLayout;
   3238 			queueFamilyIndex,							//	deUint32				srcQueueFamilyIndex;
   3239 			queueFamilyIndex,							//	deUint32				destQueueFamilyIndex;
   3240 			*image,										//	VkImage					image;
   3241 			{
   3242 				VK_IMAGE_ASPECT_COLOR_BIT,					//	VkImageAspect	aspect;
   3243 				0u,											//	deUint32		baseMipLevel;
   3244 				1u,											//	deUint32		mipLevels;
   3245 				0u,											//	deUint32		baseArraySlice;
   3246 				1u,											//	deUint32		arraySize;
   3247 			}											//	VkImageSubresourceRange	subresourceRange;
   3248 		};
   3249 		colorAttBarriers.push_back(imgBarrier);
   3250 		if (needInterface)
   3251 		{
   3252 			imgBarrier.image = *fragOutputImage;
   3253 			colorAttBarriers.push_back(imgBarrier);
   3254 			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());
   3255 		}
   3256 		else
   3257 		{
   3258 			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());
   3259 		}
   3260 	}
   3261 
   3262 	{
   3263 		vector<VkClearValue>			clearValue		;
   3264 		clearValue.push_back(makeClearValueColorF32(0.125f, 0.25f, 0.75f, 1.0f));
   3265 		if (needInterface)
   3266 		{
   3267 			clearValue.push_back(makeClearValueColorU32(0, 0, 0, 0));
   3268 		}
   3269 		VkRenderPassBeginInfo			passBeginParams	=
   3270 		{
   3271 			VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,			//	VkStructureType		sType;
   3272 			DE_NULL,											//	const void*			pNext;
   3273 			*renderPass,										//	VkRenderPass		renderPass;
   3274 			*framebuffer,										//	VkFramebuffer		framebuffer;
   3275 			{ { 0, 0 }, { renderSize.x(), renderSize.y() } },	//	VkRect2D			renderArea;
   3276 			1u,													//	deUint32			clearValueCount;
   3277 			clearValue.data(),									//	const VkClearValue*	pClearValues;
   3278 		};
   3279 		if (needInterface)
   3280 		{
   3281 			passBeginParams.clearValueCount += 1;
   3282 		}
   3283 		vk.cmdBeginRenderPass(*cmdBuf, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE);
   3284 	}
   3285 
   3286 	vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
   3287 	{
   3288 		const VkDeviceSize bindingOffset = 0;
   3289 		vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
   3290 	}
   3291 	if (needInterface)
   3292 	{
   3293 		const VkDeviceSize bindingOffset = 0;
   3294 		vk.cmdBindVertexBuffers(*cmdBuf, 1u, 1u, &vertexInputBuffer.get(), &bindingOffset);
   3295 	}
   3296 	if (hasPushConstants)
   3297 	{
   3298 		vector<deUint8> pushConstantsBytes;
   3299 		instance.pushConstants.getBuffer()->getBytes(pushConstantsBytes);
   3300 
   3301 		const deUint32	size	= static_cast<deUint32>(pushConstantsBytes.size());
   3302 		const void*		data	= &pushConstantsBytes.front();
   3303 
   3304 		vk.cmdPushConstants(*cmdBuf, *pipelineLayout, VK_SHADER_STAGE_ALL_GRAPHICS, 0, size, data);
   3305 	}
   3306 	if (numResources != 0)
   3307 	{
   3308 		// Bind to set number 0.
   3309 		vk.cmdBindDescriptorSets(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, &rawSet, 0, DE_NULL);
   3310 	}
   3311 	vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/);
   3312 	vk.cmdEndRenderPass(*cmdBuf);
   3313 
   3314 	{
   3315 		vector<VkImageMemoryBarrier>	renderFinishBarrier;
   3316 		VkImageMemoryBarrier			imgBarrier				=
   3317 		{
   3318 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		//	VkStructureType			sType;
   3319 			DE_NULL,									//	const void*				pNext;
   3320 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		//	VkMemoryOutputFlags		outputMask;
   3321 			VK_ACCESS_TRANSFER_READ_BIT,				//	VkMemoryInputFlags		inputMask;
   3322 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	//	VkImageLayout			oldLayout;
   3323 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		//	VkImageLayout			newLayout;
   3324 			queueFamilyIndex,							//	deUint32				srcQueueFamilyIndex;
   3325 			queueFamilyIndex,							//	deUint32				destQueueFamilyIndex;
   3326 			*image,										//	VkImage					image;
   3327 			{
   3328 				VK_IMAGE_ASPECT_COLOR_BIT,					//	VkImageAspectFlags	aspectMask;
   3329 				0u,											//	deUint32			baseMipLevel;
   3330 				1u,											//	deUint32			mipLevels;
   3331 				0u,											//	deUint32			baseArraySlice;
   3332 				1u,											//	deUint32			arraySize;
   3333 			}											//	VkImageSubresourceRange	subresourceRange;
   3334 		};
   3335 		renderFinishBarrier.push_back(imgBarrier);
   3336 
   3337 		if (needInterface)
   3338 		{
   3339 			imgBarrier.image = *fragOutputImage;
   3340 			renderFinishBarrier.push_back(imgBarrier);
   3341 			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());
   3342 		}
   3343 		else
   3344 		{
   3345 			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());
   3346 		}
   3347 	}
   3348 
   3349 	{
   3350 		const VkBufferImageCopy	copyParams	=
   3351 		{
   3352 			(VkDeviceSize)0u,						//	VkDeviceSize			bufferOffset;
   3353 			(deUint32)renderSize.x(),				//	deUint32				bufferRowLength;
   3354 			(deUint32)renderSize.y(),				//	deUint32				bufferImageHeight;
   3355 			{
   3356 				VK_IMAGE_ASPECT_COLOR_BIT,				//	VkImageAspect		aspect;
   3357 				0u,										//	deUint32			mipLevel;
   3358 				0u,										//	deUint32			arrayLayer;
   3359 				1u,										//	deUint32			arraySize;
   3360 			},										//	VkImageSubresourceCopy	imageSubresource;
   3361 			{ 0u, 0u, 0u },							//	VkOffset3D				imageOffset;
   3362 			{ renderSize.x(), renderSize.y(), 1u }	//	VkExtent3D				imageExtent;
   3363 		};
   3364 		vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, &copyParams);
   3365 
   3366 		if (needInterface)
   3367 		{
   3368 			vk.cmdCopyImageToBuffer(*cmdBuf, *fragOutputImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *fragOutputBuffer, 1u, &copyParams);
   3369 		}
   3370 	}
   3371 
   3372 	{
   3373 		vector<VkBufferMemoryBarrier> cpFinishBarriers		;
   3374 		VkBufferMemoryBarrier			copyFinishBarrier	=
   3375 		{
   3376 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	//	VkStructureType		sType;
   3377 			DE_NULL,									//	const void*			pNext;
   3378 			VK_ACCESS_TRANSFER_WRITE_BIT,				//	VkMemoryOutputFlags	outputMask;
   3379 			VK_ACCESS_HOST_READ_BIT,					//	VkMemoryInputFlags	inputMask;
   3380 			queueFamilyIndex,							//	deUint32			srcQueueFamilyIndex;
   3381 			queueFamilyIndex,							//	deUint32			destQueueFamilyIndex;
   3382 			*readImageBuffer,							//	VkBuffer			buffer;
   3383 			0u,											//	VkDeviceSize		offset;
   3384 			imageSizeBytes								//	VkDeviceSize		size;
   3385 		};
   3386 		cpFinishBarriers.push_back(copyFinishBarrier);
   3387 
   3388 		if (needInterface)
   3389 		{
   3390 			copyFinishBarrier.buffer	= *fragOutputBuffer;
   3391 			copyFinishBarrier.size		= VK_WHOLE_SIZE;
   3392 			cpFinishBarriers.push_back(copyFinishBarrier);
   3393 
   3394 			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);
   3395 		}
   3396 		else
   3397 		{
   3398 			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);
   3399 		}
   3400 	}
   3401 
   3402 	VK_CHECK(vk.endCommandBuffer(*cmdBuf));
   3403 
   3404 	// Upload vertex data
   3405 	{
   3406 		const VkMappedMemoryRange	range			=
   3407 		{
   3408 			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	//	VkStructureType	sType;
   3409 			DE_NULL,								//	const void*		pNext;
   3410 			vertexBufferMemory->getMemory(),		//	VkDeviceMemory	mem;
   3411 			0,										//	VkDeviceSize	offset;
   3412 			(VkDeviceSize)sizeof(vertexData),		//	VkDeviceSize	size;
   3413 		};
   3414 		void*						vertexBufPtr	= vertexBufferMemory->getHostPtr();
   3415 
   3416 		deMemcpy(vertexBufPtr, &vertexData[0], sizeof(vertexData));
   3417 		VK_CHECK(vk.flushMappedMemoryRanges(*vkDevice, 1u, &range));
   3418 	}
   3419 
   3420 	if (needInterface)
   3421 	{
   3422 		vector<deUint8> inputBufferBytes;
   3423 		instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
   3424 
   3425 		const deUint32				typNumBytes		= instance.interfaces.getInputType().getNumBytes();
   3426 		const deUint32				bufNumBytes		= static_cast<deUint32>(inputBufferBytes.size());
   3427 
   3428 		// Require that the test instantation provides four output values.
   3429 		DE_ASSERT(bufNumBytes == 4 * typNumBytes);
   3430 
   3431 		// We have four triangles. Because interpolation happens before executing the fragment shader,
   3432 		// we need to provide the same vertex attribute for the same triangle. That means, duplicate each
   3433 		// value three times for all four values.
   3434 
   3435 		const deUint8*				provided		= static_cast<const deUint8*>(&inputBufferBytes.front());
   3436 		vector<deUint8>				data;
   3437 
   3438 		data.reserve(3 * bufNumBytes);
   3439 
   3440 		for (deUint32 offset = 0; offset < bufNumBytes; offset += typNumBytes)
   3441 			for (deUint32 vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
   3442 				for (deUint32 byteNdx = 0; byteNdx < typNumBytes; ++byteNdx)
   3443 					data.push_back(provided[offset + byteNdx]);
   3444 
   3445 		deMemcpy(vertexInputMemory->getHostPtr(), data.data(), data.size());
   3446 
   3447 		const VkMappedMemoryRange	range			=
   3448 		{
   3449 			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	//	VkStructureType	sType;
   3450 			DE_NULL,								//	const void*		pNext;
   3451 			vertexInputMemory->getMemory(),			//	VkDeviceMemory	mem;
   3452 			0,										//	VkDeviceSize	offset;
   3453 			VK_WHOLE_SIZE,							//	VkDeviceSize	size;
   3454 		};
   3455 
   3456 		VK_CHECK(vk.flushMappedMemoryRanges(*vkDevice, 1u, &range));
   3457 	}
   3458 
   3459 	// Submit & wait for completion
   3460 	{
   3461 		const VkFenceCreateInfo	fenceParams	=
   3462 		{
   3463 			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,	//	VkStructureType		sType;
   3464 			DE_NULL,								//	const void*			pNext;
   3465 			0u,										//	VkFenceCreateFlags	flags;
   3466 		};
   3467 		const Unique<VkFence>	fence		(createFence(vk, *vkDevice, &fenceParams));
   3468 		const VkSubmitInfo		submitInfo	=
   3469 		{
   3470 			VK_STRUCTURE_TYPE_SUBMIT_INFO,
   3471 			DE_NULL,
   3472 			0u,
   3473 			(const VkSemaphore*)DE_NULL,
   3474 			(const VkPipelineStageFlags*)DE_NULL,
   3475 			1u,
   3476 			&cmdBuf.get(),
   3477 			0u,
   3478 			(const VkSemaphore*)DE_NULL,
   3479 		};
   3480 
   3481 		VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
   3482 		VK_CHECK(vk.waitForFences(*vkDevice, 1u, &fence.get(), DE_TRUE, ~0ull));
   3483 	}
   3484 
   3485 	const void* imagePtr	= readImageBufferMemory->getHostPtr();
   3486 	const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
   3487 												  renderSize.x(), renderSize.y(), 1, imagePtr);
   3488 	// Log image
   3489 	{
   3490 		const VkMappedMemoryRange	range		=
   3491 		{
   3492 			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	//	VkStructureType	sType;
   3493 			DE_NULL,								//	const void*		pNext;
   3494 			readImageBufferMemory->getMemory(),		//	VkDeviceMemory	mem;
   3495 			0,										//	VkDeviceSize	offset;
   3496 			imageSizeBytes,							//	VkDeviceSize	size;
   3497 		};
   3498 
   3499 		VK_CHECK(vk.invalidateMappedMemoryRanges(*vkDevice, 1u, &range));
   3500 		context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer);
   3501 	}
   3502 
   3503 	if (needInterface)
   3504 	{
   3505 		const VkDeviceSize			fragOutputImgSize	= (VkDeviceSize)(instance.interfaces.getOutputType().getNumBytes() * renderSize.x() * renderSize.y());
   3506 		const VkMappedMemoryRange	range				=
   3507 		{
   3508 			VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	//	VkStructureType	sType;
   3509 			DE_NULL,								//	const void*		pNext;
   3510 			fragOutputMemory->getMemory(),			//	VkDeviceMemory	mem;
   3511 			0,										//	VkDeviceSize	offset;
   3512 			fragOutputImgSize,						//	VkDeviceSize	size;
   3513 		};
   3514 
   3515 		VK_CHECK(vk.invalidateMappedMemoryRanges(*vkDevice, 1u, &range));
   3516 	}
   3517 
   3518 	{ // Make sure all output resources are ready.
   3519 		for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
   3520 		{
   3521 			const VkMappedMemoryRange	range	=
   3522 			{
   3523 				VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,			//	VkStructureType	sType;
   3524 				DE_NULL,										//	const void*		pNext;
   3525 				outResourceMemories[outputNdx]->getMemory(),	//	VkDeviceMemory	mem;
   3526 				0,												//	VkDeviceSize	offset;
   3527 				VK_WHOLE_SIZE,									//	VkDeviceSize	size;
   3528 			};
   3529 
   3530 			VK_CHECK(vk.invalidateMappedMemoryRanges(*vkDevice, 1u, &range));
   3531 		}
   3532 	}
   3533 
   3534 	const RGBA threshold(1, 1, 1, 1);
   3535 
   3536 	const RGBA upperLeft(pixelBuffer.getPixel(1, 1));
   3537 	if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold))
   3538 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper left corner mismatch"));
   3539 
   3540 	const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1));
   3541 	if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold))
   3542 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper right corner mismatch"));
   3543 
   3544 	const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1));
   3545 	if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold))
   3546 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower left corner mismatch"));
   3547 
   3548 	const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1));
   3549 	if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold))
   3550 		return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower right corner mismatch"));
   3551 
   3552 	// Check that the contents in the ouput variable matches expected.
   3553 	if (needInterface)
   3554 	{
   3555 		vector<deUint8>						inputBufferBytes;
   3556 		vector<deUint8>						outputBufferBytes;
   3557 
   3558 		instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
   3559 		instance.interfaces.getOutputBuffer()->getBytes(outputBufferBytes);
   3560 
   3561 		const IFDataType&					outputType				= instance.interfaces.getOutputType();
   3562 		const void*							inputData				= &inputBufferBytes.front();
   3563 		const void*							outputData				= &outputBufferBytes.front();
   3564 		vector<std::pair<int, int> >		positions;
   3565 		const tcu::ConstPixelBufferAccess	fragOutputBufferAccess	(outputType.getTextureFormat(), renderSize.x(), renderSize.y(), 1, fragOutputMemory->getHostPtr());
   3566 
   3567 		positions.push_back(std::make_pair(1, 1));
   3568 		positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, 1));
   3569 		positions.push_back(std::make_pair(1, fragOutputBufferAccess.getHeight() - 1));
   3570 		positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, fragOutputBufferAccess.getHeight() - 1));
   3571 
   3572 		for (deUint32 posNdx = 0; posNdx < positions.size(); ++posNdx)
   3573 		{
   3574 			const int	x		= positions[posNdx].first;
   3575 			const int	y		= positions[posNdx].second;
   3576 			bool		equal	= true;
   3577 
   3578 			if (outputType.elementType == NUMBERTYPE_FLOAT32)
   3579 			{
   3580 				const float*		expected	= static_cast<const float*>(outputData) + posNdx * outputType.numElements;
   3581 				const float*		actual		= static_cast<const float*>(fragOutputBufferAccess.getPixelPtr(x, y));
   3582 
   3583 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
   3584 					if (!compare32BitFloat(expected[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
   3585 						equal = false;
   3586 			}
   3587 			else if (outputType.elementType == NUMBERTYPE_INT32)
   3588 			{
   3589 				const deInt32*		expected	= static_cast<const deInt32*>(outputData) + posNdx * outputType.numElements;
   3590 				const deInt32*		actual		= static_cast<const deInt32*>(fragOutputBufferAccess.getPixelPtr(x, y));
   3591 
   3592 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
   3593 					if (expected[eleNdx] != actual[eleNdx])
   3594 						equal = false;
   3595 			}
   3596 			else if (outputType.elementType == NUMBERTYPE_UINT32)
   3597 			{
   3598 				const deUint32*		expected	= static_cast<const deUint32*>(outputData) + posNdx * outputType.numElements;
   3599 				const deUint32*		actual		= static_cast<const deUint32*>(fragOutputBufferAccess.getPixelPtr(x, y));
   3600 
   3601 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
   3602 					if (expected[eleNdx] != actual[eleNdx])
   3603 						equal = false;
   3604 			}
   3605 			else if (outputType.elementType == NUMBERTYPE_FLOAT16)
   3606 			{
   3607 				const float*		original	= static_cast<const float*>(inputData) + posNdx * outputType.numElements;
   3608 				const deFloat16*	actual		= static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
   3609 
   3610 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
   3611 					if (!compare16BitFloat(original[eleNdx], actual[eleNdx], instance.interfaces.getRoundingMode(), context.getTestContext().getLog()))
   3612 						equal = false;
   3613 			}
   3614 			else if (outputType.elementType == NUMBERTYPE_INT16)
   3615 			{
   3616 				const deInt16*		expected	= static_cast<const deInt16*>(outputData) + posNdx * outputType.numElements;
   3617 				const deInt16*		actual		= static_cast<const deInt16*>(fragOutputBufferAccess.getPixelPtr(x, y));
   3618 
   3619 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
   3620 					if (expected[eleNdx] != actual[eleNdx])
   3621 						equal = false;
   3622 			}
   3623 			else if (outputType.elementType == NUMBERTYPE_UINT16)
   3624 			{
   3625 				const deUint16*		expected	= static_cast<const deUint16*>(outputData) + posNdx * outputType.numElements;
   3626 				const deUint16*		actual		= static_cast<const deUint16*>(fragOutputBufferAccess.getPixelPtr(x, y));
   3627 
   3628 				for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
   3629 					if (expected[eleNdx] != actual[eleNdx])
   3630 						equal = false;
   3631 			}
   3632 			else {
   3633 				DE_ASSERT(0 && "unhandled type");
   3634 			}
   3635 
   3636 			if (!equal)
   3637 				return TestStatus(instance.failResult, instance.getSpecializedFailMessage("fragment output dat point #" + numberToString(posNdx) + " mismatch"));
   3638 		}
   3639 	}
   3640 
   3641 	// Check the contents in output resources match with expected.
   3642 	for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
   3643 	{
   3644 		const BufferSp& expected = instance.resources.outputs[outputNdx].second;
   3645 
   3646 		if (instance.resources.verifyIO != DE_NULL)
   3647 		{
   3648 			if (!(*instance.resources.verifyIO)(instance.resources.inputs, outResourceMemories, instance.resources.outputs, context.getTestContext().getLog()))
   3649 				return tcu::TestStatus::fail("Resource returned doesn't match with expected");
   3650 		}
   3651 		else
   3652 		{
   3653 			vector<deUint8> expectedBytes;
   3654 			expected->getBytes(expectedBytes);
   3655 
   3656 			if (deMemCmp(&expectedBytes.front(), outResourceMemories[outputNdx]->getHostPtr(), expectedBytes.size()))
   3657 				return tcu::TestStatus::fail("Resource returned doesn't match bitwisely with expected");
   3658 		}
   3659 	}
   3660 
   3661 	return TestStatus::pass("Rendered output matches input");
   3662 }
   3663 
   3664 void createTestsForAllStages (const std::string&			name,
   3665 							  const RGBA					(&inputColors)[4],
   3666 							  const RGBA					(&outputColors)[4],
   3667 							  const map<string, string>&	testCodeFragments,
   3668 							  const vector<deInt32>&		specConstants,
   3669 							  const PushConstants&			pushConstants,
   3670 							  const GraphicsResources&		resources,
   3671 							  const GraphicsInterfaces&		interfaces,
   3672 							  const vector<string>&			extensions,
   3673 							  const vector<string>&			features,
   3674 							  VulkanFeatures				vulkanFeatures,
   3675 							  tcu::TestCaseGroup*			tests,
   3676 							  const qpTestResult			failResult,
   3677 							  const string&					failMessageTemplate)
   3678 {
   3679 	const ShaderElement		vertFragPipelineStages[]		=
   3680 	{
   3681 		ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
   3682 		ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
   3683 	};
   3684 
   3685 	const ShaderElement		tessPipelineStages[]			=
   3686 	{
   3687 		ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
   3688 		ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
   3689 		ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
   3690 		ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
   3691 	};
   3692 
   3693 	const ShaderElement		geomPipelineStages[]				=
   3694 	{
   3695 		ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
   3696 		ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT),
   3697 		ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
   3698 	};
   3699 
   3700 	StageToSpecConstantMap	specConstantMap;
   3701 
   3702 	specConstantMap[VK_SHADER_STAGE_VERTEX_BIT] = specConstants;
   3703 	addFunctionCaseWithPrograms<InstanceContext>(
   3704 			tests, name + "_vert", "", addShaderCodeCustomVertex, runAndVerifyDefaultPipeline,
   3705 			createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments,
   3706 				specConstantMap, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, vk::VK_SHADER_STAGE_VERTEX_BIT, failResult, failMessageTemplate));
   3707 
   3708 	specConstantMap.clear();
   3709 	specConstantMap[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] = specConstants;
   3710 	addFunctionCaseWithPrograms<InstanceContext>(
   3711 			tests, name + "_tessc", "", addShaderCodeCustomTessControl, runAndVerifyDefaultPipeline,
   3712 			createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments,
   3713 				specConstantMap, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, failResult, failMessageTemplate));
   3714 
   3715 	specConstantMap.clear();
   3716 	specConstantMap[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = specConstants;
   3717 	addFunctionCaseWithPrograms<InstanceContext>(
   3718 			tests, name + "_tesse", "", addShaderCodeCustomTessEval, runAndVerifyDefaultPipeline,
   3719 			createInstanceContext(tessPipelineStages, inputColors, outputColors, testCodeFragments,
   3720 				specConstantMap, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, failResult, failMessageTemplate));
   3721 
   3722 	specConstantMap.clear();
   3723 	specConstantMap[VK_SHADER_STAGE_GEOMETRY_BIT] = specConstants;
   3724 	addFunctionCaseWithPrograms<InstanceContext>(
   3725 			tests, name + "_geom", "", addShaderCodeCustomGeometry, runAndVerifyDefaultPipeline,
   3726 			createInstanceContext(geomPipelineStages, inputColors, outputColors, testCodeFragments,
   3727 				specConstantMap, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, vk::VK_SHADER_STAGE_GEOMETRY_BIT, failResult, failMessageTemplate));
   3728 
   3729 	specConstantMap.clear();
   3730 	specConstantMap[VK_SHADER_STAGE_FRAGMENT_BIT] = specConstants;
   3731 	addFunctionCaseWithPrograms<InstanceContext>(
   3732 			tests, name + "_frag", "", addShaderCodeCustomFragment, runAndVerifyDefaultPipeline,
   3733 			createInstanceContext(vertFragPipelineStages, inputColors, outputColors, testCodeFragments,
   3734 				specConstantMap, pushConstants, resources, interfaces, extensions, features, vulkanFeatures, vk::VK_SHADER_STAGE_FRAGMENT_BIT, failResult, failMessageTemplate));
   3735 }
   3736 
   3737 void addTessCtrlTest(tcu::TestCaseGroup* group, const char* name, const map<string, string>& fragments)
   3738 {
   3739 	RGBA defaultColors[4];
   3740 	getDefaultColors(defaultColors);
   3741 	const ShaderElement pipelineStages[] =
   3742 	{
   3743 		ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT),
   3744 		ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT),
   3745 		ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT),
   3746 		ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT),
   3747 	};
   3748 
   3749 	addFunctionCaseWithPrograms<InstanceContext>(
   3750 			group, name, "", addShaderCodeCustomTessControl,
   3751 			runAndVerifyDefaultPipeline, createInstanceContext(
   3752 				pipelineStages, defaultColors, defaultColors, fragments,
   3753 				StageToSpecConstantMap(), PushConstants(), GraphicsResources(),
   3754 				GraphicsInterfaces(), vector<string>(), vector<string>(),
   3755 				VulkanFeatures(), vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
   3756 }
   3757 
   3758 } // SpirVAssembly
   3759 } // vkt
   3760