1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2021 The Khronos Group Inc. 6 * Copyright (c) 2023 LunarG, Inc. 7 * Copyright (c) 2023 Nintendo 8 * 9 * Licensed under the Apache License, Version 2.0 (the "License"); 10 * you may not use this file except in compliance with the License. 11 * You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 * 21 *//*! 22 * \file vktPipelineInterfaceMatchingTests.cpp 23 * \brief Interface matching tests 24 *//*--------------------------------------------------------------------*/ 25 26#include "vktPipelineInterfaceMatchingTests.hpp" 27#include "vktPipelineImageUtil.hpp" 28 29#include "vkBuilderUtil.hpp" 30#include "vkBarrierUtil.hpp" 31#include "vkImageUtil.hpp" 32#include "vkMemUtil.hpp" 33#include "vkQueryUtil.hpp" 34#include "vkTypeUtil.hpp" 35#include "vkCmdUtil.hpp" 36#include "vkObjUtil.hpp" 37 38#include "tcuTestLog.hpp" 39#include "tcuTestCase.hpp" 40#include "tcuStringTemplate.hpp" 41 42#include <set> 43 44namespace vkt 45{ 46namespace pipeline 47{ 48 49using namespace vk; 50using namespace de; 51using namespace tcu; 52 53namespace 54{ 55 56enum class TestType 57{ 58 VECTOR_LENGTH = 0, 59 DECORATION_MISMATCH, 60}; 61 62enum class VecType 63{ 64 VEC2 = 0, 65 VEC3, 66 VEC4, 67 IVEC2, 68 IVEC3, 69 IVEC4, 70 UVEC2, 71 UVEC3, 72 UVEC4, 73}; 74 75enum class DecorationType 76{ 77 NONE = 0, 78 FLAT, 79 NO_PERSPECTIVE, 80 COMPONENT0 81}; 82 83enum class PipelineType 84{ 85 // all combinations with vert and frag 86 VERT_OUT_FRAG_IN = 0, 87 88 // all combinations with vert, tesc, tese and frag 89 VERT_OUT_TESC_IN_TESE_FRAG, 90 VERT_TESC_TESE_OUT_FRAG_IN, 91 VERT_TESC_OUT_TESE_IN_FRAG, 92 93 // all combinations with vert, geom and frag 94 VERT_OUT_GEOM_IN_FRAG, 95 VERT_GEOM_OUT_FRAG_IN, 96 97 // all combinations with vert, tesc, tese, geom and frag 98 VERT_OUT_TESC_IN_TESE_GEOM_FRAG, // this won't add coverage as it is similar to VERT_OUT_TESC_IN_TESE_FRAG 99 //VERT_TESC_OUT_TESE_IN_GEOM_FRAG, // this won't add coverage as it is similar to VERT_TESC_OUT_TESE_IN_FRAG 100 VERT_TESC_TESE_OUT_GEOM_IN_FRAG, 101 VERT_TESC_TESE_GEOM_OUT_FRAG_IN, 102}; 103 104enum class DefinitionType 105{ 106 LOOSE_VARIABLE = 0, 107 MEMBER_OF_BLOCK, 108 MEMBER_OF_STRUCTURE, 109 MEMBER_OF_ARRAY_OF_STRUCTURES, 110 MEMBER_OF_STRUCTURE_IN_BLOCK, 111 MEMBER_OF_ARRAY_OF_STRUCTURES_IN_BLOCK, 112}; 113 114struct TestParams 115{ 116 PipelineConstructionType pipelineConstructionType; 117 TestType testType; 118 119 VecType outVecType; 120 VecType inVecType; 121 122 DecorationType outDeclDecoration; 123 DecorationType inDeclDecoration; 124 125 PipelineType pipelineType; 126 DefinitionType definitionType; 127}; 128 129typedef de::SharedPtr<TestParams> TestParamsSp; 130 131// helper function that check if specified pipeline is in set of pipelines 132bool isPipelineOneOf(PipelineType pipelineType, std::set<PipelineType> pipelines) 133{ 134 return !!pipelines.count(pipelineType); 135} 136 137class InterfaceMatchingTestInstance : public vkt::TestInstance 138{ 139public: 140 InterfaceMatchingTestInstance (Context& context, 141 const TestParamsSp params); 142 virtual ~InterfaceMatchingTestInstance (void) = default; 143 144 tcu::TestStatus iterate(void) override; 145 146private: 147 TestParamsSp m_params; 148 SimpleAllocator m_alloc; 149 150 Move<VkBuffer> m_vertexBuffer; 151 de::MovePtr<Allocation> m_vertexBufferAlloc; 152 Move<VkBuffer> m_resultBuffer; 153 de::MovePtr<Allocation> m_resultBufferAlloc; 154 155 Move<VkImage> m_colorImage; 156 de::MovePtr<Allocation> m_colorImageAlloc; 157 Move<VkImageView> m_colorAttachmentView; 158 RenderPassWrapper m_renderPass; 159 Move<VkFramebuffer> m_framebuffer; 160 161 ShaderWrapper m_vertShaderModule; 162 ShaderWrapper m_tescShaderModule; 163 ShaderWrapper m_teseShaderModule; 164 ShaderWrapper m_geomShaderModule; 165 ShaderWrapper m_fragShaderModule; 166 167 PipelineLayoutWrapper m_pipelineLayout; 168 GraphicsPipelineWrapper m_graphicsPipeline; 169 170 Move<VkCommandPool> m_cmdPool; 171 Move<VkCommandBuffer> m_cmdBuffer; 172}; 173 174InterfaceMatchingTestInstance::InterfaceMatchingTestInstance(Context& context, const TestParamsSp params) 175 : vkt::TestInstance(context) 176 , m_params(params) 177 , m_alloc(context.getDeviceInterface(), context.getDevice(), 178 getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())) 179 , m_graphicsPipeline(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), params->pipelineConstructionType) 180{ 181} 182 183tcu::TestStatus InterfaceMatchingTestInstance::iterate(void) 184{ 185 const DeviceInterface& vk = m_context.getDeviceInterface(); 186 const VkDevice device = m_context.getDevice(); 187 const VkQueue queue = m_context.getUniversalQueue(); 188 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 189 const VkComponentMapping componentMappingRGBA = makeComponentMappingRGBA(); 190 VkImageSubresourceRange subresourceRange { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }; 191 const VkFormat colorFormat (VK_FORMAT_R8G8B8A8_UNORM); 192 const tcu::UVec2 renderSize (16, 16); 193 const tcu::TextureFormat textureFormat = mapVkFormat(colorFormat); 194 const VkDeviceSize pixelDataSize = renderSize.x() * renderSize.y() * textureFormat.getPixelSize(); 195 const VkDeviceSize vertexBufferOffset = 0; 196 197 // create color image that is used as a color attachment 198 { 199 const VkImageCreateInfo colorImageParams 200 { 201 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 202 DE_NULL, // const void* pNext; 203 0u, // VkImageCreateFlags flags; 204 VK_IMAGE_TYPE_2D, // VkImageType imageType; 205 colorFormat, // VkFormat format; 206 { renderSize.x(), renderSize.y(), 1u }, // VkExtent3D extent; 207 1u, // deUint32 mipLevels; 208 1u, // deUint32 arrayLayers; 209 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 210 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 211 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; 212 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 213 1u, // deUint32 queueFamilyIndexCount; 214 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 215 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 216 }; 217 218 m_colorImage = createImage(vk, device, &colorImageParams); 219 220 // allocate and bind color image memory 221 m_colorImageAlloc = m_alloc.allocate(getImageMemoryRequirements(vk, device, *m_colorImage), MemoryRequirement::Any); 222 VK_CHECK(vk.bindImageMemory(device, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset())); 223 } 224 225 // create color attachment view 226 { 227 const VkImageViewCreateInfo colorAttachmentViewParams 228 { 229 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 230 DE_NULL, // const void* pNext; 231 0u, // VkImageViewCreateFlags flags; 232 *m_colorImage, // VkImage image; 233 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 234 colorFormat, // VkFormat format; 235 componentMappingRGBA, // VkComponentMapping components; 236 subresourceRange // VkImageSubresourceRange subresourceRange; 237 }; 238 239 m_colorAttachmentView = createImageView(vk, device, &colorAttachmentViewParams); 240 } 241 242 // create render pass 243 m_renderPass = RenderPassWrapper(m_params->pipelineConstructionType, vk, device, colorFormat); 244 245 // create framebuffer 246 { 247 const VkFramebufferCreateInfo framebufferParams 248 { 249 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 250 DE_NULL, // const void* pNext; 251 0u, // VkFramebufferCreateFlags flags; 252 *m_renderPass, // VkRenderPass renderPass; 253 1u, // deUint32 attachmentCount; 254 &m_colorAttachmentView.get(), // const VkImageView* pAttachments; 255 (deUint32)renderSize.x(), // deUint32 width; 256 (deUint32)renderSize.y(), // deUint32 height; 257 1u // deUint32 layers; 258 }; 259 260 m_renderPass.createFramebuffer(vk, device, &framebufferParams, *m_colorImage); 261 } 262 263 // create pipeline layout 264 { 265 const VkPipelineLayoutCreateInfo pipelineLayoutParams 266 { 267 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 268 DE_NULL, // const void* pNext; 269 0u, // VkPipelineLayoutCreateFlags flags; 270 0u, // deUint32 setLayoutCount; 271 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; 272 0u, // deUint32 pushConstantRangeCount; 273 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 274 }; 275 276 m_pipelineLayout = PipelineLayoutWrapper(m_params->pipelineConstructionType, vk, device, &pipelineLayoutParams); 277 } 278 279 // create pipeline 280 bool useTess = isPipelineOneOf(m_params->pipelineType, { 281 PipelineType::VERT_OUT_TESC_IN_TESE_FRAG, 282 PipelineType::VERT_TESC_TESE_OUT_FRAG_IN, 283 PipelineType::VERT_TESC_OUT_TESE_IN_FRAG, 284 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG, 285 PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG, 286 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN }); 287 288 m_vertShaderModule = ShaderWrapper(vk, device, m_context.getBinaryCollection().get("vert"), 0); 289 m_fragShaderModule = ShaderWrapper(vk, device, m_context.getBinaryCollection().get("frag"), 0); 290 if (useTess) 291 { 292 m_tescShaderModule = ShaderWrapper(vk, device, m_context.getBinaryCollection().get("tesc"), 0); 293 m_teseShaderModule = ShaderWrapper(vk, device, m_context.getBinaryCollection().get("tese"), 0); 294 } 295 296 if (isPipelineOneOf(m_params->pipelineType, { 297 PipelineType::VERT_OUT_GEOM_IN_FRAG, 298 PipelineType::VERT_GEOM_OUT_FRAG_IN, 299 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG, 300 PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG, 301 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN })) 302 { 303 m_geomShaderModule = ShaderWrapper(vk, device, m_context.getBinaryCollection().get("geom"), 0); 304 } 305 306 const std::vector<VkViewport> viewports { makeViewport(renderSize) }; 307 const std::vector<VkRect2D> scissors { makeRect2D(renderSize) }; 308 309 m_graphicsPipeline.setDefaultTopology(useTess ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP) 310 .setDefaultRasterizationState() 311 .setDefaultDepthStencilState() 312 .setDefaultMultisampleState() 313 .setDefaultColorBlendState() 314 .setupVertexInputState() 315 .setupPreRasterizationShaderState(viewports, 316 scissors, 317 m_pipelineLayout, 318 *m_renderPass, 319 0u, 320 m_vertShaderModule, 321 DE_NULL, 322 m_tescShaderModule, 323 m_teseShaderModule, 324 m_geomShaderModule) 325 .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, m_fragShaderModule) 326 .setupFragmentOutputState(*m_renderPass) 327 .setMonolithicPipelineLayout(m_pipelineLayout) 328 .buildPipeline(); 329 330 // create vertex buffer 331 { 332 std::vector<float> vertices 333 { 334 1.0f, -1.0f, 0.0f, 1.0f, 335 -1.0f, 1.0f, 0.0f, 1.0f, 336 -1.0f, -1.0f, 0.0f, 1.0f, 337 }; 338 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(vertices.size() * sizeof(float), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 339 340 m_vertexBuffer = createBuffer(vk, device, &bufferCreateInfo); 341 m_vertexBufferAlloc = m_alloc.allocate(getBufferMemoryRequirements(vk, device, *m_vertexBuffer), MemoryRequirement::HostVisible); 342 VK_CHECK(vk.bindBufferMemory(device, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset())); 343 344 deMemcpy(m_vertexBufferAlloc->getHostPtr(), vertices.data(), vertices.size() * sizeof(float)); 345 flushAlloc(vk, device, *m_vertexBufferAlloc); 346 } 347 348 // create buffer to which we will grab rendered result 349 { 350 const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(pixelDataSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); 351 352 m_resultBuffer = createBuffer(vk, device, &bufferCreateInfo); 353 m_resultBufferAlloc = m_alloc.allocate(getBufferMemoryRequirements(vk, device, *m_resultBuffer), MemoryRequirement::HostVisible); 354 VK_CHECK(vk.bindBufferMemory(device, *m_resultBuffer, m_resultBufferAlloc->getMemory(), m_resultBufferAlloc->getOffset())); 355 } 356 357 // create command pool and command buffer 358 m_cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); 359 m_cmdBuffer = allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 360 361 // record command buffer 362 beginCommandBuffer(vk, *m_cmdBuffer, 0u); 363 364 // change image layout so we can use it as color attachment 365 const VkImageMemoryBarrier attachmentLayoutBarrier = makeImageMemoryBarrier( 366 VK_ACCESS_NONE_KHR, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 367 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 368 *m_colorImage, subresourceRange); 369 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 370 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &attachmentLayoutBarrier); 371 372 // render single triangle 373 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(renderSize), Vec4(0.0f, 0.0f, 0.0f, 1.0f)); 374 375 m_graphicsPipeline.bind(*m_cmdBuffer); 376 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &*m_vertexBuffer, &vertexBufferOffset); 377 vk.cmdDraw(*m_cmdBuffer, 4, 1, 0, 0); 378 379 m_renderPass.end(vk, *m_cmdBuffer); 380 381 copyImageToBuffer(vk, *m_cmdBuffer, *m_colorImage, *m_resultBuffer, tcu::IVec2(renderSize.x(), renderSize.y())); 382 383 endCommandBuffer(vk, *m_cmdBuffer); 384 385 // submit commands 386 submitCommandsAndWait(vk, device, queue, *m_cmdBuffer); 387 388 // read buffer data 389 invalidateAlloc(vk, device, *m_resultBufferAlloc); 390 391 // validate result - verification is done in glsl, just checking 392 // two texels, if test passed then r channel should be set to 255 393 const unsigned char* bufferPtr = static_cast<unsigned char*>(m_resultBufferAlloc->getHostPtr()); 394 if ((bufferPtr[0] > 254) && (bufferPtr[renderSize.x()*4+8] > 254)) 395 return TestStatus::pass("Pass"); 396 397 const tcu::ConstPixelBufferAccess resultAccess(textureFormat, tcu::IVec3((int)renderSize.x(), (int)renderSize.y(), 1u), bufferPtr); 398 TestLog& log = m_context.getTestContext().getLog(); 399 log << tcu::TestLog::ImageSet("Result of rendering", "") 400 << TestLog::Image("Result", "", resultAccess) 401 << tcu::TestLog::EndImageSet; 402 403 return TestStatus::fail("Fail"); 404} 405 406class InterfaceMatchingTestCase : public vkt::TestCase 407{ 408public: 409 InterfaceMatchingTestCase (tcu::TestContext& testContext, 410 TestParamsSp params); 411 virtual ~InterfaceMatchingTestCase (void) = default; 412 413 void initPrograms (SourceCollections& sourceCollections) const override; 414 void checkSupport (Context& context) const override; 415 TestInstance* createInstance (Context& context) const override; 416 417protected: 418 419 enum class ComponentType 420 { 421 FLOAT = 0, 422 INT, 423 UINT 424 }; 425 426 struct VecData 427 { 428 std::string glslType; 429 ComponentType componentType; 430 deUint32 componentsCount; 431 std::string components[4]; 432 }; 433 434 struct DecorationData 435 { 436 std::string namePart; 437 std::string glslDecoration; 438 std::string glslComponent; 439 }; 440 441 // helper structure used during construction of in/out declaration 442 struct PipelineData 443 { 444 bool outDeclArray; 445 bool inFlatDecoration; // needed for frag in 446 bool inDeclArray; 447 }; 448 449 typedef std::map<std::string, std::string> SpecializationMap; 450 451 std::string genOutAssignment (const std::string& variableName, const VecData& outVecData) const; 452 std::string genInVerification (const std::string& variableName, const VecData& outVecData, const VecData& inVecData) const; 453 454 const VecData& getVecData (VecType vecType) const; 455 const DecorationData& getDecorationData (DecorationType decorationType) const; 456 457 const PipelineData& getPipelineData (PipelineType pipelineType) const; 458 std::string generateName (const TestParams& testParams) const; 459 460private: 461 462 const TestParamsSp m_params; 463}; 464 465InterfaceMatchingTestCase::InterfaceMatchingTestCase(tcu::TestContext& testContext, 466 TestParamsSp params) 467 : vkt::TestCase (testContext, generateName(*params)) 468 , m_params (params) 469{ 470} 471 472void InterfaceMatchingTestCase::initPrograms(SourceCollections& sourceCollections) const 473{ 474 GlslSourceCollection& glslSources = sourceCollections.glslSources; 475 const VecData& outVecData = getVecData(m_params->outVecType); 476 const VecData& inVecData = getVecData(m_params->inVecType); 477 const DecorationData& outDecorationData = getDecorationData(m_params->outDeclDecoration); 478 const DecorationData& inDecorationData = getDecorationData(m_params->inDeclDecoration); 479 const PipelineData& pipelineData = getPipelineData(m_params->pipelineType); 480 481 // deterimine if decoration or array is needed for in/out declarations 482 const std::string outDeclArray = pipelineData.outDeclArray ? "[]" : ""; 483 const std::string inDeclArray = pipelineData.inDeclArray ? "[]" : ""; 484 const std::string variableToAssignArray = pipelineData.outDeclArray ? "[gl_InvocationID]" : ""; 485 const std::string variableToVerifyArray = pipelineData.inDeclArray ? "[0]" : ""; 486 487 std::string outDecoration = ""; 488 std::string inDecoration = pipelineData.inFlatDecoration ? "flat " : ""; 489 std::string outComponent = outDecorationData.glslComponent; 490 std::string inComponent = inDecorationData.glslComponent; 491 if (m_params->testType == TestType::DECORATION_MISMATCH) 492 { 493 outDecoration = outDecorationData.glslDecoration; 494 inDecoration = inDecorationData.glslDecoration; 495 } 496 497 std::string outDeclaration; 498 std::string inDeclaration; 499 std::string variableToAssignName; 500 std::string variableToVerifyName; 501 502 // generate in/out declarations 503 switch (m_params->definitionType) 504 { 505 case DefinitionType::LOOSE_VARIABLE: 506 outDeclaration = "layout(location = 0" + outDecorationData.glslComponent + ") out " + outDecoration + outVecData.glslType + " looseVariable" + outDeclArray + ";\n"; 507 inDeclaration = "layout(location = 0" + inDecorationData.glslComponent + ") in " + inDecoration + inVecData.glslType + " looseVariable" + inDeclArray + ";\n"; 508 variableToAssignName = "looseVariable" + variableToAssignArray; 509 variableToVerifyName = "looseVariable" + variableToVerifyArray; 510 break; 511 512 case DefinitionType::MEMBER_OF_BLOCK: 513 outDeclaration += "layout(location = 0) out block {\n" 514 " vec2 dummy;\n" 515 "layout(location = 1" + outDecorationData.glslComponent + ") " + 516 outDecoration + outVecData.glslType + " variableInBlock;\n" 517 "} testBlock" + outDeclArray + ";\n"; 518 inDeclaration += "in block {\n" 519 "layout(location = 0) vec2 dummy;\n" 520 "layout(location = 1" + inDecorationData.glslComponent + ") " + 521 inDecoration + inVecData.glslType + " variableInBlock;\n" 522 "} testBlock" + inDeclArray + ";\n"; 523 variableToAssignName = "testBlock" + variableToAssignArray + ".variableInBlock"; 524 variableToVerifyName = "testBlock" + variableToVerifyArray + ".variableInBlock"; 525 break; 526 527 case DefinitionType::MEMBER_OF_STRUCTURE: 528 outDeclaration += "layout(location = 0) out " + outDecoration + "struct {\n" 529 " vec2 dummy;\n" 530 " " + outVecData.glslType + " variableInStruct;\n" 531 "} testStruct" + outDeclArray + ";\n"; 532 inDeclaration += "layout(location = 0) in " + inDecoration + "struct {\n" 533 " vec2 dummy;\n" 534 " " + inVecData.glslType + " variableInStruct;\n" 535 "} testStruct" + inDeclArray + ";\n"; 536 variableToAssignName = "testStruct" + variableToAssignArray + ".variableInStruct"; 537 variableToVerifyName = "testStruct" + variableToVerifyArray + ".variableInStruct"; 538 break; 539 540 case DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES: 541 outDeclaration += "layout(location = 0) out " + outDecoration + "struct {\n" 542 " float dummy;\n" 543 " " + outVecData.glslType + " variableInStruct;\n" 544 "} testStructArray" + outDeclArray + "[3];\n"; 545 inDeclaration += "layout(location = 0) in " + inDecoration + "struct {\n" 546 " float dummy;\n" 547 " " + inVecData.glslType + " variableInStruct;\n" 548 "} testStructArray" + inDeclArray + "[3];\n"; 549 // just verify last item from array 550 variableToAssignName = "testStructArray" + variableToAssignArray + "[2].variableInStruct"; 551 variableToVerifyName = "testStructArray" + variableToVerifyArray + "[2].variableInStruct"; 552 break; 553 554 case DefinitionType::MEMBER_OF_STRUCTURE_IN_BLOCK: 555 outDeclaration += "struct TestStruct {\n" 556 " vec2 dummy;\n" 557 " " + outVecData.glslType + " variableInStruct;\n" 558 "};\n" 559 "layout(location = 0) out block {\n" 560 " vec2 dummy;\n" 561 " " + outDecoration + "TestStruct structInBlock;\n" 562 "} testBlock" + outDeclArray + ";\n"; 563 inDeclaration += "struct TestStruct {\n" 564 " vec2 dummy;\n" 565 " " + inVecData.glslType + " variableInStruct;\n" 566 "};\n" 567 "layout(location = 0) in block {\n" 568 " vec2 dummy;\n" 569 " " + inDecoration + "TestStruct structInBlock;\n" 570 "} testBlock" + inDeclArray + ";\n"; 571 variableToAssignName = "testBlock" + variableToAssignArray + ".structInBlock.variableInStruct"; 572 variableToVerifyName = "testBlock" + variableToVerifyArray + ".structInBlock.variableInStruct"; 573 break; 574 575 case DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES_IN_BLOCK: 576 outDeclaration += "struct TestStruct {\n" 577 " vec4 dummy;\n" 578 " " + outVecData.glslType + " variableInStruct;\n" 579 "};\n" 580 "layout(location = 0) out block {\n" 581 " " + outDecoration + "TestStruct structArrayInBlock[3];\n" 582 "} testBlock" + outDeclArray + ";\n"; 583 inDeclaration += "struct TestStruct {\n" 584 " vec4 dummy;\n" 585 " " + inVecData.glslType + " variableInStruct;\n" 586 "};" 587 "layout(location = 0) in block {\n" 588 " " + inDecoration + "TestStruct structArrayInBlock[3];\n" 589 "} testBlock" + inDeclArray + ";\n"; 590 // just verify second item from array 591 variableToAssignName = "testBlock" + variableToAssignArray + ".structArrayInBlock[1].variableInStruct"; 592 variableToVerifyName = "testBlock" + variableToVerifyArray + ".structArrayInBlock[1].variableInStruct"; 593 break; 594 595 default: 596 DE_ASSERT(DE_FALSE); 597 } 598 599 std::string outValueAssignment = genOutAssignment (variableToAssignName, outVecData); 600 std::string inValueVerification = genInVerification(variableToVerifyName, outVecData, inVecData); 601 602 // create specialization map and grab references to both 603 // values so we dont have to index into it in every case 604 SpecializationMap specializationMap 605 { 606 { "DECLARATIONS", "" }, 607 { "OPERATIONS", "" }, 608 }; 609 std::string& declarations = specializationMap["DECLARATIONS"]; 610 std::string& operations = specializationMap["OPERATIONS"]; 611 612 // define vertex shader source 613 if (isPipelineOneOf(m_params->pipelineType, { 614 PipelineType::VERT_OUT_FRAG_IN, 615 PipelineType::VERT_OUT_TESC_IN_TESE_FRAG, 616 PipelineType::VERT_OUT_GEOM_IN_FRAG, 617 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG })) 618 { 619 declarations = outDeclaration; 620 operations = outValueAssignment; 621 } 622 // else passthrough source 623 624 tcu::StringTemplate vertTemplate( 625 "#version 450\n" 626 "layout(location = 0) in vec4 inPosition;\n" 627 "${DECLARATIONS}" 628 "void main(void)\n" 629 "{\n" 630 " gl_Position = inPosition;\n" 631 "${OPERATIONS}" 632 "}\n"); 633 glslSources.add("vert") << glu::VertexSource(vertTemplate.specialize(specializationMap)); 634 635 // define tesselation control shader source 636 bool tescNeeded = DE_FALSE; 637 switch (m_params->pipelineType) 638 { 639 case PipelineType::VERT_TESC_OUT_TESE_IN_FRAG: 640 declarations = outDeclaration; 641 operations = outValueAssignment; 642 tescNeeded = DE_TRUE; 643 break; 644 645 case PipelineType::VERT_OUT_TESC_IN_TESE_FRAG: 646 case PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG: 647 declarations = inDeclaration + 648 "layout(location = 0) out float outResult[];\n"; 649 operations = " float result;\n" + 650 inValueVerification + 651 " outResult[gl_InvocationID] = result;\n"; 652 tescNeeded = DE_TRUE; 653 break; 654 655 case PipelineType::VERT_TESC_TESE_OUT_FRAG_IN: 656 case PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG: 657 case PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN: 658 // passthrough sources 659 tescNeeded = DE_TRUE; 660 break; 661 662 default: 663 break; 664 } 665 666 std::string tescSource = tescNeeded ? 667 StringTemplate( 668 "#version 450\n" 669 "#extension GL_EXT_tessellation_shader : require\n\n" 670 "layout(vertices = 1) out;\n\n" 671 "${DECLARATIONS}" 672 "void main(void)\n" 673 "{\n" 674 " gl_TessLevelInner[0] = 1.0;\n" 675 " gl_TessLevelOuter[0] = 1.0;\n" 676 " gl_TessLevelOuter[1] = 1.0;\n" 677 " gl_TessLevelOuter[2] = 1.0;\n" 678 "${OPERATIONS}" 679 "}\n").specialize(specializationMap) 680 : ""; 681 682 // define tesselation evaluation shader source 683 bool teseNeeded = DE_FALSE; 684 switch (m_params->pipelineType) 685 { 686 case PipelineType::VERT_TESC_TESE_OUT_FRAG_IN: 687 case PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG: 688 declarations = outDeclaration; 689 operations = outValueAssignment; 690 teseNeeded = DE_TRUE; 691 break; 692 693 case PipelineType::VERT_TESC_OUT_TESE_IN_FRAG: 694 declarations = inDeclaration + 695 "layout(location = 0) out float outResult;\n"; 696 operations = " float result;\n" + 697 inValueVerification + 698 " outResult = result;\n"; 699 teseNeeded = DE_TRUE; 700 break; 701 702 case PipelineType::VERT_OUT_TESC_IN_TESE_FRAG: 703 case PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG: 704 declarations = "layout(location = 0) in float inResult[];\n" 705 "layout(location = 0) out float outResult;\n"; 706 operations = " outResult = inResult[0];\n"; 707 teseNeeded = DE_TRUE; 708 break; 709 710 case PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN: 711 // passthrough sources 712 teseNeeded = DE_TRUE; 713 break; 714 715 default: 716 break; 717 } 718 719 std::string teseSource = teseNeeded ? 720 StringTemplate( 721 "#version 450\n" 722 "#extension GL_EXT_tessellation_shader : require\n\n" 723 "layout(triangles) in;\n" 724 "${DECLARATIONS}" 725 "void main(void)\n" 726 "{\n" 727 " gl_Position = vec4(gl_TessCoord.xy * 2.0 - 1.0, 0.0, 1.0);\n" 728 "${OPERATIONS}" 729 "}\n").specialize(specializationMap) 730 : ""; 731 732 DE_ASSERT(tescSource.empty() == teseSource.empty()); 733 if (!tescSource.empty()) 734 { 735 glslSources.add("tesc") << glu::TessellationControlSource(tescSource); 736 glslSources.add("tese") << glu::TessellationEvaluationSource(teseSource); 737 } 738 739 // define geometry shader source 740 bool geomNeeded = DE_FALSE; 741 switch (m_params->pipelineType) 742 { 743 case PipelineType::VERT_GEOM_OUT_FRAG_IN: 744 case PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN: 745 declarations = outDeclaration; 746 operations = outValueAssignment; 747 geomNeeded = DE_TRUE; 748 break; 749 750 case PipelineType::VERT_OUT_GEOM_IN_FRAG: 751 case PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG: 752 declarations = inDeclaration + 753 "layout(location = 0) out float result;\n"; 754 operations = inValueVerification; 755 geomNeeded = DE_TRUE; 756 break; 757 758 case PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG: 759 declarations = "layout(location = 0) in float inResult[];\n" 760 "layout(location = 0) out float outResult;\n"; 761 operations = " outResult = inResult[0];\n"; 762 geomNeeded = DE_TRUE; 763 break; 764 765 default: 766 break; 767 } 768 769 if (geomNeeded) 770 { 771 tcu::StringTemplate geomTemplate( 772 "#version 450\n" 773 "#extension GL_EXT_geometry_shader : require\n" 774 "layout(triangles) in;\n" 775 "layout(triangle_strip, max_vertices=3) out;\n" 776 "${DECLARATIONS}" 777 "void main(void)\n" 778 "{\n" 779 "${OPERATIONS}" 780 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n" 781 " EmitVertex();\n" 782 "${OPERATIONS}" 783 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 784 " EmitVertex();\n" 785 "${OPERATIONS}" 786 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 787 " EmitVertex();\n" 788 " EndPrimitive();\n" 789 "}\n"); 790 glslSources.add("geom") << glu::GeometrySource(geomTemplate.specialize(specializationMap)); 791 } 792 793 // define fragment shader source 794 if (isPipelineOneOf(m_params->pipelineType, { 795 PipelineType::VERT_OUT_FRAG_IN, 796 PipelineType::VERT_TESC_TESE_OUT_FRAG_IN, 797 PipelineType::VERT_GEOM_OUT_FRAG_IN, 798 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN })) 799 { 800 declarations = inDeclaration; 801 operations = " float result = 0.0;\n" + 802 inValueVerification; 803 } 804 else // passthrough source 805 { 806 declarations = "layout(location = 0) in flat float result;\n"; 807 operations = ""; 808 } 809 810 tcu::StringTemplate fragTemplate( 811 "#version 450\n" 812 "layout(location = 0) out vec4 fragColor;\n" 813 "${DECLARATIONS}" 814 "void main(void)\n" 815 "{\n" 816 "${OPERATIONS}" 817 " fragColor = vec4(result);\n" 818 "}\n"); 819 glslSources.add("frag") << glu::FragmentSource(fragTemplate.specialize(specializationMap)); 820} 821 822std::string InterfaceMatchingTestCase::genOutAssignment(const std::string& variableName, const VecData& outVecData) const 823{ 824 // generate value assignment to out variable; 825 // for vec2/looseVariable this will generate: 826 // "looseVariable = vec2(-2.0, 3.0);" 827 828 // define separators to avoid if statements in loop 829 std::string outSeparator(", "); 830 std::string endSeparator(""); 831 std::vector<std::string*> outSeparators(4, &outSeparator); 832 outSeparators[outVecData.componentsCount - 1] = &endSeparator; 833 834 // generate value assignment 835 std::string outValueAssignment = std::string(" ") + variableName + " = " + outVecData.glslType + "("; 836 for (deUint32 i = 0; i < outVecData.componentsCount; ++i) 837 outValueAssignment += outVecData.components[i] + *outSeparators[i]; 838 839 return outValueAssignment + ");\n"; 840} 841 842std::string InterfaceMatchingTestCase::genInVerification(const std::string& variableName, const VecData& outVecData, const VecData& inVecData) const 843{ 844 // generate value verification; 845 // note that input has same or less components then output; 846 // for vec2/looseVariable this will generate: 847 // "result = float(abs(looseVariable.x - -2.0) < eps) *" 848 // "float(abs(looseVariable.y - 3.0) < eps);\n" 849 850 static const std::string componentNames[] = { "x", "y", "z", "w" }; 851 852 // define separators to avoid if statements in loop 853 std::string inSeparator (" *\n\t\t "); 854 std::string endSeparator (""); 855 std::string* inSeparators[] { &inSeparator, &inSeparator, &inSeparator, &endSeparator }; 856 857 inSeparators[inVecData.componentsCount - 1] = &endSeparator; 858 859 std::string inValueVerification(" result = "); 860 tcu::StringTemplate verificationTemplate( 861 inVecData.componentType == ComponentType::FLOAT ? 862 "float(abs(" + variableName + ".${COMPONENT} - ${VALUE}) < 0.001)" : 863 "float(" + variableName + ".${COMPONENT} == ${VALUE})"); 864 865 // verify each component using formula for float or int 866 for (deUint32 i = 0; i < inVecData.componentsCount; ++i) 867 { 868 inValueVerification += verificationTemplate.specialize({ 869 { "COMPONENT", componentNames[i] }, 870 { "VALUE", outVecData.components[i] } 871 }); 872 inValueVerification += *inSeparators[i]; 873 } 874 875 return inValueVerification + ";\n"; 876} 877 878void InterfaceMatchingTestCase::checkSupport(Context& context) const 879{ 880 if (m_params->pipelineConstructionType != PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) 881 { 882 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params->pipelineConstructionType); 883 884 // if graphicsPipelineLibraryIndependentInterpolationDecoration is VK_FALSE then interface mismatch 885 // tests involving the Flat or NoPerspective qualifiers should be skipped for pipeline library tests 886#ifndef CTS_USES_VULKANSC 887 if (!context.getGraphicsPipelineLibraryPropertiesEXT().graphicsPipelineLibraryIndependentInterpolationDecoration) 888 { 889 if ((m_params->inDeclDecoration == DecorationType::FLAT) || 890 (m_params->inDeclDecoration == DecorationType::NO_PERSPECTIVE) || 891 (m_params->outDeclDecoration == DecorationType::FLAT) || 892 (m_params->outDeclDecoration == DecorationType::NO_PERSPECTIVE)) 893 TCU_THROW(NotSupportedError, "graphicsPipelineLibraryIndependentInterpolationDecoration is not supported"); 894 } 895#endif // CTS_USES_VULKANSC 896 } 897 898 // when outputs from earlier stage are matched with smaller 899 // inputs in future stage request VK_KHR_maintenance4 900 if ((m_params->testType == TestType::VECTOR_LENGTH) && 901 (m_params->outVecType != m_params->inVecType)) 902 { 903 context.requireDeviceFunctionality("VK_KHR_maintenance4"); 904 } 905 906 const InstanceInterface& vki = context.getInstanceInterface(); 907 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 908 const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physicalDevice); 909 910 if (isPipelineOneOf(m_params->pipelineType, { 911 PipelineType::VERT_OUT_TESC_IN_TESE_FRAG, 912 PipelineType::VERT_TESC_TESE_OUT_FRAG_IN, 913 PipelineType::VERT_TESC_OUT_TESE_IN_FRAG, 914 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG, 915 PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG, 916 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN })) 917 if (!features.tessellationShader) 918 TCU_THROW(NotSupportedError, "Tessellation shader not supported"); 919 920 if (isPipelineOneOf(m_params->pipelineType, { 921 PipelineType::VERT_OUT_GEOM_IN_FRAG, 922 PipelineType::VERT_GEOM_OUT_FRAG_IN, 923 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG, 924 PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG, 925 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN })) 926 if (!features.geometryShader) 927 TCU_THROW(NotSupportedError, "Geometry shader not supported"); 928} 929 930TestInstance* InterfaceMatchingTestCase::createInstance(Context& context) const 931{ 932 return new InterfaceMatchingTestInstance(context, m_params); 933} 934 935const InterfaceMatchingTestCase::VecData& InterfaceMatchingTestCase::getVecData(VecType vecType) const 936{ 937 static const std::map<VecType, VecData> vecDataMap 938 { 939 { VecType::VEC2, { "vec2", ComponentType::FLOAT, 2, { "-2.0", "3.0", "", "" } } }, 940 { VecType::VEC3, { "vec3", ComponentType::FLOAT, 3, { "-3.0", "2.0", "5.0", "" } } }, 941 { VecType::VEC4, { "vec4", ComponentType::FLOAT, 4, { "-4.0", "-9.0", "3.0", "7.0" } } }, 942 { VecType::IVEC2, { "ivec2", ComponentType::INT, 2, { "-4", "8", "", "" } } }, 943 { VecType::IVEC3, { "ivec3", ComponentType::INT, 3, { "-5", "10", "15", "" } } }, 944 { VecType::IVEC4, { "ivec4", ComponentType::INT, 4, { "-16", "12", "20", "80" } } }, 945 { VecType::UVEC2, { "uvec2", ComponentType::UINT, 2, { "2", "8", "", "" } } }, 946 { VecType::UVEC3, { "uvec3", ComponentType::UINT, 3, { "3", "9", "27", "" } } }, 947 { VecType::UVEC4, { "uvec4", ComponentType::UINT, 4, { "4", "16", "64", "256" } } }, 948 }; 949 950 DE_ASSERT(vecDataMap.find(vecType) != vecDataMap.end()); 951 return vecDataMap.at(vecType); 952} 953 954const InterfaceMatchingTestCase::DecorationData& InterfaceMatchingTestCase::getDecorationData(DecorationType decorationType) const 955{ 956 static const std::map<DecorationType, DecorationData> decorationDataMap 957 { 958 { DecorationType::NONE, { "none", "", "" } }, 959 { DecorationType::FLAT, { "flat", "flat ", "" } }, 960 { DecorationType::NO_PERSPECTIVE, { "noperspective", "noperspective ", "" } }, 961 { DecorationType::COMPONENT0, { "component0", "", ", component = 0 " } }, 962 }; 963 964 DE_ASSERT(decorationDataMap.find(decorationType) != decorationDataMap.end()); 965 return decorationDataMap.at(decorationType); 966} 967 968const InterfaceMatchingTestCase::PipelineData& InterfaceMatchingTestCase::getPipelineData(PipelineType pipelineType) const 969{ 970 // pipelineDataMap is used to simplify generation of declarations in glsl 971 // it represent fallowing rules: 972 // * for case where tesc outputs variable it must be declarred as an array 973 // * when frag input variable is verified we need to use flat interpolation 974 // * all stages except for frag need input to be array (note: we do not use input in vert) 975 976 static const std::map<PipelineType, PipelineData> pipelineDataMap 977 { 978 // outArr inFlat inArr 979 { PipelineType::VERT_OUT_FRAG_IN, { 0, 1, 0 } }, 980 { PipelineType::VERT_OUT_TESC_IN_TESE_FRAG, { 0, 0, 1 } }, 981 { PipelineType::VERT_TESC_TESE_OUT_FRAG_IN, { 0, 1, 0 } }, 982 { PipelineType::VERT_TESC_OUT_TESE_IN_FRAG, { 1, 0, 1 } }, 983 { PipelineType::VERT_OUT_GEOM_IN_FRAG, { 0, 0, 1 } }, 984 { PipelineType::VERT_GEOM_OUT_FRAG_IN, { 0, 1, 0 } }, 985 { PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG, { 0, 0, 1 } }, 986 { PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG, { 0, 0, 1 } }, 987 { PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN, { 0, 1, 0 } }, 988 }; 989 990 DE_ASSERT(pipelineDataMap.find(pipelineType) != pipelineDataMap.end()); 991 return pipelineDataMap.at(pipelineType); 992} 993 994std::string InterfaceMatchingTestCase::generateName(const TestParams& testParams) const 995{ 996 static const std::map<PipelineType, std::string> pipelineTypeMap 997 { 998 { PipelineType::VERT_OUT_FRAG_IN, "vert_out_frag_in" }, 999 { PipelineType::VERT_OUT_TESC_IN_TESE_FRAG, "vert_out_tesc_in_tese_frag" }, 1000 { PipelineType::VERT_TESC_TESE_OUT_FRAG_IN, "vert_tesc_tese_out_frag_in" }, 1001 { PipelineType::VERT_TESC_OUT_TESE_IN_FRAG, "vert_tesc_out_tese_in_frag" }, 1002 { PipelineType::VERT_OUT_GEOM_IN_FRAG, "vert_out_geom_in_frag" }, 1003 { PipelineType::VERT_GEOM_OUT_FRAG_IN, "vert_geom_out_frag_in" }, 1004 { PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG, "vert_out_tesc_in_tese_geom_frag" }, 1005 { PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG, "vert_tesc_tese_out_geom_in_frag" }, 1006 { PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN, "vert_tesc_tese_geom_out_frag_in" }, 1007 }; 1008 1009 static const std::map <DefinitionType, std::string> definitionTypeMap 1010 { 1011 { DefinitionType::LOOSE_VARIABLE, "loose_variable" }, 1012 { DefinitionType::MEMBER_OF_BLOCK, "member_of_block" }, 1013 { DefinitionType::MEMBER_OF_STRUCTURE, "member_of_structure" }, 1014 { DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES, "member_of_array_of_structures" }, 1015 { DefinitionType::MEMBER_OF_STRUCTURE_IN_BLOCK, "member_of_structure_in_block" }, 1016 { DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES_IN_BLOCK, "member_of_array_of_structures_in_block" }, 1017 }; 1018 1019 DE_ASSERT(pipelineTypeMap.find(testParams.pipelineType) != pipelineTypeMap.end()); 1020 DE_ASSERT(definitionTypeMap.find(testParams.definitionType) != definitionTypeMap.end()); 1021 1022 std::string caseName; 1023 1024 if (testParams.testType == TestType::VECTOR_LENGTH) 1025 caseName = "out_" + getVecData(testParams.outVecType).glslType + 1026 "_in_" + getVecData(testParams.inVecType).glslType; 1027 else 1028 caseName = "out_" + getDecorationData(testParams.outDeclDecoration).namePart + 1029 "_in_" + getDecorationData(testParams.inDeclDecoration).namePart; 1030 1031 return caseName + "_" + 1032 definitionTypeMap.at(testParams.definitionType) + "_" + 1033 pipelineTypeMap.at(testParams.pipelineType); 1034}; 1035 1036} // anonymous 1037 1038tcu::TestCaseGroup* createInterfaceMatchingTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType) 1039{ 1040 VecType vecTypeList[3][3] 1041 { 1042 { VecType::VEC4, VecType::VEC3, VecType::VEC2 }, // float 1043 { VecType::IVEC4, VecType::IVEC3, VecType::IVEC2 }, // int 1044 { VecType::UVEC4, VecType::UVEC3, VecType::UVEC2 }, // uint 1045 }; 1046 1047 PipelineType pipelineTypeList[] 1048 { 1049 PipelineType::VERT_OUT_FRAG_IN, 1050 PipelineType::VERT_OUT_TESC_IN_TESE_FRAG, 1051 PipelineType::VERT_TESC_TESE_OUT_FRAG_IN, 1052 PipelineType::VERT_TESC_OUT_TESE_IN_FRAG, 1053 PipelineType::VERT_OUT_GEOM_IN_FRAG, 1054 PipelineType::VERT_GEOM_OUT_FRAG_IN, 1055 PipelineType::VERT_OUT_TESC_IN_TESE_GEOM_FRAG, 1056 PipelineType::VERT_TESC_TESE_OUT_GEOM_IN_FRAG, 1057 PipelineType::VERT_TESC_TESE_GEOM_OUT_FRAG_IN, 1058 }; 1059 1060 DefinitionType definitionsTypeList[] 1061 { 1062 DefinitionType::LOOSE_VARIABLE, 1063 DefinitionType::MEMBER_OF_BLOCK, 1064 DefinitionType::MEMBER_OF_STRUCTURE, 1065 DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES, 1066 DefinitionType::MEMBER_OF_STRUCTURE_IN_BLOCK, 1067 DefinitionType::MEMBER_OF_ARRAY_OF_STRUCTURES_IN_BLOCK, 1068 }; 1069 1070 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "interface_matching")); 1071 1072 de::MovePtr<tcu::TestCaseGroup> vectorMatching(new tcu::TestCaseGroup(testCtx, "vector_length")); 1073 for (PipelineType pipelineType : pipelineTypeList) 1074 for (DefinitionType defType : definitionsTypeList) 1075 { 1076 // iterate over vector type - float, int or uint 1077 for (deUint32 vecDataFormat = 0; vecDataFormat < 3; ++vecDataFormat) 1078 { 1079 // iterate over all out/in lenght combinations 1080 const VecType* vecType = vecTypeList[vecDataFormat]; 1081 for (deUint32 outVecSizeIndex = 0; outVecSizeIndex < 3; ++outVecSizeIndex) 1082 { 1083 VecType outVecType = vecType[outVecSizeIndex]; 1084 for (deUint32 inVecSizeIndex = 0; inVecSizeIndex < 3; ++inVecSizeIndex) 1085 { 1086 VecType inVecType = vecType[inVecSizeIndex]; 1087 if (outVecType < inVecType) 1088 continue; 1089 1090 auto testParams = new TestParams 1091 { 1092 pipelineConstructionType, 1093 TestType::VECTOR_LENGTH, 1094 outVecType, 1095 inVecType, 1096 DecorationType::NONE, 1097 DecorationType::NONE, 1098 pipelineType, 1099 defType 1100 }; 1101 1102 vectorMatching->addChild(new InterfaceMatchingTestCase(testCtx, TestParamsSp(testParams))); 1103 } 1104 } 1105 } 1106 } 1107 testGroup->addChild(vectorMatching.release()); 1108 1109 std::vector<std::pair<DecorationType, DecorationType> > decorationPairs 1110 { 1111 { DecorationType::NONE, DecorationType::NO_PERSPECTIVE }, 1112 { DecorationType::NONE, DecorationType::FLAT }, 1113 { DecorationType::FLAT, DecorationType::NO_PERSPECTIVE }, 1114 { DecorationType::FLAT, DecorationType::NONE }, 1115 { DecorationType::NO_PERSPECTIVE, DecorationType::FLAT }, 1116 { DecorationType::NO_PERSPECTIVE, DecorationType::NONE }, 1117 { DecorationType::COMPONENT0, DecorationType::NONE }, 1118 { DecorationType::NONE, DecorationType::COMPONENT0 }, 1119 }; 1120 1121 de::MovePtr<tcu::TestCaseGroup> decorationMismatching(new tcu::TestCaseGroup(testCtx, "decoration_mismatch")); 1122 for (PipelineType stageType : pipelineTypeList) 1123 for (DefinitionType defType : definitionsTypeList) 1124 for (const auto& decoration : decorationPairs) 1125 { 1126 // tests component = 0 only for loose variables or member of block 1127 if (((decoration.first == DecorationType::COMPONENT0) || 1128 (decoration.second == DecorationType::COMPONENT0)) && 1129 ((defType != DefinitionType::LOOSE_VARIABLE) && 1130 (defType != DefinitionType::MEMBER_OF_BLOCK))) 1131 continue; 1132 1133 auto testParams = new TestParams 1134 { 1135 pipelineConstructionType, 1136 TestType::DECORATION_MISMATCH, 1137 VecType::VEC4, 1138 VecType::VEC4, 1139 decoration.first, 1140 decoration.second, 1141 stageType, 1142 defType 1143 }; 1144 decorationMismatching->addChild(new InterfaceMatchingTestCase(testCtx, TestParamsSp(testParams))); 1145 } 1146 1147 testGroup->addChild(decorationMismatching.release()); 1148 return testGroup.release(); 1149} 1150 1151} // pipeline 1152} // vkt 1153