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