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) == 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(Context & context,const DeviceInterface & vk,const VkDevice & device,const VkQueue & queue,VkCommandPool cmdPool,VkCommandBuffer cmdBuffer,VkBuffer buffer,VkImage image,VkImageAspectFlags aspect)2946 void copyBufferToImage (Context& context, const DeviceInterface& vk, const VkDevice& device, const VkQueue& queue, VkCommandPool cmdPool, 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 context.resetCommandPoolForVKSC(device, cmdPool);
2972 }
2973
getImageAspectFlags(VkFormat format)2974 VkImageAspectFlags getImageAspectFlags (VkFormat format)
2975 {
2976 const tcu::TextureFormat::ChannelOrder channelOrder = vk::mapVkFormat(format).order;
2977 VkImageAspectFlags aspectFlags = (VkImageAspectFlags)0u;
2978
2979 if (tcu::hasDepthComponent(channelOrder))
2980 aspectFlags |= VK_IMAGE_ASPECT_DEPTH_BIT;
2981
2982 if (tcu::hasStencilComponent(channelOrder))
2983 aspectFlags |= VK_IMAGE_ASPECT_STENCIL_BIT;
2984
2985 if (!aspectFlags)
2986 aspectFlags |= VK_IMAGE_ASPECT_COLOR_BIT;
2987
2988 return aspectFlags;
2989 }
2990
runAndVerifyUnusedVariablePipeline(Context & context,UnusedVariableContext unusedVariableContext)2991 TestStatus runAndVerifyUnusedVariablePipeline (Context &context, UnusedVariableContext unusedVariableContext)
2992 {
2993 return runAndVerifyDefaultPipeline(context, unusedVariableContext.instanceContext);
2994 }
2995
runAndVerifyDefaultPipeline(Context & context,InstanceContext instance)2996 TestStatus runAndVerifyDefaultPipeline (Context& context, InstanceContext instance)
2997 {
2998 if (getMinRequiredVulkanVersion(instance.resources.spirvVersion) > context.getUsedApiVersion())
2999 {
3000 TCU_THROW(NotSupportedError, string("Vulkan higher than or equal to " + getVulkanName(getMinRequiredVulkanVersion(instance.resources.spirvVersion)) + " is required for this test to run").c_str());
3001 }
3002
3003 const DeviceInterface& vk = context.getDeviceInterface();
3004 const InstanceInterface& vkInstance = context.getInstanceInterface();
3005 const VkPhysicalDevice vkPhysicalDevice = context.getPhysicalDevice();
3006 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex();
3007 const VkQueue queue = context.getUniversalQueue();
3008 const VkDevice& device = context.getDevice();
3009 Allocator& allocator = context.getDefaultAllocator();
3010 vector<ModuleHandleSp> modules;
3011 map<VkShaderStageFlagBits, VkShaderModule> moduleByStage;
3012 const deUint32 fullRenderSize = 256;
3013 const deUint32 quarterRenderSize = 64;
3014 const tcu::UVec2 renderSize (fullRenderSize, fullRenderSize);
3015 const int testSpecificSeed = 31354125;
3016 const int seed = context.getTestContext().getCommandLine().getBaseSeed() ^ testSpecificSeed;
3017 bool supportsGeometry = false;
3018 bool supportsTessellation = false;
3019 bool hasGeometry = false;
3020 bool hasTessellation = false;
3021 const bool hasPushConstants = !instance.pushConstants.empty();
3022 const deUint32 numInResources = static_cast<deUint32>(instance.resources.inputs.size());
3023 const deUint32 numOutResources = static_cast<deUint32>(instance.resources.outputs.size());
3024 const deUint32 numResources = numInResources + numOutResources;
3025 const bool needInterface = !instance.interfaces.empty();
3026 const VkPhysicalDeviceFeatures& features = context.getDeviceFeatures();
3027 const Vec4 defaulClearColor (0.125f, 0.25f, 0.75f, 1.0f);
3028 bool splitRenderArea = instance.splitRenderArea;
3029
3030 const deUint32 renderDimension = splitRenderArea ? quarterRenderSize : fullRenderSize;
3031 const int numRenderSegments = splitRenderArea ? 4 : 1;
3032
3033 supportsGeometry = features.geometryShader == VK_TRUE;
3034 supportsTessellation = features.tessellationShader == VK_TRUE;
3035 hasGeometry = (instance.requiredStages & VK_SHADER_STAGE_GEOMETRY_BIT);
3036 hasTessellation = (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) ||
3037 (instance.requiredStages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
3038
3039 if (hasGeometry && !supportsGeometry)
3040 {
3041 TCU_THROW(NotSupportedError, "Geometry not supported");
3042 }
3043
3044 if (hasTessellation && !supportsTessellation)
3045 {
3046 TCU_THROW(NotSupportedError, "Tessellation not supported");
3047 }
3048
3049 // Check all required extensions are supported
3050 for (std::vector<std::string>::const_iterator i = instance.requiredDeviceExtensions.begin(); i != instance.requiredDeviceExtensions.end(); ++i)
3051 {
3052 if (!de::contains(context.getDeviceExtensions().begin(), context.getDeviceExtensions().end(), *i))
3053 TCU_THROW(NotSupportedError, (std::string("Extension not supported: ") + *i).c_str());
3054 }
3055
3056 #ifndef CTS_USES_VULKANSC
3057 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
3058 !context.getPortabilitySubsetFeatures().mutableComparisonSamplers)
3059 {
3060 // In portability when mutableComparisonSamplers is false then
3061 // VkSamplerCreateInfo can't have compareEnable set to true
3062 for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
3063 {
3064 const Resource& resource = instance.resources.inputs[inputNdx];
3065 const bool hasSampler = (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
3066 (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLER) ||
3067 (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3068 if (hasSampler &&
3069 tcu::hasDepthComponent(vk::mapVkFormat(instance.resources.inputFormat).order))
3070 {
3071 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: mutableComparisonSamplers are not supported by this implementation");
3072 }
3073 }
3074 }
3075 #endif // CTS_USES_VULKANSC
3076
3077 {
3078 VulkanFeatures localRequired = instance.requestedFeatures;
3079
3080 const VkShaderStageFlags vertexPipelineStoresAndAtomicsAffected = vk::VK_SHADER_STAGE_VERTEX_BIT
3081 | vk::VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT
3082 | vk::VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT
3083 | vk::VK_SHADER_STAGE_GEOMETRY_BIT;
3084
3085 // reset fragment stores and atomics feature requirement
3086 if ((localRequired.coreFeatures.fragmentStoresAndAtomics != DE_FALSE) &&
3087 (instance.customizedStages & vk::VK_SHADER_STAGE_FRAGMENT_BIT) == 0)
3088 {
3089 localRequired.coreFeatures.fragmentStoresAndAtomics = DE_FALSE;
3090 }
3091
3092 // reset vertex pipeline stores and atomics feature requirement
3093 if (localRequired.coreFeatures.vertexPipelineStoresAndAtomics != DE_FALSE &&
3094 (instance.customizedStages & vertexPipelineStoresAndAtomicsAffected) == 0)
3095 {
3096 localRequired.coreFeatures.vertexPipelineStoresAndAtomics = DE_FALSE;
3097 }
3098
3099 const char* unsupportedFeature = DE_NULL;
3100 if (!isVulkanFeaturesSupported(context, localRequired, &unsupportedFeature))
3101 TCU_THROW(NotSupportedError, std::string("At least following requested feature not supported: ") + unsupportedFeature);
3102 }
3103
3104 // Check Interface Input/Output formats are supported
3105 if (needInterface)
3106 {
3107 VkFormatProperties formatProperties;
3108 vkInstance.getPhysicalDeviceFormatProperties(vkPhysicalDevice, instance.interfaces.getInputType().getVkFormat(), &formatProperties);
3109 if ((formatProperties.bufferFeatures & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) == 0)
3110 {
3111 std::string error = "Interface Input format (";
3112 const std::string formatName = getFormatName(instance.interfaces.getInputType().getVkFormat());
3113 error += formatName + ") not supported";
3114 TCU_THROW(NotSupportedError, error.c_str());
3115 }
3116
3117 vkInstance.getPhysicalDeviceFormatProperties(vkPhysicalDevice, instance.interfaces.getOutputType().getVkFormat(), &formatProperties);
3118 if (((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0) ||
3119 ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) == 0))
3120 {
3121 std::string error = "Interface Output format (";
3122 const std::string formatName = getFormatName(instance.interfaces.getInputType().getVkFormat());
3123 error += formatName + ") not supported";
3124 TCU_THROW(NotSupportedError, error.c_str());
3125 }
3126 }
3127
3128 de::Random(seed).shuffle(instance.inputColors, instance.inputColors+4);
3129 de::Random(seed).shuffle(instance.outputColors, instance.outputColors+4);
3130 const Vec4 vertexData[] =
3131 {
3132 // Upper left corner:
3133 Vec4(-1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), //1
3134 Vec4(-0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[0].toVec(), //2
3135 Vec4(-1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[0].toVec(), //3
3136
3137 // Upper right corner:
3138 Vec4(+0.5f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), //4
3139 Vec4(+1.0f, -1.0f, 0.0f, 1.0f), instance.inputColors[1].toVec(), //5
3140 Vec4(+1.0f, -0.5f, 0.0f, 1.0f), instance.inputColors[1].toVec(), //6
3141
3142 // Lower left corner:
3143 Vec4(-1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[2].toVec(), //7
3144 Vec4(-0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), //8
3145 Vec4(-1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[2].toVec(), //9
3146
3147 // Lower right corner:
3148 Vec4(+1.0f, +0.5f, 0.0f, 1.0f), instance.inputColors[3].toVec(), //10
3149 Vec4(+1.0f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(), //11
3150 Vec4(+0.5f, +1.0f, 0.0f, 1.0f), instance.inputColors[3].toVec(), //12
3151
3152 // The rest is used only renderFullSquare specified. Fills area already filled with clear color
3153 // Left 1
3154 Vec4(-1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor, //3
3155 Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor, //2
3156 Vec4(-1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor, //7
3157
3158 // Left 2
3159 Vec4(-1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor, //7
3160 Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor, //2
3161 Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor, //8
3162
3163 // Left-Center
3164 Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor, //8
3165 Vec4(-0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor, //2
3166 Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor, //4
3167
3168 // Right-Center
3169 Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor, //4
3170 Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor, //12
3171 Vec4(-0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor, //8
3172
3173 // Right 2
3174 Vec4(+0.5f, -1.0f, 0.0f, 1.0f), defaulClearColor, //4
3175 Vec4(+1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor, //6
3176 Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor, //12
3177
3178 // Right 1
3179 Vec4(+0.5f, +1.0f, 0.0f, 1.0f), defaulClearColor, //12
3180 Vec4(+1.0f, -0.5f, 0.0f, 1.0f), defaulClearColor, //6
3181 Vec4(+1.0f, +0.5f, 0.0f, 1.0f), defaulClearColor, //10
3182 };
3183
3184 const size_t singleVertexDataSize = 2 * sizeof(Vec4);
3185 const size_t vertexCount = instance.renderFullSquare ? sizeof(vertexData) / singleVertexDataSize : 4*3;
3186 const size_t vertexDataSize = vertexCount * singleVertexDataSize;
3187
3188 Move<VkBuffer> vertexInputBuffer;
3189 de::MovePtr<Allocation> vertexInputMemory;
3190 Move<VkBuffer> fragOutputBuffer;
3191 de::MovePtr<Allocation> fragOutputMemory;
3192 Move<VkImage> fragOutputImage;
3193 de::MovePtr<Allocation> fragOutputImageMemory;
3194 Move<VkImageView> fragOutputImageView;
3195
3196 const VkBufferCreateInfo vertexBufferParams =
3197 {
3198 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
3199 DE_NULL, // const void* pNext;
3200 0u, // VkBufferCreateFlags flags;
3201 (VkDeviceSize)vertexDataSize, // VkDeviceSize size;
3202 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
3203 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
3204 1u, // deUint32 queueFamilyCount;
3205 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
3206 };
3207 const Unique<VkBuffer> vertexBuffer (createBuffer(vk, device, &vertexBufferParams));
3208 const UniquePtr<Allocation> vertexBufferMemory (allocator.allocate(getBufferMemoryRequirements(vk, device, *vertexBuffer), MemoryRequirement::HostVisible));
3209
3210 VK_CHECK(vk.bindBufferMemory(device, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
3211
3212 const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32)*renderSize.x()*renderSize.y());
3213 const VkBufferCreateInfo readImageBufferParams =
3214 {
3215 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
3216 DE_NULL, // const void* pNext;
3217 0u, // VkBufferCreateFlags flags;
3218 imageSizeBytes, // VkDeviceSize size;
3219 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
3220 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
3221 1u, // deUint32 queueFamilyCount;
3222 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
3223 };
3224 const Unique<VkBuffer> readImageBuffer (createBuffer(vk, device, &readImageBufferParams));
3225 const UniquePtr<Allocation> readImageBufferMemory (allocator.allocate(getBufferMemoryRequirements(vk, device, *readImageBuffer), MemoryRequirement::HostVisible));
3226
3227 VK_CHECK(vk.bindBufferMemory(device, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
3228
3229 VkImageCreateInfo imageParams =
3230 {
3231 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
3232 DE_NULL, // const void* pNext;
3233 0u, // VkImageCreateFlags flags;
3234 VK_IMAGE_TYPE_2D, // VkImageType imageType;
3235 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
3236 { renderSize.x(), renderSize.y(), 1 }, // VkExtent3D extent;
3237 1u, // deUint32 mipLevels;
3238 1u, // deUint32 arraySize;
3239 VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
3240 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
3241 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
3242 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
3243 1u, // deUint32 queueFamilyCount;
3244 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
3245 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
3246 };
3247
3248 const Unique<VkImage> image (createImage(vk, device, &imageParams));
3249 const UniquePtr<Allocation> imageMemory (allocator.allocate(getImageMemoryRequirements(vk, device, *image), MemoryRequirement::Any));
3250
3251 VK_CHECK(vk.bindImageMemory(device, *image, imageMemory->getMemory(), imageMemory->getOffset()));
3252
3253 if (needInterface)
3254 {
3255 // The pipeline renders four triangles, each with three vertexes.
3256 // Test instantialization only provides four data points, each
3257 // for one triangle. So we need allocate space of three times of
3258 // input buffer's size.
3259 vector<deUint8> inputBufferBytes;
3260 instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
3261
3262 const deUint32 inputNumBytes = deUint32(inputBufferBytes.size() * 3);
3263 // Create an additional buffer and backing memory for one input variable.
3264 const VkBufferCreateInfo vertexInputParams =
3265 {
3266 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
3267 DE_NULL, // const void* pNext;
3268 0u, // VkBufferCreateFlags flags;
3269 inputNumBytes, // VkDeviceSize size;
3270 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
3271 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
3272 1u, // deUint32 queueFamilyCount;
3273 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
3274 };
3275
3276 vertexInputBuffer = createBuffer(vk, device, &vertexInputParams);
3277 vertexInputMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *vertexInputBuffer), MemoryRequirement::HostVisible);
3278 VK_CHECK(vk.bindBufferMemory(device, *vertexInputBuffer, vertexInputMemory->getMemory(), vertexInputMemory->getOffset()));
3279
3280 // Create an additional buffer and backing memory for an output variable.
3281 const VkDeviceSize fragOutputImgSize = (VkDeviceSize)(instance.interfaces.getOutputType().getNumBytes() * renderSize.x() * renderSize.y());
3282 const VkBufferCreateInfo fragOutputParams =
3283 {
3284 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
3285 DE_NULL, // const void* pNext;
3286 0u, // VkBufferCreateFlags flags;
3287 fragOutputImgSize, // VkDeviceSize size;
3288 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // VkBufferUsageFlags usage;
3289 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
3290 1u, // deUint32 queueFamilyCount;
3291 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
3292 };
3293 fragOutputBuffer = createBuffer(vk, device, &fragOutputParams);
3294 fragOutputMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *fragOutputBuffer), MemoryRequirement::HostVisible);
3295 VK_CHECK(vk.bindBufferMemory(device, *fragOutputBuffer, fragOutputMemory->getMemory(), fragOutputMemory->getOffset()));
3296
3297 // Create an additional image and backing memory for attachment.
3298 // Reuse the previous imageParams since we only need to change the image format.
3299 imageParams.format = instance.interfaces.getOutputType().getVkFormat();
3300
3301 // Check the usage bits on the given image format are supported.
3302 requireFormatUsageSupport(vkInstance, vkPhysicalDevice, imageParams.format, imageParams.tiling, imageParams.usage);
3303
3304 fragOutputImage = createImage(vk, device, &imageParams);
3305 fragOutputImageMemory = allocator.allocate(getImageMemoryRequirements(vk, device, *fragOutputImage), MemoryRequirement::Any);
3306
3307 VK_CHECK(vk.bindImageMemory(device, *fragOutputImage, fragOutputImageMemory->getMemory(), fragOutputImageMemory->getOffset()));
3308 }
3309
3310 vector<VkAttachmentDescription> colorAttDescs;
3311 vector<VkAttachmentReference> colorAttRefs;
3312 {
3313 const VkAttachmentDescription attDesc =
3314 {
3315 0u, // VkAttachmentDescriptionFlags flags;
3316 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
3317 VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
3318 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
3319 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
3320 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
3321 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
3322 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
3323 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
3324 };
3325 colorAttDescs.push_back(attDesc);
3326
3327 const VkAttachmentReference attRef =
3328 {
3329 0u, // deUint32 attachment;
3330 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
3331 };
3332 colorAttRefs.push_back(attRef);
3333 }
3334
3335 if (needInterface)
3336 {
3337 const VkAttachmentDescription attDesc =
3338 {
3339 0u, // VkAttachmentDescriptionFlags flags;
3340 instance.interfaces.getOutputType().getVkFormat(), // VkFormat format;
3341 VK_SAMPLE_COUNT_1_BIT, // deUint32 samples;
3342 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
3343 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
3344 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
3345 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
3346 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
3347 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
3348 };
3349 colorAttDescs.push_back(attDesc);
3350
3351 const VkAttachmentReference attRef =
3352 {
3353 1u, // deUint32 attachment;
3354 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
3355 };
3356 colorAttRefs.push_back(attRef);
3357 }
3358
3359 VkSubpassDescription subpassDesc =
3360 {
3361 0u, // VkSubpassDescriptionFlags flags;
3362 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
3363 0u, // deUint32 inputCount;
3364 DE_NULL, // const VkAttachmentReference* pInputAttachments;
3365 1u, // deUint32 colorCount;
3366 colorAttRefs.data(), // const VkAttachmentReference* pColorAttachments;
3367 DE_NULL, // const VkAttachmentReference* pResolveAttachments;
3368 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
3369 0u, // deUint32 preserveCount;
3370 DE_NULL, // const VkAttachmentReference* pPreserveAttachments;
3371
3372 };
3373 VkRenderPassCreateInfo renderPassParams =
3374 {
3375 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
3376 DE_NULL, // const void* pNext;
3377 (VkRenderPassCreateFlags)0,
3378 1u, // deUint32 attachmentCount;
3379 colorAttDescs.data(), // const VkAttachmentDescription* pAttachments;
3380 1u, // deUint32 subpassCount;
3381 &subpassDesc, // const VkSubpassDescription* pSubpasses;
3382 0u, // deUint32 dependencyCount;
3383 DE_NULL, // const VkSubpassDependency* pDependencies;
3384 };
3385
3386 if (needInterface)
3387 {
3388 subpassDesc.colorAttachmentCount += 1;
3389 renderPassParams.attachmentCount += 1;
3390 }
3391
3392 const Unique<VkRenderPass> renderPass (createRenderPass(vk, device, &renderPassParams));
3393
3394 const VkImageViewCreateInfo colorAttViewParams =
3395 {
3396 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
3397 DE_NULL, // const void* pNext;
3398 0u, // VkImageViewCreateFlags flags;
3399 *image, // VkImage image;
3400 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
3401 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
3402 {
3403 VK_COMPONENT_SWIZZLE_R,
3404 VK_COMPONENT_SWIZZLE_G,
3405 VK_COMPONENT_SWIZZLE_B,
3406 VK_COMPONENT_SWIZZLE_A
3407 }, // VkChannelMapping channels;
3408 {
3409 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
3410 0u, // deUint32 baseMipLevel;
3411 1u, // deUint32 mipLevels;
3412 0u, // deUint32 baseArrayLayer;
3413 1u, // deUint32 arraySize;
3414 }, // VkImageSubresourceRange subresourceRange;
3415 };
3416 const Unique<VkImageView> colorAttView (createImageView(vk, device, &colorAttViewParams));
3417 const VkImageAspectFlags inputImageAspect = getImageAspectFlags(instance.resources.inputFormat);
3418
3419 vector<VkImageView> attViews;
3420 attViews.push_back(*colorAttView);
3421
3422 // Handle resources requested by the test instantiation.
3423 // These variables should be placed out of the following if block to avoid deallocation after out of scope.
3424 vector<AllocationSp> inResourceMemories;
3425 vector<AllocationSp> outResourceMemories;
3426 vector<BufferHandleSp> inResourceBuffers;
3427 vector<BufferHandleSp> outResourceBuffers;
3428 vector<ImageHandleSp> inResourceImages;
3429 vector<ImageViewHandleSp> inResourceImageViews;
3430 vector<SamplerHandleSp> inResourceSamplers;
3431 Move<VkDescriptorPool> descriptorPool;
3432 Move<VkDescriptorSetLayout> setLayout;
3433 VkDescriptorSetLayout rawSetLayout = DE_NULL;
3434 VkDescriptorSet rawSet = DE_NULL;
3435
3436 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
3437
3438 // Command buffer
3439 const Unique<VkCommandBuffer> cmdBuf (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
3440
3441 if (numResources != 0)
3442 {
3443 vector<VkDescriptorSetLayoutBinding> setLayoutBindings;
3444 vector<VkDescriptorPoolSize> poolSizes;
3445
3446 setLayoutBindings.reserve(numResources);
3447 poolSizes.reserve(numResources);
3448
3449 // Process all input resources.
3450 for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
3451 {
3452 const Resource& resource = instance.resources.inputs[inputNdx];
3453
3454 const bool hasImage = (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
3455 (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
3456 (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3457
3458 const bool hasSampler = (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
3459 (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLER) ||
3460 (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3461
3462 // Resource is a buffer
3463 if (!hasImage && !hasSampler)
3464 {
3465 Move<VkBuffer> resourceBuffer = createBufferForResource(vk, device, resource, queueFamilyIndex);
3466 de::MovePtr<Allocation> resourceMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3467
3468 VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3469
3470 // Copy data to memory.
3471 {
3472 vector<deUint8> resourceBytes;
3473 resource.getBytes(resourceBytes);
3474
3475 deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
3476 flushAlloc(vk, device, *resourceMemory);
3477 }
3478
3479 inResourceMemories.push_back(AllocationSp(resourceMemory.release()));
3480 inResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
3481 }
3482 // Resource is an image
3483 else if (hasImage)
3484 {
3485 Move<VkBuffer> resourceBuffer = createBufferForResource(vk, device, resource, queueFamilyIndex);
3486 de::MovePtr<Allocation> resourceMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3487
3488 VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3489
3490 // Copy data to memory.
3491 {
3492 vector<deUint8> resourceBytes;
3493 resource.getBytes(resourceBytes);
3494
3495 deMemcpy(resourceMemory->getHostPtr(), &resourceBytes.front(), resourceBytes.size());
3496 flushAlloc(vk, device, *resourceMemory);
3497 }
3498
3499 Move<VkImage> resourceImage = createImageForResource(vk, device, resource, instance.resources.inputFormat, queueFamilyIndex);
3500 de::MovePtr<Allocation> resourceImageMemory = allocator.allocate(getImageMemoryRequirements(vk, device, *resourceImage), MemoryRequirement::Any);
3501
3502 VK_CHECK(vk.bindImageMemory(device, *resourceImage, resourceImageMemory->getMemory(), resourceImageMemory->getOffset()));
3503
3504 copyBufferToImage(context, vk, device, queue, *cmdPool, *cmdBuf, resourceBuffer.get(), resourceImage.get(), inputImageAspect);
3505
3506 inResourceMemories.push_back(AllocationSp(resourceImageMemory.release()));
3507 inResourceImages.push_back(ImageHandleSp(new ImageHandleUp(resourceImage)));
3508 }
3509
3510 // Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool.
3511 const VkDescriptorSetLayoutBinding binding =
3512 {
3513 inputNdx, // binding
3514 resource.getDescriptorType(), // descriptorType
3515 1u, // descriptorCount
3516 VK_SHADER_STAGE_ALL_GRAPHICS, // stageFlags
3517 DE_NULL, // pImmutableSamplers
3518 };
3519 setLayoutBindings.push_back(binding);
3520
3521 // Note: the following code doesn't check and unify descriptors of the same type.
3522 const VkDescriptorPoolSize poolSize =
3523 {
3524 resource.getDescriptorType(), // type
3525 1u, // descriptorCount
3526 };
3527 poolSizes.push_back(poolSize);
3528 }
3529
3530 // Process all output resources.
3531 for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
3532 {
3533 const Resource& resource = instance.resources.outputs[outputNdx];
3534 // Create buffer and allocate memory.
3535 Move<VkBuffer> resourceBuffer = createBufferForResource(vk, device, resource, queueFamilyIndex);
3536 de::MovePtr<Allocation> resourceMemory = allocator.allocate(getBufferMemoryRequirements(vk, device, *resourceBuffer), MemoryRequirement::HostVisible);
3537 vector<deUint8> resourceBytes;
3538
3539 VK_CHECK(vk.bindBufferMemory(device, *resourceBuffer, resourceMemory->getMemory(), resourceMemory->getOffset()));
3540
3541 // Fill memory with all ones.
3542 resource.getBytes(resourceBytes);
3543 deMemset((deUint8*)resourceMemory->getHostPtr(), 0xff, resourceBytes.size());
3544 flushAlloc(vk, device, *resourceMemory);
3545
3546 outResourceMemories.push_back(AllocationSp(resourceMemory.release()));
3547 outResourceBuffers.push_back(BufferHandleSp(new BufferHandleUp(resourceBuffer)));
3548
3549 // Prepare descriptor bindings and pool sizes for creating descriptor set layout and pool.
3550 const VkDescriptorSetLayoutBinding binding =
3551 {
3552 numInResources + outputNdx, // binding
3553 resource.getDescriptorType(), // descriptorType
3554 1u, // descriptorCount
3555 VK_SHADER_STAGE_ALL_GRAPHICS, // stageFlags
3556 DE_NULL, // pImmutableSamplers
3557 };
3558 setLayoutBindings.push_back(binding);
3559
3560 // Note: the following code doesn't check and unify descriptors of the same type.
3561 const VkDescriptorPoolSize poolSize =
3562 {
3563 resource.getDescriptorType(), // type
3564 1u, // descriptorCount
3565 };
3566 poolSizes.push_back(poolSize);
3567 }
3568
3569 // Create descriptor set layout, descriptor pool, and allocate descriptor set.
3570 const VkDescriptorSetLayoutCreateInfo setLayoutParams =
3571 {
3572 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
3573 DE_NULL, // pNext
3574 (VkDescriptorSetLayoutCreateFlags)0, // flags
3575 numResources, // bindingCount
3576 setLayoutBindings.data(), // pBindings
3577 };
3578 setLayout = createDescriptorSetLayout(vk, device, &setLayoutParams);
3579 rawSetLayout = *setLayout;
3580
3581 const VkDescriptorPoolCreateInfo poolParams =
3582 {
3583 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType
3584 DE_NULL, // pNext
3585 (VkDescriptorPoolCreateFlags)0, // flags
3586 1u, // maxSets
3587 numResources, // poolSizeCount
3588 poolSizes.data(), // pPoolSizes
3589 };
3590 descriptorPool = createDescriptorPool(vk, device, &poolParams);
3591
3592 const VkDescriptorSetAllocateInfo setAllocParams =
3593 {
3594 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
3595 DE_NULL, // pNext
3596 *descriptorPool, // descriptorPool
3597 1u, // descriptorSetCount
3598 &rawSetLayout, // pSetLayouts
3599 };
3600 VK_CHECK(vk.allocateDescriptorSets(device, &setAllocParams, &rawSet));
3601
3602 // Update descriptor set.
3603 vector<VkWriteDescriptorSet> writeSpecs;
3604 vector<VkDescriptorBufferInfo> dBufferInfos;
3605 vector<VkDescriptorImageInfo> dImageInfos;
3606
3607 writeSpecs.reserve(numResources);
3608 dBufferInfos.reserve(numResources);
3609 dImageInfos.reserve(numResources);
3610
3611 deUint32 imgResourceNdx = 0u;
3612 deUint32 bufResourceNdx = 0u;
3613
3614 for (deUint32 inputNdx = 0; inputNdx < numInResources; ++inputNdx)
3615 {
3616 const Resource& resource = instance.resources.inputs[inputNdx];
3617
3618 const bool hasImage = (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
3619 (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
3620 (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3621
3622 const bool hasSampler = (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
3623 (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_SAMPLER) ||
3624 (resource.getDescriptorType() == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
3625
3626 // Create image view and sampler
3627 if (hasImage || hasSampler)
3628 {
3629 if (resource.getDescriptorType() != VK_DESCRIPTOR_TYPE_SAMPLER)
3630 {
3631 const VkImageViewCreateInfo imgViewParams =
3632 {
3633 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
3634 DE_NULL, // const void* pNext;
3635 0u, // VkImageViewCreateFlags flags;
3636 **inResourceImages[imgResourceNdx++], // VkImage image;
3637 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
3638 instance.resources.inputFormat, // VkFormat format;
3639 {
3640 VK_COMPONENT_SWIZZLE_R,
3641 VK_COMPONENT_SWIZZLE_G,
3642 VK_COMPONENT_SWIZZLE_B,
3643 VK_COMPONENT_SWIZZLE_A
3644 }, // VkComponentMapping channels;
3645 {
3646 inputImageAspect, // VkImageAspectFlags aspectMask;
3647 0u, // deUint32 baseMipLevel;
3648 1u, // deUint32 mipLevels;
3649 0u, // deUint32 baseArrayLayer;
3650 1u, // deUint32 arraySize;
3651 }, // VkImageSubresourceRange subresourceRange;
3652 };
3653
3654 Move<VkImageView> imgView (createImageView(vk, device, &imgViewParams));
3655 inResourceImageViews.push_back(ImageViewHandleSp(new ImageViewHandleUp(imgView)));
3656 }
3657
3658 if (hasSampler)
3659 {
3660 const bool hasDepthComponent = tcu::hasDepthComponent(vk::mapVkFormat(instance.resources.inputFormat).order);
3661 const VkSamplerCreateInfo samplerParams
3662 {
3663 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
3664 DE_NULL, // const void* pNext;
3665 0, // VkSamplerCreateFlags flags;
3666 VK_FILTER_NEAREST, // VkFilter magFilter:
3667 VK_FILTER_NEAREST, // VkFilter minFilter;
3668 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode;
3669 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU;
3670 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV;
3671 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW;
3672 0.0f, // float mipLodBias;
3673 VK_FALSE, // VkBool32 anistoropyEnable;
3674 1.0f, // float maxAnisotropy;
3675 (hasDepthComponent) ? VK_TRUE : VK_FALSE, // VkBool32 compareEnable;
3676 VK_COMPARE_OP_LESS, // VkCompareOp compareOp;
3677 0.0f, // float minLod;
3678 0.0f, // float maxLod;
3679 VK_BORDER_COLOR_INT_OPAQUE_BLACK, // VkBorderColor borderColor;
3680 VK_FALSE // VkBool32 unnormalizedCoordinates;
3681 };
3682
3683 Move<VkSampler> sampler (createSampler(vk, device, &samplerParams));
3684 inResourceSamplers.push_back(SamplerHandleSp(new SamplerHandleUp(sampler)));
3685 }
3686 }
3687
3688 // Create descriptor buffer and image infos
3689 switch (resource.getDescriptorType())
3690 {
3691 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
3692 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
3693 {
3694 const VkDescriptorBufferInfo bufInfo =
3695 {
3696 **inResourceBuffers[bufResourceNdx++], // buffer
3697 0, // offset
3698 VK_WHOLE_SIZE, // size
3699 };
3700 dBufferInfos.push_back(bufInfo);
3701 break;
3702 }
3703 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
3704 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
3705 {
3706 const VkDescriptorImageInfo imgInfo =
3707 {
3708 DE_NULL, // sampler
3709 **inResourceImageViews.back(), // imageView
3710 VK_IMAGE_LAYOUT_GENERAL // imageLayout
3711 };
3712 dImageInfos.push_back(imgInfo);
3713 break;
3714 }
3715 case VK_DESCRIPTOR_TYPE_SAMPLER:
3716 {
3717 const VkDescriptorImageInfo imgInfo =
3718 {
3719 **inResourceSamplers.back(), // sampler
3720 DE_NULL, // imageView
3721 VK_IMAGE_LAYOUT_GENERAL // imageLayout
3722 };
3723 dImageInfos.push_back(imgInfo);
3724 break;
3725 }
3726 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
3727 {
3728
3729 const VkDescriptorImageInfo imgInfo =
3730 {
3731 **inResourceSamplers.back(), // sampler
3732 **inResourceImageViews.back(), // imageView
3733 VK_IMAGE_LAYOUT_GENERAL // imageLayout
3734 };
3735 dImageInfos.push_back(imgInfo);
3736 break;
3737 }
3738 default:
3739 DE_FATAL("Not implemented");
3740 }
3741
3742 const VkWriteDescriptorSet writeSpec = {
3743 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
3744 DE_NULL, // pNext
3745 rawSet, // dstSet
3746 inputNdx, // binding
3747 0, // dstArrayElement
3748 1u, // descriptorCount
3749 instance.resources.inputs[inputNdx].getDescriptorType(), // descriptorType
3750 ( (hasImage | hasSampler) ? &dImageInfos.back() : DE_NULL), // pImageInfo
3751 (!(hasImage | hasSampler) ? &dBufferInfos.back() : DE_NULL), // pBufferInfo
3752 DE_NULL, // pTexelBufferView
3753 };
3754 writeSpecs.push_back(writeSpec);
3755 }
3756
3757 for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
3758 {
3759 const VkDescriptorBufferInfo bufInfo =
3760 {
3761 **outResourceBuffers[outputNdx], // buffer
3762 0, // offset
3763 VK_WHOLE_SIZE, // size
3764 };
3765 dBufferInfos.push_back(bufInfo);
3766
3767 const VkWriteDescriptorSet writeSpec = {
3768 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // sType
3769 DE_NULL, // pNext
3770 rawSet, // dstSet
3771 numInResources + outputNdx, // binding
3772 0, // dstArrayElement
3773 1u, // descriptorCount
3774 instance.resources.outputs[outputNdx].getDescriptorType(), // descriptorType
3775 DE_NULL, // pImageInfo
3776 &dBufferInfos.back(), // pBufferInfo
3777 DE_NULL, // pTexelBufferView
3778 };
3779 writeSpecs.push_back(writeSpec);
3780 }
3781 vk.updateDescriptorSets(device, numResources, writeSpecs.data(), 0, DE_NULL);
3782 }
3783
3784 // Pipeline layout
3785 VkPipelineLayoutCreateInfo pipelineLayoutParams =
3786 {
3787 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
3788 DE_NULL, // const void* pNext;
3789 (VkPipelineLayoutCreateFlags)0,
3790 0u, // deUint32 descriptorSetCount;
3791 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
3792 0u, // deUint32 pushConstantRangeCount;
3793 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
3794 };
3795
3796 VkPushConstantRange pushConstantRange =
3797 {
3798 VK_SHADER_STAGE_ALL_GRAPHICS, // VkShaderStageFlags stageFlags;
3799 0, // uint32_t offset;
3800 0, // uint32_t size;
3801 };
3802 if (hasPushConstants)
3803 {
3804 vector<deUint8> pushConstantsBytes;
3805 instance.pushConstants.getBuffer()->getBytes(pushConstantsBytes);
3806
3807 pushConstantRange.size = static_cast<deUint32>(pushConstantsBytes.size());
3808 pipelineLayoutParams.pushConstantRangeCount = 1;
3809 pipelineLayoutParams.pPushConstantRanges = &pushConstantRange;
3810 }
3811 if (numResources != 0)
3812 {
3813 // Update pipeline layout with the descriptor set layout.
3814 pipelineLayoutParams.setLayoutCount = 1;
3815 pipelineLayoutParams.pSetLayouts = &rawSetLayout;
3816 }
3817 const Unique<VkPipelineLayout> pipelineLayout (createPipelineLayout(vk, device, &pipelineLayoutParams));
3818
3819 // Pipeline
3820 vector<VkPipelineShaderStageCreateInfo> shaderStageParams;
3821 // We need these vectors to make sure that information about specialization constants for each stage can outlive createGraphicsPipeline().
3822 vector<vector<VkSpecializationMapEntry> > specConstantEntries;
3823 vector<VkSpecializationInfo> specializationInfos;
3824 if (DE_NULL != instance.resources.verifyBinary)
3825 {
3826 std::string shaderName;
3827 switch(instance.customizedStages)
3828 {
3829 case VK_SHADER_STAGE_VERTEX_BIT:
3830 shaderName= "vert";
3831 break;
3832 case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
3833 shaderName= "tessc";
3834 break;
3835 case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
3836 shaderName= "tesse";
3837 break;
3838 case VK_SHADER_STAGE_GEOMETRY_BIT:
3839 shaderName= "geom";
3840 break;
3841 case VK_SHADER_STAGE_FRAGMENT_BIT:
3842 shaderName= "frag";
3843 break;
3844 default:
3845 DE_ASSERT(0);
3846 break;
3847 }
3848 const ProgramBinary& binary = context.getBinaryCollection().get(shaderName);
3849 if (!instance.resources.verifyBinary(binary))
3850 return tcu::TestStatus::fail("Binary verification of SPIR-V in the test failed");
3851
3852 }
3853 createPipelineShaderStages(vk, device, instance, context, modules, shaderStageParams);
3854
3855 // And we don't want the reallocation of these vectors to invalidate pointers pointing to their contents.
3856 specConstantEntries.reserve(shaderStageParams.size());
3857 specializationInfos.reserve(shaderStageParams.size());
3858
3859 // Patch the specialization info field in PipelineShaderStageCreateInfos.
3860 for (vector<VkPipelineShaderStageCreateInfo>::iterator stageInfo = shaderStageParams.begin(); stageInfo != shaderStageParams.end(); ++stageInfo)
3861 {
3862 const StageToSpecConstantMap::const_iterator stageIt = instance.specConstants.find(stageInfo->stage);
3863
3864 if (stageIt != instance.specConstants.end())
3865 {
3866 const size_t numSpecConstants = stageIt->second.getValuesCount();
3867 vector<VkSpecializationMapEntry> entries;
3868 VkSpecializationInfo specInfo;
3869 size_t offset = 0;
3870
3871 entries.resize(numSpecConstants);
3872
3873 // Constant IDs are numbered sequentially starting from 0.
3874 for (size_t ndx = 0; ndx < numSpecConstants; ++ndx)
3875 {
3876 const size_t valueSize = stageIt->second.getValueSize(ndx);
3877
3878 entries[ndx].constantID = (deUint32)ndx;
3879 entries[ndx].offset = static_cast<deUint32>(offset);
3880 entries[ndx].size = valueSize;
3881
3882 offset += valueSize;
3883 }
3884
3885 specConstantEntries.push_back(entries);
3886
3887 specInfo.mapEntryCount = (deUint32)numSpecConstants;
3888 specInfo.pMapEntries = specConstantEntries.back().data();
3889 specInfo.dataSize = offset;
3890 specInfo.pData = stageIt->second.getValuesBuffer();
3891 specializationInfos.push_back(specInfo);
3892
3893 stageInfo->pSpecializationInfo = &specializationInfos.back();
3894 }
3895 }
3896 const VkPipelineDepthStencilStateCreateInfo depthStencilParams =
3897 {
3898 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
3899 DE_NULL, // const void* pNext;
3900 (VkPipelineDepthStencilStateCreateFlags)0,
3901 DE_FALSE, // deUint32 depthTestEnable;
3902 DE_FALSE, // deUint32 depthWriteEnable;
3903 VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp;
3904 DE_FALSE, // deUint32 depthBoundsTestEnable;
3905 DE_FALSE, // deUint32 stencilTestEnable;
3906 {
3907 VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp;
3908 VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp;
3909 VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp;
3910 VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp;
3911 0u, // deUint32 stencilCompareMask;
3912 0u, // deUint32 stencilWriteMask;
3913 0u, // deUint32 stencilReference;
3914 }, // VkStencilOpState front;
3915 {
3916 VK_STENCIL_OP_KEEP, // VkStencilOp stencilFailOp;
3917 VK_STENCIL_OP_KEEP, // VkStencilOp stencilPassOp;
3918 VK_STENCIL_OP_KEEP, // VkStencilOp stencilDepthFailOp;
3919 VK_COMPARE_OP_ALWAYS, // VkCompareOp stencilCompareOp;
3920 0u, // deUint32 stencilCompareMask;
3921 0u, // deUint32 stencilWriteMask;
3922 0u, // deUint32 stencilReference;
3923 }, // VkStencilOpState back;
3924 -1.0f, // float minDepthBounds;
3925 +1.0f, // float maxDepthBounds;
3926 };
3927 const VkViewport viewport0 = makeViewport(renderSize);
3928 const VkRect2D scissor0 = makeRect2D(0u, 0u);
3929 const VkPipelineViewportStateCreateInfo viewportParams =
3930 {
3931 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
3932 DE_NULL, // const void* pNext;
3933 (VkPipelineViewportStateCreateFlags)0,
3934 1u, // deUint32 viewportCount;
3935 &viewport0,
3936 1u,
3937 &scissor0
3938 };
3939 const VkSampleMask sampleMask = ~0u;
3940 const VkPipelineMultisampleStateCreateInfo multisampleParams =
3941 {
3942 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
3943 DE_NULL, // const void* pNext;
3944 (VkPipelineMultisampleStateCreateFlags)0,
3945 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterSamples;
3946 DE_FALSE, // deUint32 sampleShadingEnable;
3947 0.0f, // float minSampleShading;
3948 &sampleMask, // const VkSampleMask* pSampleMask;
3949 DE_FALSE, // VkBool32 alphaToCoverageEnable;
3950 DE_FALSE, // VkBool32 alphaToOneEnable;
3951 };
3952 const VkPipelineRasterizationStateCreateInfo rasterParams =
3953 {
3954 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
3955 DE_NULL, // const void* pNext;
3956 (VkPipelineRasterizationStateCreateFlags)0,
3957 DE_FALSE, // deUint32 depthClampEnable;
3958 DE_FALSE, // deUint32 rasterizerDiscardEnable;
3959 VK_POLYGON_MODE_FILL, // VkFillMode fillMode;
3960 VK_CULL_MODE_NONE, // VkCullMode cullMode;
3961 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
3962 VK_FALSE, // VkBool32 depthBiasEnable;
3963 0.0f, // float depthBias;
3964 0.0f, // float depthBiasClamp;
3965 0.0f, // float slopeScaledDepthBias;
3966 1.0f, // float lineWidth;
3967 };
3968 const VkPrimitiveTopology topology = hasTessellation? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
3969 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyParams =
3970 {
3971 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
3972 DE_NULL, // const void* pNext;
3973 (VkPipelineInputAssemblyStateCreateFlags)0,
3974 topology, // VkPrimitiveTopology topology;
3975 DE_FALSE, // deUint32 primitiveRestartEnable;
3976 };
3977
3978 vector<VkVertexInputBindingDescription> vertexBindings;
3979 vector<VkVertexInputAttributeDescription> vertexAttribs;
3980
3981 const VkVertexInputBindingDescription vertexBinding0 =
3982 {
3983 0u, // deUint32 binding;
3984 deUint32(singleVertexDataSize), // deUint32 strideInBytes;
3985 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
3986 };
3987 vertexBindings.push_back(vertexBinding0);
3988
3989 {
3990 VkVertexInputAttributeDescription attr0 =
3991 {
3992 0u, // deUint32 location;
3993 0u, // deUint32 binding;
3994 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
3995 0u // deUint32 offsetInBytes;
3996 };
3997 vertexAttribs.push_back(attr0);
3998
3999 VkVertexInputAttributeDescription attr1 =
4000 {
4001 1u, // deUint32 location;
4002 0u, // deUint32 binding;
4003 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
4004 sizeof(Vec4), // deUint32 offsetInBytes;
4005 };
4006 vertexAttribs.push_back(attr1);
4007 }
4008
4009 // If the test instantiation has additional input/output interface variables, we need to create additional bindings.
4010 // Right now we only support one additional input varible for the vertex stage, and that will be bound to binding #1
4011 // with location #2.
4012 if (needInterface)
4013 {
4014 // Portability requires stride to be multiply of minVertexInputBindingStrideAlignment
4015 // this value is usually 4 and current tests meet this requirement but
4016 // if this changes in future then this limit should be verified in checkSupport
4017 const deUint32 stride = instance.interfaces.getInputType().getNumBytes();
4018 #ifndef CTS_USES_VULKANSC
4019 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
4020 ((stride % context.getPortabilitySubsetProperties().minVertexInputBindingStrideAlignment) != 0))
4021 {
4022 DE_FATAL("stride is not multiply of minVertexInputBindingStrideAlignment");
4023 }
4024 #endif // CTS_USES_VULKANSC
4025
4026 const VkVertexInputBindingDescription vertexBinding1 =
4027 {
4028 1u, // deUint32 binding;
4029 stride, // deUint32 strideInBytes;
4030 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate stepRate;
4031 };
4032 vertexBindings.push_back(vertexBinding1);
4033
4034 VkVertexInputAttributeDescription attr =
4035 {
4036 2u, // deUint32 location;
4037 1u, // deUint32 binding;
4038 instance.interfaces.getInputType().getVkFormat(), // VkFormat format;
4039 0, // deUint32 offsetInBytes;
4040 };
4041 vertexAttribs.push_back(attr);
4042 }
4043
4044 VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
4045 {
4046 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
4047 DE_NULL, // const void* pNext;
4048 (VkPipelineVertexInputStateCreateFlags)0,
4049 1u, // deUint32 bindingCount;
4050 vertexBindings.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
4051 2u, // deUint32 attributeCount;
4052 vertexAttribs.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
4053 };
4054
4055 if (needInterface)
4056 {
4057 vertexInputStateParams.vertexBindingDescriptionCount += 1;
4058 vertexInputStateParams.vertexAttributeDescriptionCount += 1;
4059 }
4060
4061 vector<VkPipelineColorBlendAttachmentState> attBlendStates;
4062 const VkPipelineColorBlendAttachmentState attBlendState =
4063 {
4064 DE_FALSE, // deUint32 blendEnable;
4065 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendColor;
4066 VK_BLEND_FACTOR_ZERO, // VkBlend destBlendColor;
4067 VK_BLEND_OP_ADD, // VkBlendOp blendOpColor;
4068 VK_BLEND_FACTOR_ONE, // VkBlend srcBlendAlpha;
4069 VK_BLEND_FACTOR_ZERO, // VkBlend destBlendAlpha;
4070 VK_BLEND_OP_ADD, // VkBlendOp blendOpAlpha;
4071 (VK_COLOR_COMPONENT_R_BIT|
4072 VK_COLOR_COMPONENT_G_BIT|
4073 VK_COLOR_COMPONENT_B_BIT|
4074 VK_COLOR_COMPONENT_A_BIT), // VkChannelFlags channelWriteMask;
4075 };
4076 attBlendStates.push_back(attBlendState);
4077
4078 if (needInterface)
4079 attBlendStates.push_back(attBlendState);
4080
4081 VkPipelineColorBlendStateCreateInfo blendParams =
4082 {
4083 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
4084 DE_NULL, // const void* pNext;
4085 (VkPipelineColorBlendStateCreateFlags)0,
4086 DE_FALSE, // VkBool32 logicOpEnable;
4087 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
4088 1u, // deUint32 attachmentCount;
4089 attBlendStates.data(), // const VkPipelineColorBlendAttachmentState* pAttachments;
4090 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConst[4];
4091 };
4092 if (needInterface)
4093 {
4094 blendParams.attachmentCount += 1;
4095 }
4096 const VkPipelineTessellationStateCreateInfo tessellationState =
4097 {
4098 VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
4099 DE_NULL,
4100 (VkPipelineTessellationStateCreateFlags)0,
4101 3u
4102 };
4103
4104 const VkDynamicState dynamicStates[] =
4105 {
4106 VK_DYNAMIC_STATE_SCISSOR
4107 };
4108
4109 const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo =
4110 {
4111 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // sType
4112 DE_NULL, // pNext
4113 0u, // flags
4114 DE_LENGTH_OF_ARRAY(dynamicStates), // dynamicStateCount
4115 dynamicStates // pDynamicStates
4116 };
4117
4118 const VkPipelineTessellationStateCreateInfo* tessellationInfo = hasTessellation ? &tessellationState: DE_NULL;
4119 const VkGraphicsPipelineCreateInfo pipelineParams =
4120 {
4121 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
4122 DE_NULL, // const void* pNext;
4123 0u, // VkPipelineCreateFlags flags;
4124 (deUint32)shaderStageParams.size(), // deUint32 stageCount;
4125 &shaderStageParams[0], // const VkPipelineShaderStageCreateInfo* pStages;
4126 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
4127 &inputAssemblyParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
4128 tessellationInfo, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
4129 &viewportParams, // const VkPipelineViewportStateCreateInfo* pViewportState;
4130 &rasterParams, // const VkPipelineRasterStateCreateInfo* pRasterState;
4131 &multisampleParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
4132 &depthStencilParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
4133 &blendParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
4134 &dynamicStateCreateInfo, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
4135 *pipelineLayout, // VkPipelineLayout layout;
4136 *renderPass, // VkRenderPass renderPass;
4137 0u, // deUint32 subpass;
4138 DE_NULL, // VkPipeline basePipelineHandle;
4139 0u, // deInt32 basePipelineIndex;
4140 };
4141
4142 const Unique<VkPipeline> pipeline (createGraphicsPipeline(vk, device, DE_NULL, &pipelineParams));
4143
4144 if (needInterface)
4145 {
4146 const VkImageViewCreateInfo fragOutputViewParams =
4147 {
4148 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
4149 DE_NULL, // const void* pNext;
4150 0u, // VkImageViewCreateFlags flags;
4151 *fragOutputImage, // VkImage image;
4152 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
4153 instance.interfaces.getOutputType().getVkFormat(), // VkFormat format;
4154 {
4155 VK_COMPONENT_SWIZZLE_R,
4156 VK_COMPONENT_SWIZZLE_G,
4157 VK_COMPONENT_SWIZZLE_B,
4158 VK_COMPONENT_SWIZZLE_A
4159 }, // VkChannelMapping channels;
4160 {
4161 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
4162 0u, // deUint32 baseMipLevel;
4163 1u, // deUint32 mipLevels;
4164 0u, // deUint32 baseArrayLayer;
4165 1u, // deUint32 arraySize;
4166 }, // VkImageSubresourceRange subresourceRange;
4167 };
4168 fragOutputImageView = createImageView(vk, device, &fragOutputViewParams);
4169 attViews.push_back(*fragOutputImageView);
4170 }
4171
4172 // Framebuffer
4173 VkFramebufferCreateInfo framebufferParams =
4174 {
4175 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
4176 DE_NULL, // const void* pNext;
4177 (VkFramebufferCreateFlags)0,
4178 *renderPass, // VkRenderPass renderPass;
4179 1u, // deUint32 attachmentCount;
4180 attViews.data(), // const VkImageView* pAttachments;
4181 (deUint32)renderSize.x(), // deUint32 width;
4182 (deUint32)renderSize.y(), // deUint32 height;
4183 1u, // deUint32 layers;
4184 };
4185
4186 if (needInterface)
4187 framebufferParams.attachmentCount += 1;
4188
4189 const Unique<VkFramebuffer> framebuffer (createFramebuffer(vk, device, &framebufferParams));
4190
4191 bool firstPass = true;
4192
4193 for (int x = 0; x < numRenderSegments; x++)
4194 {
4195 for (int y = 0; y < numRenderSegments; y++)
4196 {
4197 // Record commands
4198 beginCommandBuffer(vk, *cmdBuf);
4199
4200 if (firstPass)
4201 {
4202 const VkMemoryBarrier vertFlushBarrier =
4203 {
4204 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // VkStructureType sType;
4205 DE_NULL, // const void* pNext;
4206 VK_ACCESS_HOST_WRITE_BIT, // VkMemoryOutputFlags outputMask;
4207 VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkMemoryInputFlags inputMask;
4208 };
4209 vector<VkImageMemoryBarrier> colorAttBarriers;
4210
4211 VkImageMemoryBarrier imgBarrier =
4212 {
4213 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
4214 DE_NULL, // const void* pNext;
4215 0u, // VkMemoryOutputFlags outputMask;
4216 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryInputFlags inputMask;
4217 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
4218 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout;
4219 queueFamilyIndex, // deUint32 srcQueueFamilyIndex;
4220 queueFamilyIndex, // deUint32 destQueueFamilyIndex;
4221 *image, // VkImage image;
4222 {
4223 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
4224 0u, // deUint32 baseMipLevel;
4225 1u, // deUint32 mipLevels;
4226 0u, // deUint32 baseArraySlice;
4227 1u, // deUint32 arraySize;
4228 } // VkImageSubresourceRange subresourceRange;
4229 };
4230 colorAttBarriers.push_back(imgBarrier);
4231 if (needInterface)
4232 {
4233 imgBarrier.image = *fragOutputImage;
4234 colorAttBarriers.push_back(imgBarrier);
4235 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());
4236 }
4237 else
4238 {
4239 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());
4240 }
4241 }
4242
4243 {
4244 vector<VkClearValue> clearValue;
4245 clearValue.push_back(makeClearValueColorF32(defaulClearColor[0], defaulClearColor[1], defaulClearColor[2], defaulClearColor[3]));
4246 if (needInterface)
4247 {
4248 clearValue.push_back(makeClearValueColorU32(0, 0, 0, 0));
4249 }
4250
4251
4252 vk::VkRect2D scissor = makeRect2D(x * renderDimension, y * renderDimension, renderDimension, renderDimension);
4253 vk.cmdSetScissor(*cmdBuf, 0u, 1u, &scissor);
4254
4255 beginRenderPass(vk, *cmdBuf, *renderPass, *framebuffer, scissor, (deUint32)clearValue.size(), clearValue.data());
4256 }
4257
4258 vk.cmdBindPipeline(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
4259 {
4260 const VkDeviceSize bindingOffset = 0;
4261 vk.cmdBindVertexBuffers(*cmdBuf, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
4262 }
4263 if (needInterface)
4264 {
4265 const VkDeviceSize bindingOffset = 0;
4266 vk.cmdBindVertexBuffers(*cmdBuf, 1u, 1u, &vertexInputBuffer.get(), &bindingOffset);
4267 }
4268 if (hasPushConstants)
4269 {
4270 vector<deUint8> pushConstantsBytes;
4271 instance.pushConstants.getBuffer()->getBytes(pushConstantsBytes);
4272
4273 const deUint32 size = static_cast<deUint32>(pushConstantsBytes.size());
4274 const void* data = &pushConstantsBytes.front();
4275
4276 vk.cmdPushConstants(*cmdBuf, *pipelineLayout, VK_SHADER_STAGE_ALL_GRAPHICS, 0, size, data);
4277 }
4278 if (numResources != 0)
4279 {
4280 // Bind to set number 0.
4281 vk.cmdBindDescriptorSets(*cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0, 1, &rawSet, 0, DE_NULL);
4282 }
4283 vk.cmdDraw(*cmdBuf, deUint32(vertexCount), 1u /*run pipeline once*/, 0u /*first vertex*/, 0u /*first instanceIndex*/);
4284 endRenderPass(vk, *cmdBuf);
4285
4286 if (x == numRenderSegments - 1 && y == numRenderSegments - 1)
4287 {
4288 {
4289 vector<VkImageMemoryBarrier> renderFinishBarrier;
4290 VkImageMemoryBarrier imgBarrier =
4291 {
4292 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
4293 DE_NULL, // const void* pNext;
4294 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkMemoryOutputFlags outputMask;
4295 VK_ACCESS_TRANSFER_READ_BIT, // VkMemoryInputFlags inputMask;
4296 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout oldLayout;
4297 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
4298 queueFamilyIndex, // deUint32 srcQueueFamilyIndex;
4299 queueFamilyIndex, // deUint32 destQueueFamilyIndex;
4300 *image, // VkImage image;
4301 {
4302 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
4303 0u, // deUint32 baseMipLevel;
4304 1u, // deUint32 mipLevels;
4305 0u, // deUint32 baseArraySlice;
4306 1u, // deUint32 arraySize;
4307 } // VkImageSubresourceRange subresourceRange;
4308 };
4309 renderFinishBarrier.push_back(imgBarrier);
4310
4311 if (needInterface)
4312 {
4313 imgBarrier.image = *fragOutputImage;
4314 renderFinishBarrier.push_back(imgBarrier);
4315 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());
4316 }
4317 else
4318 {
4319 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());
4320 }
4321 }
4322
4323 {
4324 const VkBufferImageCopy copyParams =
4325 {
4326 (VkDeviceSize)0u, // VkDeviceSize bufferOffset;
4327 (deUint32)renderSize.x(), // deUint32 bufferRowLength;
4328 (deUint32)renderSize.y(), // deUint32 bufferImageHeight;
4329 {
4330 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspect aspect;
4331 0u, // deUint32 mipLevel;
4332 0u, // deUint32 arrayLayer;
4333 1u, // deUint32 arraySize;
4334 }, // VkImageSubresourceCopy imageSubresource;
4335 { 0u, 0u, 0u }, // VkOffset3D imageOffset;
4336 { renderSize.x(), renderSize.y(), 1u }
4337 };
4338 vk.cmdCopyImageToBuffer(*cmdBuf, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params);
4339
4340 if (needInterface)
4341 {
4342 vk.cmdCopyImageToBuffer(*cmdBuf, *fragOutputImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *fragOutputBuffer, 1u, ©Params);
4343 }
4344 }
4345
4346 {
4347 vector<VkBufferMemoryBarrier> cpFinishBarriers;
4348 VkBufferMemoryBarrier copyFinishBarrier =
4349 {
4350 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
4351 DE_NULL, // const void* pNext;
4352 VK_ACCESS_TRANSFER_WRITE_BIT, // VkMemoryOutputFlags outputMask;
4353 VK_ACCESS_HOST_READ_BIT, // VkMemoryInputFlags inputMask;
4354 queueFamilyIndex, // deUint32 srcQueueFamilyIndex;
4355 queueFamilyIndex, // deUint32 destQueueFamilyIndex;
4356 *readImageBuffer, // VkBuffer buffer;
4357 0u, // VkDeviceSize offset;
4358 imageSizeBytes // VkDeviceSize size;
4359 };
4360 cpFinishBarriers.push_back(copyFinishBarrier);
4361
4362 if (needInterface)
4363 {
4364 copyFinishBarrier.buffer = *fragOutputBuffer;
4365 copyFinishBarrier.size = VK_WHOLE_SIZE;
4366 cpFinishBarriers.push_back(copyFinishBarrier);
4367
4368 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);
4369 }
4370 else
4371 {
4372 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);
4373 }
4374 }
4375 }
4376
4377 endCommandBuffer(vk, *cmdBuf);
4378
4379 if (firstPass)
4380 {
4381 // Upload vertex data
4382 {
4383 void* vertexBufPtr = vertexBufferMemory->getHostPtr();
4384 deMemcpy(vertexBufPtr, &vertexData[0], vertexDataSize);
4385 flushAlloc(vk, device, *vertexBufferMemory);
4386 }
4387
4388 if (needInterface)
4389 {
4390 vector<deUint8> inputBufferBytes;
4391 instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
4392
4393 const deUint32 typNumBytes = instance.interfaces.getInputType().getNumBytes();
4394 const deUint32 bufNumBytes = static_cast<deUint32>(inputBufferBytes.size());
4395
4396 // Require that the test instantation provides four output values.
4397 DE_ASSERT(bufNumBytes == 4 * typNumBytes);
4398
4399 // We have four triangles. Because interpolation happens before executing the fragment shader,
4400 // we need to provide the same vertex attribute for the same triangle. That means, duplicate each
4401 // value three times for all four values.
4402
4403 const deUint8* provided = static_cast<const deUint8*>(&inputBufferBytes.front());
4404 vector<deUint8> data;
4405
4406 data.reserve(3 * bufNumBytes);
4407
4408 for (deUint32 offset = 0; offset < bufNumBytes; offset += typNumBytes)
4409 for (deUint32 vertexNdx = 0; vertexNdx < 3; ++vertexNdx)
4410 for (deUint32 byteNdx = 0; byteNdx < typNumBytes; ++byteNdx)
4411 data.push_back(provided[offset + byteNdx]);
4412
4413 deMemcpy(vertexInputMemory->getHostPtr(), data.data(), data.size());
4414
4415 flushAlloc(vk, device, *vertexInputMemory);
4416
4417 }
4418 firstPass = false;
4419 }
4420
4421 // Submit & wait for completion
4422 submitCommandsAndWait(vk, device, queue, cmdBuf.get());
4423 context.resetCommandPoolForVKSC(device, *cmdPool);
4424 }
4425 }
4426
4427 const void* imagePtr = readImageBufferMemory->getHostPtr();
4428 const tcu::ConstPixelBufferAccess pixelBuffer(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
4429 renderSize.x(), renderSize.y(), 1, imagePtr);
4430 // Log image
4431 invalidateAlloc(vk, device, *readImageBufferMemory);
4432 context.getTestContext().getLog() << TestLog::Image("Result", "Result", pixelBuffer);
4433
4434 if (needInterface)
4435 invalidateAlloc(vk, device, *fragOutputMemory);
4436
4437 // Make sure all output resources are ready.
4438 for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
4439 invalidateAlloc(vk, device, *outResourceMemories[outputNdx]);
4440
4441 const RGBA threshold(1, 1, 1, 1);
4442
4443 const RGBA upperLeft(pixelBuffer.getPixel(1, 1));
4444 if (!tcu::compareThreshold(upperLeft, instance.outputColors[0], threshold))
4445 return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper left corner mismatch"));
4446
4447 const RGBA upperRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, 1));
4448 if (!tcu::compareThreshold(upperRight, instance.outputColors[1], threshold))
4449 return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Upper right corner mismatch"));
4450
4451 const RGBA lowerLeft(pixelBuffer.getPixel(1, pixelBuffer.getHeight() - 1));
4452 if (!tcu::compareThreshold(lowerLeft, instance.outputColors[2], threshold))
4453 return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower left corner mismatch"));
4454
4455 const RGBA lowerRight(pixelBuffer.getPixel(pixelBuffer.getWidth() - 1, pixelBuffer.getHeight() - 1));
4456 if (!tcu::compareThreshold(lowerRight, instance.outputColors[3], threshold))
4457 return TestStatus(instance.failResult, instance.getSpecializedFailMessage("Lower right corner mismatch"));
4458
4459 // Check that the contents in the ouput variable matches expected.
4460 if (needInterface)
4461 {
4462 vector<deUint8> inputBufferBytes;
4463 vector<deUint8> outputBufferBytes;
4464
4465 instance.interfaces.getInputBuffer()->getBytes(inputBufferBytes);
4466 instance.interfaces.getOutputBuffer()->getBytes(outputBufferBytes);
4467
4468 const IFDataType& inputType = instance.interfaces.getInputType();
4469 const IFDataType& outputType = instance.interfaces.getOutputType();
4470 const void* inputData = &inputBufferBytes.front();
4471 const void* outputData = &outputBufferBytes.front();
4472 vector<std::pair<int, int> > positions;
4473 const tcu::ConstPixelBufferAccess fragOutputBufferAccess (outputType.getTextureFormat(), renderSize.x(), renderSize.y(), 1, fragOutputMemory->getHostPtr());
4474
4475 positions.push_back(std::make_pair(1, 1));
4476 positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, 1));
4477 positions.push_back(std::make_pair(1, fragOutputBufferAccess.getHeight() - 1));
4478 positions.push_back(std::make_pair(fragOutputBufferAccess.getWidth() - 1, fragOutputBufferAccess.getHeight() - 1));
4479
4480 for (deUint32 posNdx = 0; posNdx < positions.size(); ++posNdx)
4481 {
4482 const int x = positions[posNdx].first;
4483 const int y = positions[posNdx].second;
4484 bool equal = true;
4485
4486 if (outputType.elementType == NUMBERTYPE_FLOAT32)
4487 {
4488 const float* expected = static_cast<const float*>(outputData) + posNdx * outputType.numElements;
4489 const float* actual = static_cast<const float*>(fragOutputBufferAccess.getPixelPtr(x, y));
4490
4491 for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4492 if (!compare32BitFloat(expected[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4493 equal = false;
4494 }
4495 else if (outputType.elementType == NUMBERTYPE_INT32)
4496 {
4497 const deInt32* expected = static_cast<const deInt32*>(outputData) + posNdx * outputType.numElements;
4498 const deInt32* actual = static_cast<const deInt32*>(fragOutputBufferAccess.getPixelPtr(x, y));
4499
4500 for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4501 if (expected[eleNdx] != actual[eleNdx])
4502 equal = false;
4503 }
4504 else if (outputType.elementType == NUMBERTYPE_UINT32)
4505 {
4506 const deUint32* expected = static_cast<const deUint32*>(outputData) + posNdx * outputType.numElements;
4507 const deUint32* actual = static_cast<const deUint32*>(fragOutputBufferAccess.getPixelPtr(x, y));
4508
4509 for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4510 if (expected[eleNdx] != actual[eleNdx])
4511 equal = false;
4512 }
4513 else if (outputType.elementType == NUMBERTYPE_FLOAT16 && inputType.elementType == NUMBERTYPE_FLOAT64)
4514 {
4515 const double* original = static_cast<const double*>(inputData) + posNdx * outputType.numElements;
4516 const deFloat16* actual = static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4517
4518 for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4519 if (!compare16BitFloat64(original[eleNdx], actual[eleNdx], instance.interfaces.getRoundingMode(), context.getTestContext().getLog()))
4520 equal = false;
4521 }
4522 else if (outputType.elementType == NUMBERTYPE_FLOAT16 && inputType.elementType != NUMBERTYPE_FLOAT64)
4523 {
4524 if (inputType.elementType == NUMBERTYPE_FLOAT16)
4525 {
4526 const deFloat16* original = static_cast<const deFloat16*>(inputData) + posNdx * outputType.numElements;
4527 const deFloat16* actual = static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4528
4529 for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4530 if (!compare16BitFloat(original[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4531 equal = false;
4532 }
4533 else
4534 {
4535 const float* original = static_cast<const float*>(inputData) + posNdx * outputType.numElements;
4536 const deFloat16* actual = static_cast<const deFloat16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4537
4538 for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4539 if (!compare16BitFloat(original[eleNdx], actual[eleNdx], instance.interfaces.getRoundingMode(), context.getTestContext().getLog()))
4540 equal = false;
4541 }
4542 }
4543 else if (outputType.elementType == NUMBERTYPE_INT16)
4544 {
4545 const deInt16* expected = static_cast<const deInt16*>(outputData) + posNdx * outputType.numElements;
4546 const deInt16* actual = static_cast<const deInt16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4547
4548 for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4549 if (expected[eleNdx] != actual[eleNdx])
4550 equal = false;
4551 }
4552 else if (outputType.elementType == NUMBERTYPE_UINT16)
4553 {
4554 const deUint16* expected = static_cast<const deUint16*>(outputData) + posNdx * outputType.numElements;
4555 const deUint16* actual = static_cast<const deUint16*>(fragOutputBufferAccess.getPixelPtr(x, y));
4556
4557 for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4558 if (expected[eleNdx] != actual[eleNdx])
4559 equal = false;
4560 }
4561 else if (outputType.elementType == NUMBERTYPE_FLOAT64)
4562 {
4563 const double* expected = static_cast<const double*>(outputData) + posNdx * outputType.numElements;
4564 const double* actual = static_cast<const double*>(fragOutputBufferAccess.getPixelPtr(x, y));
4565
4566 for (deUint32 eleNdx = 0; eleNdx < outputType.numElements; ++eleNdx)
4567 if (!compare64BitFloat(expected[eleNdx], actual[eleNdx], context.getTestContext().getLog()))
4568 equal = false;
4569 }
4570 else {
4571 DE_ASSERT(0 && "unhandled type");
4572 }
4573
4574 if (!equal)
4575 return TestStatus(instance.failResult, instance.getSpecializedFailMessage("fragment output dat point #" + numberToString(posNdx) + " mismatch"));
4576 }
4577 }
4578
4579 // Check the contents in output resources match with expected.
4580 for (deUint32 outputNdx = 0; outputNdx < numOutResources; ++outputNdx)
4581 {
4582 const BufferSp& expected = instance.resources.outputs[outputNdx].getBuffer();
4583
4584 if (instance.resources.verifyIO != DE_NULL)
4585 {
4586 if (!(*instance.resources.verifyIO)(instance.resources.inputs, outResourceMemories, instance.resources.outputs, context.getTestContext().getLog()))
4587 return tcu::TestStatus::fail("Resource returned doesn't match with expected");
4588 }
4589 else
4590 {
4591 vector<deUint8> expectedBytes;
4592 expected->getBytes(expectedBytes);
4593
4594 if (deMemCmp(&expectedBytes.front(), outResourceMemories[outputNdx]->getHostPtr(), expectedBytes.size()))
4595 {
4596 const size_t numExpectedEntries = expectedBytes.size() / sizeof(float);
4597 float* expectedFloats = reinterpret_cast<float*>(&expectedBytes.front());
4598 float* outputFloats = reinterpret_cast<float*>(outResourceMemories[outputNdx]->getHostPtr());
4599 float diff = 0.0f;
4600 deUint32 bitDiff = 0;
4601
4602 for (size_t expectedNdx = 0; expectedNdx < numExpectedEntries; ++expectedNdx)
4603 {
4604 // RTZ and RNE can introduce a difference of a single ULP
4605 // The RTZ output will always be either equal or lower than the RNE expected,
4606 // so perform a bitwise subtractraction and check for the ULP difference
4607 bitDiff = *reinterpret_cast<deUint32*>(&expectedFloats[expectedNdx]) - *reinterpret_cast<deUint32*>(&outputFloats[expectedNdx]);
4608
4609 // Allow a maximum of 1 ULP difference to account for RTZ rounding
4610 if (bitDiff & (~0x1))
4611 {
4612 // Note: RTZ/RNE rounding leniency isn't applied for the checks below:
4613
4614 // Some *variable_pointers* tests store counters in buffer
4615 // whose value may vary if the same shader may be executed for multiple times
4616 // in this case the output value can be expected value + non-negative integer N
4617 if (instance.customizedStages == VK_SHADER_STAGE_VERTEX_BIT ||
4618 instance.customizedStages == VK_SHADER_STAGE_GEOMETRY_BIT ||
4619 instance.customizedStages == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ||
4620 instance.customizedStages == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
4621 {
4622 if (deFloatIsInf(outputFloats[expectedNdx]) || deFloatIsNaN(outputFloats[expectedNdx]))
4623 return tcu::TestStatus::fail("Value returned is invalid");
4624
4625 diff = outputFloats[expectedNdx] - expectedFloats[expectedNdx];
4626 deUint32 intDiff = static_cast<deUint32>(diff);
4627
4628 if ((diff < 0.0f) || (expectedFloats[expectedNdx] + static_cast<float>(intDiff)) != outputFloats[expectedNdx])
4629 return tcu::TestStatus::fail("Value returned should be equal to expected value plus non-negative integer");
4630 }
4631 else
4632 {
4633 return tcu::TestStatus::fail("Resource returned should be equal to expected, allowing for RTZ/RNE rounding");
4634 }
4635 }
4636 }
4637 }
4638
4639 }
4640 }
4641
4642 return TestStatus::pass("Rendered output matches input");
4643 }
4644
getVertFragPipelineStages(void)4645 const vector<ShaderElement>& getVertFragPipelineStages (void)
4646 {
4647 static vector<ShaderElement> vertFragPipelineStages;
4648 if(vertFragPipelineStages.empty())
4649 {
4650 vertFragPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4651 vertFragPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4652 }
4653 return vertFragPipelineStages;
4654 }
4655
getTessPipelineStages(void)4656 const vector<ShaderElement>& getTessPipelineStages (void)
4657 {
4658 static vector<ShaderElement> tessPipelineStages;
4659 if(tessPipelineStages.empty())
4660 {
4661 tessPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4662 tessPipelineStages.push_back(ShaderElement("tessc", "main", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT));
4663 tessPipelineStages.push_back(ShaderElement("tesse", "main", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT));
4664 tessPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4665 }
4666 return tessPipelineStages;
4667 }
4668
getGeomPipelineStages(void)4669 const vector<ShaderElement>& getGeomPipelineStages (void)
4670 {
4671 static vector<ShaderElement> geomPipelineStages;
4672 if(geomPipelineStages.empty())
4673 {
4674 geomPipelineStages.push_back(ShaderElement("vert", "main", VK_SHADER_STAGE_VERTEX_BIT));
4675 geomPipelineStages.push_back(ShaderElement("geom", "main", VK_SHADER_STAGE_GEOMETRY_BIT));
4676 geomPipelineStages.push_back(ShaderElement("frag", "main", VK_SHADER_STAGE_FRAGMENT_BIT));
4677 }
4678 return geomPipelineStages;
4679 }
4680
4681 // Helper structure used by addTestForStage function.
4682 struct StageData
4683 {
4684 typedef const vector<ShaderElement>& (*GetPipelineStagesFn)();
4685 typedef void (*AddShaderCodeCustomStageFn)(vk::SourceCollections&, InstanceContext);
4686
4687 GetPipelineStagesFn getPipelineFn;
4688 AddShaderCodeCustomStageFn initProgramsFn;
4689
StageDatavkt::SpirVAssembly::StageData4690 StageData()
4691 : getPipelineFn(DE_NULL)
4692 , initProgramsFn(DE_NULL)
4693 {
4694 }
4695
StageDatavkt::SpirVAssembly::StageData4696 StageData(GetPipelineStagesFn pipelineGetter, AddShaderCodeCustomStageFn programsInitializer)
4697 : getPipelineFn(pipelineGetter)
4698 , initProgramsFn(programsInitializer)
4699 {
4700 }
4701 };
4702
4703 // Helper function used by addTestForStage function.
getStageData(vk::VkShaderStageFlagBits stage)4704 const StageData& getStageData (vk::VkShaderStageFlagBits stage)
4705 {
4706 // Construct map
4707 static map<vk::VkShaderStageFlagBits, StageData> testedStageData;
4708 if(testedStageData.empty())
4709 {
4710 testedStageData[VK_SHADER_STAGE_VERTEX_BIT] = StageData(getVertFragPipelineStages, addShaderCodeCustomVertex);
4711 testedStageData[VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT] = StageData(getTessPipelineStages, addShaderCodeCustomTessControl);
4712 testedStageData[VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT] = StageData(getTessPipelineStages, addShaderCodeCustomTessEval);
4713 testedStageData[VK_SHADER_STAGE_GEOMETRY_BIT] = StageData(getGeomPipelineStages, addShaderCodeCustomGeometry);
4714 testedStageData[VK_SHADER_STAGE_FRAGMENT_BIT] = StageData(getVertFragPipelineStages, addShaderCodeCustomFragment);
4715 }
4716
4717 return testedStageData[stage];
4718 }
4719
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)4720 void createTestForStage (vk::VkShaderStageFlagBits stage,
4721 const std::string& name,
4722 const RGBA (&inputColors)[4],
4723 const RGBA (&outputColors)[4],
4724 const map<string, string>& testCodeFragments,
4725 const SpecConstants& specConstants,
4726 const PushConstants& pushConstants,
4727 const GraphicsResources& resources,
4728 const GraphicsInterfaces& interfaces,
4729 const vector<string>& extensions,
4730 VulkanFeatures vulkanFeatures,
4731 tcu::TestCaseGroup* tests,
4732 const qpTestResult failResult,
4733 const string& failMessageTemplate,
4734 const bool renderFullSquare,
4735 const bool splitRenderArea)
4736 {
4737 const StageData& stageData = getStageData(stage);
4738 DE_ASSERT(stageData.getPipelineFn || stageData.initProgramsFn);
4739 const vector<ShaderElement>& pipeline = stageData.getPipelineFn();
4740
4741 StageToSpecConstantMap specConstantMap;
4742 if (!specConstants.empty())
4743 specConstantMap[stage] = specConstants;
4744
4745 InstanceContext ctx (inputColors, outputColors, testCodeFragments, specConstantMap, pushConstants, resources, interfaces, extensions, vulkanFeatures, stage);
4746 ctx.splitRenderArea = splitRenderArea;
4747 for (size_t i = 0; i < pipeline.size(); ++i)
4748 {
4749 ctx.moduleMap[pipeline[i].moduleName].push_back(std::make_pair(pipeline[i].entryName, pipeline[i].stage));
4750 ctx.requiredStages = static_cast<VkShaderStageFlagBits>(ctx.requiredStages | pipeline[i].stage);
4751 }
4752
4753 ctx.failResult = failResult;
4754 if (!failMessageTemplate.empty())
4755 ctx.failMessageTemplate = failMessageTemplate;
4756
4757 ctx.renderFullSquare = renderFullSquare;
4758 ctx.splitRenderArea = splitRenderArea;
4759 addFunctionCaseWithPrograms<InstanceContext>(tests, name, "", stageData.initProgramsFn, runAndVerifyDefaultPipeline, ctx);
4760 }
4761
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)4762 void createTestsForAllStages (const std::string& name,
4763 const RGBA (&inputColors)[4],
4764 const RGBA (&outputColors)[4],
4765 const map<string, string>& testCodeFragments,
4766 const SpecConstants& specConstants,
4767 const PushConstants& pushConstants,
4768 const GraphicsResources& resources,
4769 const GraphicsInterfaces& interfaces,
4770 const vector<string>& extensions,
4771 VulkanFeatures vulkanFeatures,
4772 tcu::TestCaseGroup* tests,
4773 const qpTestResult failResult,
4774 const string& failMessageTemplate,
4775 const bool splitRenderArea)
4776 {
4777 createTestForStage(VK_SHADER_STAGE_VERTEX_BIT, name + "_vert",
4778 inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4779 interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4780
4781 createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, name + "_tessc",
4782 inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4783 interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4784
4785 createTestForStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, name + "_tesse",
4786 inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4787 interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4788
4789 createTestForStage(VK_SHADER_STAGE_GEOMETRY_BIT, name + "_geom",
4790 inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4791 interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate);
4792
4793 createTestForStage(VK_SHADER_STAGE_FRAGMENT_BIT, name + "_frag",
4794 inputColors, outputColors, testCodeFragments, specConstants, pushConstants, resources,
4795 interfaces, extensions, vulkanFeatures, tests, failResult, failMessageTemplate, false, splitRenderArea);
4796 }
4797
addTessCtrlTest(tcu::TestCaseGroup * group,const char * name,const map<string,string> & fragments)4798 void addTessCtrlTest (tcu::TestCaseGroup* group, const char* name, const map<string, string>& fragments)
4799 {
4800 RGBA defaultColors[4];
4801 getDefaultColors(defaultColors);
4802
4803 createTestForStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, name,
4804 defaultColors, defaultColors, fragments, SpecConstants(), PushConstants(), GraphicsResources(),
4805 GraphicsInterfaces(), vector<string>(), VulkanFeatures(), group);
4806 }
4807
4808 } // SpirVAssembly
4809 } // vkt
4810