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