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