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