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