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