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