1/*------------------------------------------------------------------------ 2* Vulkan Conformance Tests 3* ------------------------ 4* 5* Copyright (c) 2016 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 vktPipelineMultisampleInterpolationTests.cpp 23* \brief Multisample Interpolation Tests 24*//*--------------------------------------------------------------------*/ 25 26#include "vktPipelineMultisampleInterpolationTests.hpp" 27#include "vktPipelineMultisampleBaseResolve.hpp" 28#include "vktPipelineMultisampleTestsUtil.hpp" 29#include "vktPipelineMakeUtil.hpp" 30#include "vktAmberTestCase.hpp" 31#include "vkQueryUtil.hpp" 32#include "tcuTestLog.hpp" 33#include <vector> 34 35namespace vkt 36{ 37namespace pipeline 38{ 39namespace multisample 40{ 41 42using namespace vk; 43 44struct VertexDataNdc 45{ 46 VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {} 47 48 tcu::Vec4 positionNdc; 49}; 50 51struct VertexDataNdcScreen 52{ 53 VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {} 54 55 tcu::Vec4 positionNdc; 56 tcu::Vec2 positionScreen; 57}; 58 59struct VertexDataNdcBarycentric 60{ 61 VertexDataNdcBarycentric (const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {} 62 63 tcu::Vec4 positionNdc; 64 tcu::Vec3 barycentricCoord; 65}; 66 67bool checkForError (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx) 68{ 69 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) 70 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) 71 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) 72 { 73 const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx]; 74 75 if (errorComponent > 0) 76 return true; 77 } 78 79 return false; 80} 81 82template <typename CaseClassName> 83class MSCase : public MultisampleCaseBase 84{ 85public: 86 MSCase (tcu::TestContext& testCtx, 87 const std::string& name, 88 const ImageMSParams& imageMSParams) 89 : MultisampleCaseBase(testCtx, name, imageMSParams) {} 90 91 void init (void); 92 void initPrograms (vk::SourceCollections& programCollection) const; 93 void checkSupport (Context& context) const; 94 TestInstance* createInstance (Context& context) const; 95 static MultisampleCaseBase* createCase (tcu::TestContext& testCtx, 96 const std::string& name, 97 const ImageMSParams& imageMSParams); 98}; 99 100template <typename CaseClassName> 101void MSCase<CaseClassName>::checkSupport (Context& context) const 102{ 103 checkGraphicsPipelineLibrarySupport(context); 104 105#ifndef CTS_USES_VULKANSC 106 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && 107 !context.getPortabilitySubsetFeatures().shaderSampleRateInterpolationFunctions) 108 { 109 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Shader sample rate interpolation functions are not supported by this implementation"); 110 } 111#endif // CTS_USES_VULKANSC 112 113 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 114} 115 116template <typename CaseClassName> 117MultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) 118{ 119 return new MSCase<CaseClassName>(testCtx, name, imageMSParams); 120} 121 122template <typename InstanceClassName> 123class MSInstance : public MSInstanceBaseResolve 124{ 125public: 126 MSInstance (Context& context, 127 const ImageMSParams& imageMSParams) 128 : MSInstanceBaseResolve(context, imageMSParams) {} 129 130 VertexDataDesc getVertexDataDescripton (void) const; 131 void uploadVertexData (const Allocation& vertexBufferAllocation, 132 const VertexDataDesc& vertexDataDescripton) const; 133 tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, 134 const tcu::ConstPixelBufferAccess& dataRS) const; 135}; 136 137class MSInstanceDistinctValues; 138 139template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceDistinctValues>::getVertexDataDescripton (void) const 140{ 141 VertexDataDesc vertexDataDesc; 142 143 vertexDataDesc.verticesCount = 3u; 144 vertexDataDesc.dataStride = sizeof(VertexDataNdc); 145 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; 146 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 147 148 const VkVertexInputAttributeDescription vertexAttribPositionNdc = 149 { 150 0u, // deUint32 location; 151 0u, // deUint32 binding; 152 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 153 DE_OFFSET_OF(VertexDataNdc, positionNdc), // deUint32 offset; 154 }; 155 156 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); 157 158 return vertexDataDesc; 159} 160 161template<> void MSInstance<MSInstanceDistinctValues>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 162{ 163 std::vector<VertexDataNdc> vertices; 164 165 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f))); 166 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f))); 167 vertices.push_back(VertexDataNdc(tcu::Vec4( 4.0f, -1.0f, 0.0f, 1.0f))); 168 169 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize)); 170} 171 172template<> tcu::TestStatus MSInstance<MSInstanceDistinctValues>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const 173{ 174 const deUint32 distinctValuesExpected = static_cast<deUint32>(m_imageMSParams.numSamples) + 1u; 175 176 std::vector<tcu::IVec4> distinctValues; 177 178 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) 179 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) 180 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) 181 { 182 const tcu::IVec4 pixel = dataRS.getPixelInt(x, y, z); 183 184 if (std::find(distinctValues.begin(), distinctValues.end(), pixel) == distinctValues.end()) 185 distinctValues.push_back(pixel); 186 } 187 188 if (distinctValues.size() >= distinctValuesExpected) 189 return tcu::TestStatus::pass("Passed"); 190 else 191 return tcu::TestStatus::fail("Expected numSamples+1 different colors in the output image"); 192} 193 194class MSCaseSampleQualifierDistinctValues; 195 196template<> void MSCase<MSCaseSampleQualifierDistinctValues>::init (void) 197{ 198 m_testCtx.getLog() 199 << tcu::TestLog::Message 200 << "Verifying that a sample qualified varying is given different values for different samples.\n" 201 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n" 202 << " => Resulting image should contain n+1 different colors, where n = sample count.\n" 203 << tcu::TestLog::EndMessage; 204 205 MultisampleCaseBase::init(); 206} 207 208template<> void MSCase<MSCaseSampleQualifierDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const 209{ 210 // Create vertex shader 211 std::ostringstream vs; 212 213 vs << "#version 440\n" 214 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 215 << "\n" 216 << "layout(location = 0) out vec4 vs_out_position_ndc;\n" 217 << "\n" 218 << "out gl_PerVertex {\n" 219 << " vec4 gl_Position;\n" 220 << "};\n" 221 << "void main (void)\n" 222 << "{\n" 223 << " gl_Position = vs_in_position_ndc;\n" 224 << " vs_out_position_ndc = vs_in_position_ndc;\n" 225 << "}\n"; 226 227 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 228 229 // Create fragment shader 230 std::ostringstream fs; 231 232 fs << "#version 440\n" 233 << "layout(location = 0) sample in vec4 fs_in_position_ndc;\n" 234 << "\n" 235 << "layout(location = 0) out vec4 fs_out_color;\n" 236 << "\n" 237 << "void main (void)\n" 238 << "{\n" 239 << " if(fs_in_position_ndc.y < -2.0*pow(0.5*(fs_in_position_ndc.x + 1.0), 2.0) + 1.0)\n" 240 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 241 << " else\n" 242 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 243 << "}\n"; 244 245 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 246} 247 248template<> void MSCase<MSCaseSampleQualifierDistinctValues>::checkSupport (Context& context) const 249{ 250 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_imageMSParams.pipelineConstructionType); 251 252 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 253} 254 255template<> TestInstance* MSCase<MSCaseSampleQualifierDistinctValues>::createInstance (Context& context) const 256{ 257 return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams); 258} 259 260class MSCaseInterpolateAtSampleDistinctValues; 261 262template<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::init (void) 263{ 264 m_testCtx.getLog() 265 << tcu::TestLog::Message 266 << "Verifying that a interpolateAtSample returns different values for different samples.\n" 267 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n" 268 << " => Resulting image should contain n+1 different colors, where n = sample count.\n" 269 << tcu::TestLog::EndMessage; 270 271 MultisampleCaseBase::init(); 272} 273 274template<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const 275{ 276 // Create vertex shader 277 std::ostringstream vs; 278 279 vs << "#version 440\n" 280 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 281 << "\n" 282 << "layout(location = 0) out vec4 vs_out_position_ndc;\n" 283 << "\n" 284 << "out gl_PerVertex {\n" 285 << " vec4 gl_Position;\n" 286 << "};\n" 287 << "void main (void)\n" 288 << "{\n" 289 << " gl_Position = vs_in_position_ndc;\n" 290 << " vs_out_position_ndc = vs_in_position_ndc;\n" 291 << "}\n"; 292 293 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 294 295 // Create fragment shader 296 std::ostringstream fs; 297 298 fs << "#version 440\n" 299 << "layout(location = 0) in vec4 fs_in_position_ndc;\n" 300 << "\n" 301 << "layout(location = 0) out vec4 fs_out_color;\n" 302 << "\n" 303 << "void main (void)\n" 304 << "{\n" 305 << " const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n" 306 << " if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n" 307 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 308 << " else\n" 309 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 310 << "}\n"; 311 312 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 313} 314 315template<> TestInstance* MSCase<MSCaseInterpolateAtSampleDistinctValues>::createInstance (Context& context) const 316{ 317 return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams); 318} 319 320class MSInstanceInterpolateScreenPosition; 321 322template<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateScreenPosition>::getVertexDataDescripton (void) const 323{ 324 VertexDataDesc vertexDataDesc; 325 326 vertexDataDesc.verticesCount = 4u; 327 vertexDataDesc.dataStride = sizeof(VertexDataNdcScreen); 328 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; 329 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; 330 331 const VkVertexInputAttributeDescription vertexAttribPositionNdc = 332 { 333 0u, // deUint32 location; 334 0u, // deUint32 binding; 335 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 336 DE_OFFSET_OF(VertexDataNdcScreen, positionNdc), // deUint32 offset; 337 }; 338 339 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); 340 341 const VkVertexInputAttributeDescription vertexAttribPositionScreen = 342 { 343 1u, // deUint32 location; 344 0u, // deUint32 binding; 345 VK_FORMAT_R32G32_SFLOAT, // VkFormat format; 346 DE_OFFSET_OF(VertexDataNdcScreen, positionScreen), // deUint32 offset; 347 }; 348 349 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen); 350 351 return vertexDataDesc; 352} 353 354template<> void MSInstance<MSInstanceInterpolateScreenPosition>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 355{ 356 const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize); 357 const float screenSizeX = static_cast<float>(layerSize.x()); 358 const float screenSizeY = static_cast<float>(layerSize.y()); 359 360 std::vector<VertexDataNdcScreen> vertices; 361 362 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f))); 363 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f))); 364 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSizeY))); 365 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY))); 366 367 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize)); 368} 369 370template<> tcu::TestStatus MSInstance<MSInstanceInterpolateScreenPosition>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const 371{ 372 if (checkForError(imageRSInfo, dataRS, 0)) 373 return tcu::TestStatus::fail("Failed"); 374 375 return tcu::TestStatus::pass("Passed"); 376} 377 378class MSCaseInterpolateAtSampleSingleSample; 379 380template<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::init (void) 381{ 382 m_testCtx.getLog() 383 << tcu::TestLog::Message 384 << "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n" 385 << " Interpolate varying containing screen space location.\n" 386 << " => fract(screen space location) should be (about) (0.5, 0.5)\n" 387 << tcu::TestLog::EndMessage; 388 389 MultisampleCaseBase::init(); 390} 391 392template<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::initPrograms (vk::SourceCollections& programCollection) const 393{ 394 // Create vertex shader 395 std::ostringstream vs; 396 397 vs << "#version 440\n" 398 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 399 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 400 << "\n" 401 << "layout(location = 0) out vec2 vs_out_position_screen;\n" 402 << "\n" 403 << "out gl_PerVertex {\n" 404 << " vec4 gl_Position;\n" 405 << "};\n" 406 << "void main (void)\n" 407 << "{\n" 408 << " gl_Position = vs_in_position_ndc;\n" 409 << " vs_out_position_screen = vs_in_position_screen;\n" 410 << "}\n"; 411 412 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 413 414 // Create fragment shader 415 std::ostringstream fs; 416 417 fs << "#version 440\n" 418 << "layout(location = 0) in vec2 fs_in_position_screen;\n" 419 << "\n" 420 << "layout(location = 0) out vec4 fs_out_color;\n" 421 << "\n" 422 << "void main (void)\n" 423 << "{\n" 424 << " const float threshold = 0.15625;\n" 425 << " const vec2 position_screen_at_sample = interpolateAtSample(fs_in_position_screen, 0);\n" 426 << " const vec2 position_inside_pixel = fract(position_screen_at_sample);\n" 427 << "\n" 428 << " if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= threshold)\n" 429 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 430 << " else\n" 431 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 432 << "}\n"; 433 434 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 435} 436 437template<> TestInstance* MSCase<MSCaseInterpolateAtSampleSingleSample>::createInstance (Context& context) const 438{ 439 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 440} 441 442class MSCaseInterpolateAtSampleIgnoresCentroid; 443 444template<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::init (void) 445{ 446 m_testCtx.getLog() 447 << tcu::TestLog::Message 448 << "Verifying that interpolateAtSample ignores centroid qualifier.\n" 449 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n" 450 << " => interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n" 451 << tcu::TestLog::EndMessage; 452 453 MultisampleCaseBase::init(); 454} 455 456template<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::initPrograms (vk::SourceCollections& programCollection) const 457{ 458 // Create vertex shader 459 std::ostringstream vs; 460 461 vs << "#version 440\n" 462 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 463 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 464 << "\n" 465 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n" 466 << "layout(location = 1) out vec2 vs_out_pos_screen_fragment;\n" 467 << "\n" 468 << "out gl_PerVertex {\n" 469 << " vec4 gl_Position;\n" 470 << "};\n" 471 << "void main (void)\n" 472 << "{\n" 473 << " gl_Position = vs_in_position_ndc;\n" 474 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n" 475 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n" 476 << "}\n"; 477 478 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 479 480 // Create fragment shader 481 std::ostringstream fs; 482 483 fs << "#version 440\n" 484 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n" 485 << "layout(location = 1) in vec2 fs_in_pos_screen_fragment;\n" 486 << "\n" 487 << "layout(location = 0) out vec4 fs_out_color;\n" 488 << "\n" 489 << "void main (void)\n" 490 << "{\n" 491 << " const float threshold = 0.0005;\n" 492 << "\n" 493 << " const vec2 position_a = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n" 494 << " const vec2 position_b = interpolateAtSample(fs_in_pos_screen_fragment, gl_SampleID);\n" 495 << " const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n" 496 << "\n" 497 << " if (valuesEqual)\n" 498 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 499 << " else\n" 500 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 501 << "}\n"; 502 503 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 504} 505 506template<> TestInstance* MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::createInstance (Context& context) const 507{ 508 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 509} 510 511class MSCaseInterpolateAtSampleConsistency; 512 513template<> void MSCase<MSCaseInterpolateAtSampleConsistency>::init (void) 514{ 515 const std::string indexStr = de::toString(m_imageMSParams.componentData.index); 516 std::string componentMsg; 517 518 switch (m_imageMSParams.componentData.source) 519 { 520 case multisample::ComponentSource::CONSTANT: componentMsg = "Using single constant component " + indexStr; break; 521 case multisample::ComponentSource::PUSH_CONSTANT: componentMsg = "Using single component via push constant " + indexStr; break; 522 default: break; 523 } 524 525 m_testCtx.getLog() 526 << tcu::TestLog::Message 527 << "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n" 528 << (componentMsg.empty() ? std::string() : componentMsg + "\n") 529 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n" 530 << " => interpolateAtSample(screenCentroid, sampleID) = screenSample\n" 531 << tcu::TestLog::EndMessage; 532 533 MultisampleCaseBase::init(); 534} 535 536template<> void MSCase<MSCaseInterpolateAtSampleConsistency>::initPrograms (vk::SourceCollections& programCollection) const 537{ 538 // Create vertex shader 539 std::ostringstream vs; 540 541 vs << "#version 440\n" 542 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 543 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 544 << "\n" 545 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n" 546 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n" 547 << "\n" 548 << "out gl_PerVertex {\n" 549 << " vec4 gl_Position;\n" 550 << "};\n" 551 << "void main (void)\n" 552 << "{\n" 553 << " gl_Position = vs_in_position_ndc;\n" 554 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n" 555 << " vs_out_pos_screen_sample = vs_in_position_screen;\n" 556 << "}\n"; 557 558 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 559 560 // Create fragment shader 561 std::ostringstream fs; 562 563 fs << "#version 440\n" 564 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n" 565 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n" 566 << "\n" 567 << "layout(location = 0) out vec4 fs_out_color;\n" 568 << "\n"; 569 570 if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT) 571 { 572 fs << "layout(push_constant) uniform PushConstants {\n" 573 << " uint component;\n" 574 << "};\n" 575 << "\n"; 576 } 577 578 fs << "void main (void)\n" 579 << "{\n" 580 << " const float threshold = 0.15625;\n" 581 << "\n"; 582 583 if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE) 584 { 585 fs << " const vec2 pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n" 586 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_sample - fs_in_pos_screen_sample), vec2(threshold)));\n"; 587 } 588 else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT) 589 { 590 const auto& index = m_imageMSParams.componentData.index; 591 fs << " const float pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid[" << index << "], gl_SampleID);\n" 592 << " const bool valuesEqual = (abs(pos_interpolated_at_sample - fs_in_pos_screen_sample[" << index << "]) < threshold);\n"; 593 } 594 else // multisample::ComponentSource::PUSH_CONSTANT 595 { 596 fs << " const float pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid[component], gl_SampleID);\n" 597 << " const bool valuesEqual = (abs(pos_interpolated_at_sample - fs_in_pos_screen_sample[component]) < threshold);\n"; 598 } 599 600 fs << "\n" 601 << " if (valuesEqual)\n" 602 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 603 << " else\n" 604 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 605 << "}\n"; 606 607 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 608} 609 610template<> TestInstance* MSCase<MSCaseInterpolateAtSampleConsistency>::createInstance (Context& context) const 611{ 612 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 613} 614 615class MSCaseInterpolateAtCentroidConsistency; 616 617template<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::init (void) 618{ 619 const std::string indexStr = de::toString(m_imageMSParams.componentData.index); 620 std::string componentMsg; 621 622 switch (m_imageMSParams.componentData.source) 623 { 624 case multisample::ComponentSource::CONSTANT: componentMsg = "Using single constant component " + indexStr; break; 625 case multisample::ComponentSource::PUSH_CONSTANT: componentMsg = "Using single component via push constant " + indexStr; break; 626 default: break; 627 } 628 629 m_testCtx.getLog() 630 << tcu::TestLog::Message 631 << "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid qualified varying.\n" 632 << (componentMsg.empty() ? std::string() : componentMsg + "\n") 633 << " Interpolate varying containing screen space location with sample and centroid qualifiers.\n" 634 << " => interpolateAtCentroid(screenSample) = screenCentroid\n" 635 << tcu::TestLog::EndMessage; 636 637 MultisampleCaseBase::init(); 638} 639 640template<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::initPrograms (vk::SourceCollections& programCollection) const 641{ 642 // Create vertex shader 643 std::ostringstream vs; 644 645 vs << "#version 440\n" 646 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 647 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 648 << "\n" 649 << "layout(location = 0) out vec2 vs_out_pos_screen_sample[2];\n" 650 << "layout(location = 2) out vec2 vs_out_pos_screen_centroid[2];\n" 651 << "\n" 652 << "out gl_PerVertex {\n" 653 << " vec4 gl_Position;\n" 654 << "};\n" 655 << "void main (void)\n" 656 << "{\n" 657 << " gl_Position = vs_in_position_ndc;\n" 658 // Index 0 is never read, so we'll populate them with bad values 659 << " vs_out_pos_screen_sample[0] = vec2(-70.3, 42.1);\n" 660 << " vs_out_pos_screen_centroid[0] = vec2(7.7, -3.2);\n" 661 // Actual coordinates in index 1: 662 << " vs_out_pos_screen_sample[1] = vs_in_position_screen;\n" 663 << " vs_out_pos_screen_centroid[1] = vs_in_position_screen;\n" 664 << "}\n"; 665 666 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 667 668 // Create fragment shader 669 std::ostringstream fs; 670 671 fs << "#version 440\n" 672 << "layout(location = 0) sample in vec2 fs_in_pos_screen_sample[2];\n" 673 << "layout(location = 2) centroid in vec2 fs_in_pos_screen_centroid[2];\n" 674 << "\n" 675 << "layout(location = 0) out vec4 fs_out_color;\n" 676 << "\n"; 677 678 if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT) 679 { 680 fs << "layout(push_constant) uniform PushConstants {\n" 681 << " uint component;\n" 682 << "};\n" 683 << "\n"; 684 } 685 686 fs << "void main (void)\n" 687 << "{\n" 688 << " const float threshold = 0.0005;\n" 689 << "\n"; 690 691 if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE) 692 { 693 fs << " const vec2 pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample[1]);\n" 694 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid[1]), vec2(threshold)));\n"; 695 } 696 else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT) 697 { 698 const auto& index = m_imageMSParams.componentData.index; 699 fs << " const float pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample[1][" << index << "]);\n" 700 << " const bool valuesEqual = (abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid[1][" << index << "]) < threshold);\n"; 701 } 702 else // multisample::ComponentSource::PUSH_CONSTANT 703 { 704 fs << " const float pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample[1][component]);\n" 705 << " const bool valuesEqual = (abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid[1][component]) < threshold);\n"; 706 } 707 708 fs << "\n" 709 << " if (valuesEqual)\n" 710 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 711 << " else\n" 712 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 713 << "}\n"; 714 715 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 716} 717 718template<> TestInstance* MSCase<MSCaseInterpolateAtCentroidConsistency>::createInstance (Context& context) const 719{ 720 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 721} 722 723class MSCaseInterpolateAtOffsetPixelCenter; 724 725template<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::init (void) 726{ 727 m_testCtx.getLog() 728 << tcu::TestLog::Message 729 << "Verifying that interpolateAtOffset returns value sampled at an offset from the center of the pixel.\n" 730 << " Interpolate varying containing screen space location.\n" 731 << " => interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset" 732 << tcu::TestLog::EndMessage; 733 734 MultisampleCaseBase::init(); 735} 736 737template<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::initPrograms (vk::SourceCollections& programCollection) const 738{ 739 // Create vertex shader 740 std::ostringstream vs; 741 742 vs << "#version 440\n" 743 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 744 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 745 << "\n" 746 << "layout(location = 0) out vec2 vs_out_pos_screen;\n" 747 << "layout(location = 1) out vec2 vs_out_offset;\n" 748 << "\n" 749 << "out gl_PerVertex {\n" 750 << " vec4 gl_Position;\n" 751 << "};\n" 752 << "void main (void)\n" 753 << "{\n" 754 << " gl_Position = vs_in_position_ndc;\n" 755 << " vs_out_pos_screen = vs_in_position_screen;\n" 756 << " vs_out_offset = vs_in_position_ndc.xy * 0.5;\n" 757 << "}\n"; 758 759 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 760 761 // Create fragment shader 762 std::ostringstream fs; 763 764 fs << "#version 440\n" 765 << "layout(location = 0) in vec2 fs_in_pos_screen;\n" 766 << "layout(location = 1) in vec2 fs_in_offset;\n" 767 << "\n" 768 << "layout(location = 0) out vec4 fs_out_color;\n" 769 << "\n" 770 << "void main (void)\n" 771 << "{\n" 772 << " const vec2 frag_center = interpolateAtOffset(fs_in_pos_screen, vec2(0.0));\n" 773 << " const vec2 center_diff = abs(frag_center - fs_in_pos_screen);\n" 774 << " const float threshold = 0.125;\n" 775 << " bool valuesEqual = false;\n" 776 << "\n" 777 << " if (all(lessThan(center_diff, vec2(0.5 + threshold)))) {\n" 778 << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen, fs_in_offset);\n" 779 << " const vec2 reference_value = frag_center + fs_in_offset;\n" 780 << "\n" 781 << " valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - reference_value), vec2(threshold)));\n" 782 << " }\n" 783 << "\n" 784 << " if (valuesEqual)\n" 785 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 786 << " else\n" 787 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 788 << "}\n"; 789 790 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 791} 792 793template<> TestInstance* MSCase<MSCaseInterpolateAtOffsetPixelCenter>::createInstance (Context& context) const 794{ 795 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 796} 797 798class MSCaseInterpolateAtOffsetSamplePosition; 799 800template<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::init (void) 801{ 802 const std::string indexStr = de::toString(m_imageMSParams.componentData.index); 803 std::string componentMsg; 804 805 switch (m_imageMSParams.componentData.source) 806 { 807 case multisample::ComponentSource::CONSTANT: componentMsg = "Using single constant component " + indexStr; break; 808 case multisample::ComponentSource::PUSH_CONSTANT: componentMsg = "Using single component via push constant " + indexStr; break; 809 default: break; 810 } 811 812 m_testCtx.getLog() 813 << tcu::TestLog::Message 814 << "Verifying that interpolateAtOffset of screen position with the offset of current sample position returns value " 815 << "similar to screen position interpolated at sample.\n" 816 << (componentMsg.empty() ? std::string() : componentMsg + "\n") 817 << " Interpolate varying containing screen space location with and without sample qualifier.\n" 818 << " => interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample" 819 << tcu::TestLog::EndMessage; 820 821 MultisampleCaseBase::init(); 822} 823 824template<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::initPrograms (vk::SourceCollections& programCollection) const 825{ 826 // Create vertex shader 827 std::ostringstream vs; 828 829 vs << "#version 440\n" 830 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 831 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 832 << "\n" 833 << "layout(location = 0) out vec2 vs_out_pos_screen_fragment;\n" 834 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n" 835 << "\n" 836 << "out gl_PerVertex {\n" 837 << " vec4 gl_Position;\n" 838 << "};\n" 839 << "void main (void)\n" 840 << "{\n" 841 << " gl_Position = vs_in_position_ndc;\n" 842 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n" 843 << " vs_out_pos_screen_sample = vs_in_position_screen;\n" 844 << "}\n"; 845 846 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 847 848 // Create fragment shader 849 std::ostringstream fs; 850 851 fs << "#version 440\n" 852 << "layout(location = 0) in vec2 fs_in_pos_screen_fragment;\n" 853 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n" 854 << "\n" 855 << "layout(location = 0) out vec4 fs_out_color;\n" 856 << "\n"; 857 858 if (m_imageMSParams.componentData.source == multisample::ComponentSource::PUSH_CONSTANT) 859 { 860 fs << "layout(push_constant) uniform PushConstants {\n" 861 << " uint component;\n" 862 << "};\n" 863 << "\n"; 864 } 865 866 fs << "void main (void)\n" 867 << "{\n" 868 << " const float threshold = 0.15625;\n" 869 << "\n" 870 << " const vec2 offset = gl_SamplePosition - vec2(0.5, 0.5);\n"; 871 872 if (m_imageMSParams.componentData.source == multisample::ComponentSource::NONE) 873 { 874 fs << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment, offset);\n" 875 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - fs_in_pos_screen_sample), vec2(threshold)));\n"; 876 } 877 else if (m_imageMSParams.componentData.source == multisample::ComponentSource::CONSTANT) 878 { 879 const auto& index = m_imageMSParams.componentData.index; 880 fs << " const float pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment[" << index << "], offset);\n" 881 << " const bool valuesEqual = (abs(pos_interpolated_at_offset - fs_in_pos_screen_sample[" << index << "]) < threshold);\n"; 882 } 883 else // multisample::ComponentSource::PUSH_CONSTANT 884 { 885 fs << " const float pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment[component], offset);\n" 886 << " const bool valuesEqual = (abs(pos_interpolated_at_offset - fs_in_pos_screen_sample[component]) < threshold);\n"; 887 } 888 889 fs << "\n" 890 << " if (valuesEqual)\n" 891 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 892 << " else\n" 893 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 894 << "}\n"; 895 896 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 897} 898 899template<> TestInstance* MSCase<MSCaseInterpolateAtOffsetSamplePosition>::createInstance (Context& context) const 900{ 901 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 902} 903 904class MSInstanceInterpolateBarycentricCoordinates; 905 906template<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateBarycentricCoordinates>::getVertexDataDescripton (void) const 907{ 908 VertexDataDesc vertexDataDesc; 909 910 vertexDataDesc.verticesCount = 3u; 911 vertexDataDesc.dataStride = sizeof(VertexDataNdcBarycentric); 912 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; 913 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 914 915 const VkVertexInputAttributeDescription vertexAttribPositionNdc = 916 { 917 0u, // deUint32 location; 918 0u, // deUint32 binding; 919 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 920 DE_OFFSET_OF(VertexDataNdcBarycentric, positionNdc), // deUint32 offset; 921 }; 922 923 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); 924 925 const VkVertexInputAttributeDescription vertexAttrBarCoord = 926 { 927 1u, // deUint32 location; 928 0u, // deUint32 binding; 929 VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format; 930 DE_OFFSET_OF(VertexDataNdcBarycentric, barycentricCoord), // deUint32 offset; 931 }; 932 933 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord); 934 935 return vertexDataDesc; 936} 937 938template<> void MSInstance<MSInstanceInterpolateBarycentricCoordinates>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 939{ 940 // Create buffer storing vertex data 941 std::vector<VertexDataNdcBarycentric> vertices; 942 943 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f))); 944 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f))); 945 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f))); 946 947 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize)); 948} 949 950template<> tcu::TestStatus MSInstance<MSInstanceInterpolateBarycentricCoordinates>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const 951{ 952 if (checkForError(imageRSInfo, dataRS, 0)) 953 return tcu::TestStatus::fail("Failed"); 954 955 return tcu::TestStatus::pass("Passed"); 956} 957 958class MSCaseCentroidQualifierInsidePrimitive; 959 960template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::init (void) 961{ 962 m_testCtx.getLog() 963 << tcu::TestLog::Message 964 << "Verifying that varying qualified with centroid is interpolated at location inside both the pixel and the primitive being processed.\n" 965 << " Interpolate triangle's barycentric coordinates with centroid qualifier.\n" 966 << " => After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n" 967 << tcu::TestLog::EndMessage; 968 969 MultisampleCaseBase::init(); 970} 971 972template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::initPrograms (vk::SourceCollections& programCollection) const 973{ 974 // Create vertex shader 975 std::ostringstream vs; 976 977 vs << "#version 440\n" 978 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 979 << "layout(location = 1) in vec3 vs_in_barCoord;\n" 980 << "\n" 981 << "layout(location = 0) out vec3 vs_out_barCoord;\n" 982 << "\n" 983 << "out gl_PerVertex {\n" 984 << " vec4 gl_Position;\n" 985 << "};\n" 986 << "void main (void)\n" 987 << "{\n" 988 << " gl_Position = vs_in_position_ndc;\n" 989 << " vs_out_barCoord = vs_in_barCoord;\n" 990 << "}\n"; 991 992 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 993 994 // Create fragment shader 995 std::ostringstream fs; 996 997 fs << "#version 440\n" 998 << "layout(location = 0) centroid in vec3 fs_in_barCoord;\n" 999 << "\n" 1000 << "layout(location = 0) out vec4 fs_out_color;\n" 1001 << "\n" 1002 << "void main (void)\n" 1003 << "{\n" 1004 << " if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) )\n" 1005 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 1006 << " else\n" 1007 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 1008 << "}\n"; 1009 1010 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 1011} 1012 1013template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::checkSupport (Context& context) const 1014{ 1015 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_imageMSParams.pipelineConstructionType); 1016} 1017 1018template<> TestInstance* MSCase<MSCaseCentroidQualifierInsidePrimitive>::createInstance (Context& context) const 1019{ 1020 return new MSInstance<MSInstanceInterpolateBarycentricCoordinates>(context, m_imageMSParams); 1021} 1022 1023} // multisample 1024 1025tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType) 1026{ 1027 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation")); 1028 1029 const tcu::UVec3 imageSizes[] = 1030 { 1031 tcu::UVec3(128u, 128u, 1u), 1032 tcu::UVec3(137u, 191u, 1u), 1033 }; 1034 1035 const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3)); 1036 1037 const vk::VkSampleCountFlagBits imageSamples[] = 1038 { 1039 vk::VK_SAMPLE_COUNT_2_BIT, 1040 vk::VK_SAMPLE_COUNT_4_BIT, 1041 vk::VK_SAMPLE_COUNT_8_BIT, 1042 vk::VK_SAMPLE_COUNT_16_BIT, 1043 vk::VK_SAMPLE_COUNT_32_BIT, 1044 vk::VK_SAMPLE_COUNT_64_BIT, 1045 }; 1046 1047 const deUint32 samplesElemCount = static_cast<deUint32>(sizeof(imageSamples) / sizeof(vk::VkSampleCountFlagBits)); 1048 1049 de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolate_at_single_sample")); 1050 1051 for (deUint32 imageSizeNdx = 0u; imageSizeNdx < sizesElemCount; ++imageSizeNdx) 1052 { 1053 const tcu::UVec3 imageSize = imageSizes[imageSizeNdx]; 1054 std::ostringstream imageSizeStream; 1055 1056 imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z(); 1057 1058 de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str())); 1059 1060 multisample::ImageMSParams imageParams 1061 { 1062 pipelineConstructionType, 1063 vk::VK_SAMPLE_COUNT_1_BIT, 1064 imageSize, 1065 multisample::ComponentData{}, 1066 1.0f, 1067 }; 1068 sizeGroup->addChild(multisample::MSCase<multisample::MSCaseInterpolateAtSampleSingleSample>::createCase(testCtx, "samples_" + de::toString(1), imageParams)); 1069 1070 caseGroup->addChild(sizeGroup.release()); 1071 } 1072 1073 testGroup->addChild(caseGroup.release()); 1074 1075 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleDistinctValues> > (testCtx, "sample_interpolate_at_distinct_values", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 1076 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleIgnoresCentroid> >(testCtx, "sample_interpolate_at_ignores_centroid", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 1077 1078 // Test consistency in sample interpolation function 1079 de::MovePtr<tcu::TestCaseGroup> sampleGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolation_consistency")); 1080 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "all_components", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 1081 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u})); 1082 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u})); 1083 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "pushc_component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u})); 1084 sampleGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "pushc_component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u})); 1085 testGroup->addChild(sampleGroup.release()); 1086 1087 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleQualifierDistinctValues> > (testCtx, "sample_qualifier_distinct_values", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 1088 1089 de::MovePtr<tcu::TestCaseGroup> centroidGroup(new tcu::TestCaseGroup(testCtx, "centroid_interpolation_consistency", "Test consistency in centroid interpolation function")); 1090 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "all_components", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 1091 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u})); 1092 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u})); 1093 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "pushc_component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u})); 1094 centroidGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "pushc_component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u})); 1095 testGroup->addChild(centroidGroup.release()); 1096 1097#ifndef CTS_USES_VULKANSC 1098 // there is no support for pipelineConstructionType in amber 1099 if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) 1100 { 1101 de::MovePtr<tcu::TestCaseGroup> reInterpolationGroup(new tcu::TestCaseGroup(testCtx, "reinterpolation_consistency", "Test consistency in reinterpolation")); 1102 std::vector<std::string> requirements; 1103 requirements.push_back("Features.sampleRateShading"); 1104 reInterpolationGroup->addChild(cts_amber::createAmberTestCase(testCtx, "interpolate_at_centroid", "", "pipeline", "reinterpolate_at_centroid.amber", requirements)); 1105 reInterpolationGroup->addChild(cts_amber::createAmberTestCase(testCtx, "interpolate_at_sample", "", "pipeline", "reinterpolate_at_sample.amber", requirements)); 1106 testGroup->addChild(reInterpolationGroup.release()); 1107 1108 de::MovePtr<tcu::TestCaseGroup> nonuniformInterpolantIndexingGroup(new tcu::TestCaseGroup(testCtx, "nonuniform_interpolant_indexing", "Test nonuniform interpolant indexing")); 1109 std::vector<std::string> requirementsNonuniformIntepolantIndexing; 1110 requirementsNonuniformIntepolantIndexing.push_back("Features.sampleRateShading"); 1111 nonuniformInterpolantIndexingGroup->addChild(cts_amber::createAmberTestCase(testCtx, "centroid", "pipeline/nonuniform_interpolant_indexing", "centroid.amber", requirementsNonuniformIntepolantIndexing)); 1112 nonuniformInterpolantIndexingGroup->addChild(cts_amber::createAmberTestCase(testCtx, "sample", "pipeline/nonuniform_interpolant_indexing", "sample.amber", requirementsNonuniformIntepolantIndexing)); 1113 nonuniformInterpolantIndexingGroup->addChild(cts_amber::createAmberTestCase(testCtx, "offset", "pipeline/nonuniform_interpolant_indexing", "offset.amber", requirementsNonuniformIntepolantIndexing)); 1114 testGroup->addChild(nonuniformInterpolantIndexingGroup.release()); 1115 } 1116 1117 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseCentroidQualifierInsidePrimitive> > (testCtx, "centroid_qualifier_inside_primitive", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 1118#endif // CTS_USES_VULKANSC 1119 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetPixelCenter> > (testCtx, "offset_interpolate_at_pixel_center", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 1120 1121 de::MovePtr<tcu::TestCaseGroup> offsetGroup(new tcu::TestCaseGroup(testCtx, "offset_interpolation_at_sample_position", "Test interpolation at offset function works for sample positions")); 1122 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "all_components", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 1123 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 0u})); 1124 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::CONSTANT, 1u})); 1125 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "pushc_component_0", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 0u})); 1126 offsetGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "pushc_component_1", pipelineConstructionType, imageSizes, sizesElemCount, imageSamples, samplesElemCount, multisample::ComponentData{multisample::ComponentSource::PUSH_CONSTANT, 1u})); 1127 testGroup->addChild(offsetGroup.release()); 1128 1129 return testGroup.release(); 1130} 1131 1132} // pipeline 1133} // vkt 1134