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