1/*------------------------------------------------------------------------ 2* Vulkan Conformance Tests 3* ------------------------ 4* 5* Copyright (c) 2016 The Khronos Group Inc. 6* 7* Licensed under the Apache License, Version 2.0 (the "License"); 8* you may not use this file except in compliance with the License. 9* You may obtain a copy of the License at 10* 11* http://www.apache.org/licenses/LICENSE-2.0 12* 13* Unless required by applicable law or agreed to in writing, software 14* distributed under the License is distributed on an "AS IS" BASIS, 15* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16* See the License for the specific language governing permissions and 17* limitations under the License. 18* 19*//* 20* \file vktPipelineMultisampleInterpolationTests.cpp 21* \brief Multisample Interpolation Tests 22*//*--------------------------------------------------------------------*/ 23 24#include "vktPipelineMultisampleInterpolationTests.hpp" 25#include "vktPipelineMultisampleBaseResolve.hpp" 26#include "vktPipelineMultisampleTestsUtil.hpp" 27#include "vktPipelineMakeUtil.hpp" 28#include "vkQueryUtil.hpp" 29#include "tcuTestLog.hpp" 30#include <vector> 31 32namespace vkt 33{ 34namespace pipeline 35{ 36namespace multisample 37{ 38 39using namespace vk; 40 41struct VertexDataNdc 42{ 43 VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {} 44 45 tcu::Vec4 positionNdc; 46}; 47 48struct VertexDataNdcScreen 49{ 50 VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {} 51 52 tcu::Vec4 positionNdc; 53 tcu::Vec2 positionScreen; 54}; 55 56struct VertexDataNdcBarycentric 57{ 58 VertexDataNdcBarycentric (const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {} 59 60 tcu::Vec4 positionNdc; 61 tcu::Vec3 barycentricCoord; 62}; 63 64bool checkForError (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx) 65{ 66 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) 67 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) 68 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) 69 { 70 const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx]; 71 72 if (errorComponent > 0) 73 return true; 74 } 75 76 return false; 77} 78 79template <typename CaseClassName> 80class MSCase : public MultisampleCaseBase 81{ 82public: 83 MSCase (tcu::TestContext& testCtx, 84 const std::string& name, 85 const ImageMSParams& imageMSParams) 86 : MultisampleCaseBase(testCtx, name, imageMSParams) {} 87 88 void init (void); 89 void initPrograms (vk::SourceCollections& programCollection) const; 90 TestInstance* createInstance (Context& context) const; 91 static MultisampleCaseBase* createCase (tcu::TestContext& testCtx, 92 const std::string& name, 93 const ImageMSParams& imageMSParams); 94}; 95 96template <typename CaseClassName> 97MultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) 98{ 99 return new MSCase<CaseClassName>(testCtx, name, imageMSParams); 100} 101 102template <typename InstanceClassName> 103class MSInstance : public MSInstanceBaseResolve 104{ 105public: 106 MSInstance (Context& context, 107 const ImageMSParams& imageMSParams) 108 : MSInstanceBaseResolve(context, imageMSParams) {} 109 110 VertexDataDesc getVertexDataDescripton (void) const; 111 void uploadVertexData (const Allocation& vertexBufferAllocation, 112 const VertexDataDesc& vertexDataDescripton) const; 113 tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, 114 const tcu::ConstPixelBufferAccess& dataRS) const; 115}; 116 117class MSInstanceDistinctValues; 118 119template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceDistinctValues>::getVertexDataDescripton (void) const 120{ 121 VertexDataDesc vertexDataDesc; 122 123 vertexDataDesc.verticesCount = 3u; 124 vertexDataDesc.dataStride = sizeof(VertexDataNdc); 125 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; 126 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 127 128 const VkVertexInputAttributeDescription vertexAttribPositionNdc = 129 { 130 0u, // deUint32 location; 131 0u, // deUint32 binding; 132 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 133 DE_OFFSET_OF(VertexDataNdc, positionNdc), // deUint32 offset; 134 }; 135 136 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); 137 138 return vertexDataDesc; 139} 140 141template<> void MSInstance<MSInstanceDistinctValues>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 142{ 143 std::vector<VertexDataNdc> vertices; 144 145 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f))); 146 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f))); 147 vertices.push_back(VertexDataNdc(tcu::Vec4( 4.0f, -1.0f, 0.0f, 1.0f))); 148 149 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize)); 150} 151 152template<> tcu::TestStatus MSInstance<MSInstanceDistinctValues>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const 153{ 154 const deUint32 distinctValuesExpected = static_cast<deUint32>(m_imageMSParams.numSamples) + 1u; 155 156 std::vector<tcu::IVec4> distinctValues; 157 158 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) 159 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) 160 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) 161 { 162 const tcu::IVec4 pixel = dataRS.getPixelInt(x, y, z); 163 164 if (std::find(distinctValues.begin(), distinctValues.end(), pixel) == distinctValues.end()) 165 distinctValues.push_back(pixel); 166 } 167 168 if (distinctValues.size() >= distinctValuesExpected) 169 return tcu::TestStatus::pass("Passed"); 170 else 171 return tcu::TestStatus::fail("Expected numSamples+1 different colors in the output image"); 172} 173 174class MSCaseSampleQualifierDistinctValues; 175 176template<> void MSCase<MSCaseSampleQualifierDistinctValues>::init (void) 177{ 178 m_testCtx.getLog() 179 << tcu::TestLog::Message 180 << "Verifying that a sample qualified varying is given different values for different samples.\n" 181 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n" 182 << " => Resulting image should contain n+1 different colors, where n = sample count.\n" 183 << tcu::TestLog::EndMessage; 184 185 MultisampleCaseBase::init(); 186} 187 188template<> void MSCase<MSCaseSampleQualifierDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const 189{ 190 // Create vertex shader 191 std::ostringstream vs; 192 193 vs << "#version 440\n" 194 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 195 << "\n" 196 << "layout(location = 0) out vec4 vs_out_position_ndc;\n" 197 << "\n" 198 << "out gl_PerVertex {\n" 199 << " vec4 gl_Position;\n" 200 << "};\n" 201 << "void main (void)\n" 202 << "{\n" 203 << " gl_Position = vs_in_position_ndc;\n" 204 << " vs_out_position_ndc = vs_in_position_ndc;\n" 205 << "}\n"; 206 207 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 208 209 // Create fragment shader 210 std::ostringstream fs; 211 212 fs << "#version 440\n" 213 << "layout(location = 0) sample in vec4 fs_in_position_ndc;\n" 214 << "\n" 215 << "layout(location = 0) out vec4 fs_out_color;\n" 216 << "\n" 217 << "void main (void)\n" 218 << "{\n" 219 << " if(fs_in_position_ndc.y < -2.0*pow(0.5*(fs_in_position_ndc.x + 1.0), 2.0) + 1.0)\n" 220 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 221 << " else\n" 222 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 223 << "}\n"; 224 225 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 226} 227 228template<> TestInstance* MSCase<MSCaseSampleQualifierDistinctValues>::createInstance (Context& context) const 229{ 230 if (!context.getDeviceFeatures().sampleRateShading) 231 TCU_THROW(NotSupportedError, "sampleRateShading support required"); 232 return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams); 233} 234 235class MSCaseInterpolateAtSampleDistinctValues; 236 237template<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::init (void) 238{ 239 m_testCtx.getLog() 240 << tcu::TestLog::Message 241 << "Verifying that a interpolateAtSample returns different values for different samples.\n" 242 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n" 243 << " => Resulting image should contain n+1 different colors, where n = sample count.\n" 244 << tcu::TestLog::EndMessage; 245 246 MultisampleCaseBase::init(); 247} 248 249template<> void MSCase<MSCaseInterpolateAtSampleDistinctValues>::initPrograms (vk::SourceCollections& programCollection) const 250{ 251 // Create vertex shader 252 std::ostringstream vs; 253 254 vs << "#version 440\n" 255 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 256 << "\n" 257 << "layout(location = 0) out vec4 vs_out_position_ndc;\n" 258 << "\n" 259 << "out gl_PerVertex {\n" 260 << " vec4 gl_Position;\n" 261 << "};\n" 262 << "void main (void)\n" 263 << "{\n" 264 << " gl_Position = vs_in_position_ndc;\n" 265 << " vs_out_position_ndc = vs_in_position_ndc;\n" 266 << "}\n"; 267 268 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 269 270 // Create fragment shader 271 std::ostringstream fs; 272 273 fs << "#version 440\n" 274 << "layout(location = 0) in vec4 fs_in_position_ndc;\n" 275 << "\n" 276 << "layout(location = 0) out vec4 fs_out_color;\n" 277 << "\n" 278 << "void main (void)\n" 279 << "{\n" 280 << " const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n" 281 << " if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n" 282 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 283 << " else\n" 284 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 285 << "}\n"; 286 287 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 288} 289 290template<> TestInstance* MSCase<MSCaseInterpolateAtSampleDistinctValues>::createInstance (Context& context) const 291{ 292 if (!context.getDeviceFeatures().sampleRateShading) 293 TCU_THROW(NotSupportedError, "sampleRateShading support required"); 294 295 return new MSInstance<MSInstanceDistinctValues>(context, m_imageMSParams); 296} 297 298class MSInstanceInterpolateScreenPosition; 299 300template<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateScreenPosition>::getVertexDataDescripton (void) const 301{ 302 VertexDataDesc vertexDataDesc; 303 304 vertexDataDesc.verticesCount = 4u; 305 vertexDataDesc.dataStride = sizeof(VertexDataNdcScreen); 306 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; 307 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; 308 309 const VkVertexInputAttributeDescription vertexAttribPositionNdc = 310 { 311 0u, // deUint32 location; 312 0u, // deUint32 binding; 313 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 314 DE_OFFSET_OF(VertexDataNdcScreen, positionNdc), // deUint32 offset; 315 }; 316 317 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); 318 319 const VkVertexInputAttributeDescription vertexAttribPositionScreen = 320 { 321 1u, // deUint32 location; 322 0u, // deUint32 binding; 323 VK_FORMAT_R32G32_SFLOAT, // VkFormat format; 324 DE_OFFSET_OF(VertexDataNdcScreen, positionScreen), // deUint32 offset; 325 }; 326 327 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen); 328 329 return vertexDataDesc; 330} 331 332template<> void MSInstance<MSInstanceInterpolateScreenPosition>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 333{ 334 const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize); 335 const float screenSizeX = static_cast<float>(layerSize.x()); 336 const float screenSizeY = static_cast<float>(layerSize.y()); 337 338 std::vector<VertexDataNdcScreen> vertices; 339 340 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f))); 341 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f))); 342 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSizeY))); 343 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY))); 344 345 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize)); 346} 347 348template<> tcu::TestStatus MSInstance<MSInstanceInterpolateScreenPosition>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const 349{ 350 if (checkForError(imageRSInfo, dataRS, 0)) 351 return tcu::TestStatus::fail("Failed"); 352 353 return tcu::TestStatus::pass("Passed"); 354} 355 356class MSCaseInterpolateAtSampleSingleSample; 357 358template<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::init (void) 359{ 360 m_testCtx.getLog() 361 << tcu::TestLog::Message 362 << "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n" 363 << " Interpolate varying containing screen space location.\n" 364 << " => fract(screen space location) should be (about) (0.5, 0.5)\n" 365 << tcu::TestLog::EndMessage; 366 367 MultisampleCaseBase::init(); 368} 369 370template<> void MSCase<MSCaseInterpolateAtSampleSingleSample>::initPrograms (vk::SourceCollections& programCollection) const 371{ 372 // Create vertex shader 373 std::ostringstream vs; 374 375 vs << "#version 440\n" 376 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 377 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 378 << "\n" 379 << "layout(location = 0) out vec2 vs_out_position_screen;\n" 380 << "\n" 381 << "out gl_PerVertex {\n" 382 << " vec4 gl_Position;\n" 383 << "};\n" 384 << "void main (void)\n" 385 << "{\n" 386 << " gl_Position = vs_in_position_ndc;\n" 387 << " vs_out_position_screen = vs_in_position_screen;\n" 388 << "}\n"; 389 390 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 391 392 // Create fragment shader 393 std::ostringstream fs; 394 395 fs << "#version 440\n" 396 << "layout(location = 0) in vec2 fs_in_position_screen;\n" 397 << "\n" 398 << "layout(location = 0) out vec4 fs_out_color;\n" 399 << "\n" 400 << "void main (void)\n" 401 << "{\n" 402 << " const float threshold = 0.15625;\n" 403 << " const vec2 position_screen_at_sample = interpolateAtSample(fs_in_position_screen, 0);\n" 404 << " const vec2 position_inside_pixel = fract(position_screen_at_sample);\n" 405 << "\n" 406 << " if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= threshold)\n" 407 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 408 << " else\n" 409 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 410 << "}\n"; 411 412 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 413} 414 415template<> TestInstance* MSCase<MSCaseInterpolateAtSampleSingleSample>::createInstance (Context& context) const 416{ 417 if (!context.getDeviceFeatures().sampleRateShading) 418 TCU_THROW(NotSupportedError, "sampleRateShading support required"); 419 420 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 421} 422 423class MSCaseInterpolateAtSampleIgnoresCentroid; 424 425template<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::init (void) 426{ 427 m_testCtx.getLog() 428 << tcu::TestLog::Message 429 << "Verifying that interpolateAtSample ignores centroid qualifier.\n" 430 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n" 431 << " => interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n" 432 << tcu::TestLog::EndMessage; 433 434 MultisampleCaseBase::init(); 435} 436 437template<> void MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::initPrograms (vk::SourceCollections& programCollection) const 438{ 439 // Create vertex shader 440 std::ostringstream vs; 441 442 vs << "#version 440\n" 443 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 444 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 445 << "\n" 446 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n" 447 << "layout(location = 1) out vec2 vs_out_pos_screen_fragment;\n" 448 << "\n" 449 << "out gl_PerVertex {\n" 450 << " vec4 gl_Position;\n" 451 << "};\n" 452 << "void main (void)\n" 453 << "{\n" 454 << " gl_Position = vs_in_position_ndc;\n" 455 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n" 456 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n" 457 << "}\n"; 458 459 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 460 461 // Create fragment shader 462 std::ostringstream fs; 463 464 fs << "#version 440\n" 465 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n" 466 << "layout(location = 1) in vec2 fs_in_pos_screen_fragment;\n" 467 << "\n" 468 << "layout(location = 0) out vec4 fs_out_color;\n" 469 << "\n" 470 << "void main (void)\n" 471 << "{\n" 472 << " const float threshold = 0.0005;\n" 473 << "\n" 474 << " const vec2 position_a = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n" 475 << " const vec2 position_b = interpolateAtSample(fs_in_pos_screen_fragment, gl_SampleID);\n" 476 << " const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n" 477 << "\n" 478 << " if (valuesEqual)\n" 479 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 480 << " else\n" 481 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 482 << "}\n"; 483 484 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 485} 486 487template<> TestInstance* MSCase<MSCaseInterpolateAtSampleIgnoresCentroid>::createInstance (Context& context) const 488{ 489 if (!context.getDeviceFeatures().sampleRateShading) 490 TCU_THROW(NotSupportedError, "sampleRateShading support required"); 491 492 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 493} 494 495class MSCaseInterpolateAtSampleConsistency; 496 497template<> void MSCase<MSCaseInterpolateAtSampleConsistency>::init (void) 498{ 499 m_testCtx.getLog() 500 << tcu::TestLog::Message 501 << "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n" 502 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n" 503 << " => interpolateAtSample(screenCentroid, sampleID) = screenSample\n" 504 << tcu::TestLog::EndMessage; 505 506 MultisampleCaseBase::init(); 507} 508 509template<> void MSCase<MSCaseInterpolateAtSampleConsistency>::initPrograms (vk::SourceCollections& programCollection) const 510{ 511 // Create vertex shader 512 std::ostringstream vs; 513 514 vs << "#version 440\n" 515 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 516 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 517 << "\n" 518 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n" 519 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n" 520 << "\n" 521 << "out gl_PerVertex {\n" 522 << " vec4 gl_Position;\n" 523 << "};\n" 524 << "void main (void)\n" 525 << "{\n" 526 << " gl_Position = vs_in_position_ndc;\n" 527 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n" 528 << " vs_out_pos_screen_sample = vs_in_position_screen;\n" 529 << "}\n"; 530 531 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 532 533 // Create fragment shader 534 std::ostringstream fs; 535 536 fs << "#version 440\n" 537 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n" 538 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n" 539 << "\n" 540 << "layout(location = 0) out vec4 fs_out_color;\n" 541 << "\n" 542 << "void main (void)\n" 543 << "{\n" 544 << " const float threshold = 0.15625;\n" 545 << "\n" 546 << " const vec2 pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n" 547 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_sample - fs_in_pos_screen_sample), vec2(threshold)));\n" 548 << "\n" 549 << " if (valuesEqual)\n" 550 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 551 << " else\n" 552 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 553 << "}\n"; 554 555 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 556} 557 558template<> TestInstance* MSCase<MSCaseInterpolateAtSampleConsistency>::createInstance (Context& context) const 559{ 560 if (!context.getDeviceFeatures().sampleRateShading) 561 TCU_THROW(NotSupportedError, "sampleRateShading support required"); 562 563 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 564} 565 566class MSCaseInterpolateAtCentroidConsistency; 567 568template<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::init (void) 569{ 570 m_testCtx.getLog() 571 << tcu::TestLog::Message 572 << "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid qualified varying.\n" 573 << " Interpolate varying containing screen space location with sample and centroid qualifiers.\n" 574 << " => interpolateAtCentroid(screenSample) = screenCentroid\n" 575 << tcu::TestLog::EndMessage; 576 577 MultisampleCaseBase::init(); 578} 579 580template<> void MSCase<MSCaseInterpolateAtCentroidConsistency>::initPrograms (vk::SourceCollections& programCollection) const 581{ 582 // Create vertex shader 583 std::ostringstream vs; 584 585 vs << "#version 440\n" 586 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 587 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 588 << "\n" 589 << "layout(location = 0) out vec2 vs_out_pos_screen_sample;\n" 590 << "layout(location = 1) out vec2 vs_out_pos_screen_centroid;\n" 591 << "\n" 592 << "out gl_PerVertex {\n" 593 << " vec4 gl_Position;\n" 594 << "};\n" 595 << "void main (void)\n" 596 << "{\n" 597 << " gl_Position = vs_in_position_ndc;\n" 598 << " vs_out_pos_screen_sample = vs_in_position_screen;\n" 599 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n" 600 << "}\n"; 601 602 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 603 604 // Create fragment shader 605 std::ostringstream fs; 606 607 fs << "#version 440\n" 608 << "layout(location = 0) sample in vec2 fs_in_pos_screen_sample;\n" 609 << "layout(location = 1) centroid in vec2 fs_in_pos_screen_centroid;\n" 610 << "\n" 611 << "layout(location = 0) out vec4 fs_out_color;\n" 612 << "\n" 613 << "void main (void)\n" 614 << "{\n" 615 << " const float threshold = 0.0005;\n" 616 << "\n" 617 << " const vec2 pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample);\n" 618 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid), vec2(threshold)));\n" 619 << "\n" 620 << " if (valuesEqual)\n" 621 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 622 << " else\n" 623 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 624 << "}\n"; 625 626 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 627} 628 629template<> TestInstance* MSCase<MSCaseInterpolateAtCentroidConsistency>::createInstance (Context& context) const 630{ 631 if (!context.getDeviceFeatures().sampleRateShading) 632 TCU_THROW(NotSupportedError, "sampleRateShading support required"); 633 634 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 635} 636 637class MSCaseInterpolateAtOffsetPixelCenter; 638 639template<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::init (void) 640{ 641 m_testCtx.getLog() 642 << tcu::TestLog::Message 643 << "Verifying that interpolateAtOffset returns value sampled at an offset from the center of the pixel.\n" 644 << " Interpolate varying containing screen space location.\n" 645 << " => interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset" 646 << tcu::TestLog::EndMessage; 647 648 MultisampleCaseBase::init(); 649} 650 651template<> void MSCase<MSCaseInterpolateAtOffsetPixelCenter>::initPrograms (vk::SourceCollections& programCollection) const 652{ 653 // Create vertex shader 654 std::ostringstream vs; 655 656 vs << "#version 440\n" 657 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 658 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 659 << "\n" 660 << "layout(location = 0) out vec2 vs_out_pos_screen;\n" 661 << "layout(location = 1) out vec2 vs_out_offset;\n" 662 << "\n" 663 << "out gl_PerVertex {\n" 664 << " vec4 gl_Position;\n" 665 << "};\n" 666 << "void main (void)\n" 667 << "{\n" 668 << " gl_Position = vs_in_position_ndc;\n" 669 << " vs_out_pos_screen = vs_in_position_screen;\n" 670 << " vs_out_offset = vs_in_position_ndc.xy * 0.5;\n" 671 << "}\n"; 672 673 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 674 675 // Create fragment shader 676 std::ostringstream fs; 677 678 fs << "#version 440\n" 679 << "layout(location = 0) in vec2 fs_in_pos_screen;\n" 680 << "layout(location = 1) in vec2 fs_in_offset;\n" 681 << "\n" 682 << "layout(location = 0) out vec4 fs_out_color;\n" 683 << "\n" 684 << "void main (void)\n" 685 << "{\n" 686 << " const vec2 frag_center = interpolateAtOffset(fs_in_pos_screen, vec2(0.0));\n" 687 << " const vec2 center_diff = abs(frag_center - fs_in_pos_screen);\n" 688 << " const float threshold = 0.125;\n" 689 << " bool valuesEqual = false;\n" 690 << "\n" 691 << " if (all(lessThan(center_diff, vec2(0.5 + threshold)))) {\n" 692 << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen, fs_in_offset);\n" 693 << " const vec2 reference_value = frag_center + fs_in_offset;\n" 694 << "\n" 695 << " valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - reference_value), vec2(threshold)));\n" 696 << " }\n" 697 << "\n" 698 << " if (valuesEqual)\n" 699 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 700 << " else\n" 701 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 702 << "}\n"; 703 704 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 705} 706 707template<> TestInstance* MSCase<MSCaseInterpolateAtOffsetPixelCenter>::createInstance (Context& context) const 708{ 709 if (!context.getDeviceFeatures().sampleRateShading) 710 TCU_THROW(NotSupportedError, "sampleRateShading support required"); 711 712 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 713} 714 715class MSCaseInterpolateAtOffsetSamplePosition; 716 717template<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::init (void) 718{ 719 m_testCtx.getLog() 720 << tcu::TestLog::Message 721 << "Verifying that interpolateAtOffset of screen position with the offset of current sample position returns value " 722 << "similar to screen position interpolated at sample.\n" 723 << " Interpolate varying containing screen space location with and without sample qualifier.\n" 724 << " => interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample" 725 << tcu::TestLog::EndMessage; 726 727 MultisampleCaseBase::init(); 728} 729 730template<> void MSCase<MSCaseInterpolateAtOffsetSamplePosition>::initPrograms (vk::SourceCollections& programCollection) const 731{ 732 // Create vertex shader 733 std::ostringstream vs; 734 735 vs << "#version 440\n" 736 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 737 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 738 << "\n" 739 << "layout(location = 0) out vec2 vs_out_pos_screen_fragment;\n" 740 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n" 741 << "\n" 742 << "out gl_PerVertex {\n" 743 << " vec4 gl_Position;\n" 744 << "};\n" 745 << "void main (void)\n" 746 << "{\n" 747 << " gl_Position = vs_in_position_ndc;\n" 748 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n" 749 << " vs_out_pos_screen_sample = vs_in_position_screen;\n" 750 << "}\n"; 751 752 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 753 754 // Create fragment shader 755 std::ostringstream fs; 756 757 fs << "#version 440\n" 758 << "layout(location = 0) in vec2 fs_in_pos_screen_fragment;\n" 759 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n" 760 << "\n" 761 << "layout(location = 0) out vec4 fs_out_color;\n" 762 << "\n" 763 << "void main (void)\n" 764 << "{\n" 765 << " const float threshold = 0.15625;\n" 766 << "\n" 767 << " const vec2 offset = gl_SamplePosition - vec2(0.5, 0.5);\n" 768 << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment, offset);\n" 769 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - fs_in_pos_screen_sample), vec2(threshold)));\n" 770 << "\n" 771 << " if (valuesEqual)\n" 772 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 773 << " else\n" 774 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 775 << "}\n"; 776 777 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 778} 779 780template<> TestInstance* MSCase<MSCaseInterpolateAtOffsetSamplePosition>::createInstance (Context& context) const 781{ 782 if (!context.getDeviceFeatures().sampleRateShading) 783 TCU_THROW(NotSupportedError, "sampleRateShading support required"); 784 785 return new MSInstance<MSInstanceInterpolateScreenPosition>(context, m_imageMSParams); 786} 787 788class MSInstanceInterpolateBarycentricCoordinates; 789 790template<> MSInstanceBaseResolve::VertexDataDesc MSInstance<MSInstanceInterpolateBarycentricCoordinates>::getVertexDataDescripton (void) const 791{ 792 VertexDataDesc vertexDataDesc; 793 794 vertexDataDesc.verticesCount = 3u; 795 vertexDataDesc.dataStride = sizeof(VertexDataNdcBarycentric); 796 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; 797 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; 798 799 const VkVertexInputAttributeDescription vertexAttribPositionNdc = 800 { 801 0u, // deUint32 location; 802 0u, // deUint32 binding; 803 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 804 DE_OFFSET_OF(VertexDataNdcBarycentric, positionNdc), // deUint32 offset; 805 }; 806 807 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); 808 809 const VkVertexInputAttributeDescription vertexAttrBarCoord = 810 { 811 1u, // deUint32 location; 812 0u, // deUint32 binding; 813 VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format; 814 DE_OFFSET_OF(VertexDataNdcBarycentric, barycentricCoord), // deUint32 offset; 815 }; 816 817 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord); 818 819 return vertexDataDesc; 820} 821 822template<> void MSInstance<MSInstanceInterpolateBarycentricCoordinates>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 823{ 824 // Create buffer storing vertex data 825 std::vector<VertexDataNdcBarycentric> vertices; 826 827 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f))); 828 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f))); 829 vertices.push_back(VertexDataNdcBarycentric(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f))); 830 831 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize)); 832} 833 834template<> tcu::TestStatus MSInstance<MSInstanceInterpolateBarycentricCoordinates>::verifyImageData (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS) const 835{ 836 if (checkForError(imageRSInfo, dataRS, 0)) 837 return tcu::TestStatus::fail("Failed"); 838 839 return tcu::TestStatus::pass("Passed"); 840} 841 842class MSCaseCentroidQualifierInsidePrimitive; 843 844template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::init (void) 845{ 846 m_testCtx.getLog() 847 << tcu::TestLog::Message 848 << "Verifying that varying qualified with centroid is interpolated at location inside both the pixel and the primitive being processed.\n" 849 << " Interpolate triangle's barycentric coordinates with centroid qualifier.\n" 850 << " => After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n" 851 << tcu::TestLog::EndMessage; 852 853 MultisampleCaseBase::init(); 854} 855 856template<> void MSCase<MSCaseCentroidQualifierInsidePrimitive>::initPrograms (vk::SourceCollections& programCollection) const 857{ 858 // Create vertex shader 859 std::ostringstream vs; 860 861 vs << "#version 440\n" 862 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 863 << "layout(location = 1) in vec3 vs_in_barCoord;\n" 864 << "\n" 865 << "layout(location = 0) out vec3 vs_out_barCoord;\n" 866 << "\n" 867 << "out gl_PerVertex {\n" 868 << " vec4 gl_Position;\n" 869 << "};\n" 870 << "void main (void)\n" 871 << "{\n" 872 << " gl_Position = vs_in_position_ndc;\n" 873 << " vs_out_barCoord = vs_in_barCoord;\n" 874 << "}\n"; 875 876 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 877 878 // Create fragment shader 879 std::ostringstream fs; 880 881 fs << "#version 440\n" 882 << "layout(location = 0) centroid in vec3 fs_in_barCoord;\n" 883 << "\n" 884 << "layout(location = 0) out vec4 fs_out_color;\n" 885 << "\n" 886 << "void main (void)\n" 887 << "{\n" 888 << " if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) )\n" 889 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 890 << " else\n" 891 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 892 << "}\n"; 893 894 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 895} 896 897template<> TestInstance* MSCase<MSCaseCentroidQualifierInsidePrimitive>::createInstance (Context& context) const 898{ 899 return new MSInstance<MSInstanceInterpolateBarycentricCoordinates>(context, m_imageMSParams); 900} 901 902} // multisample 903 904tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testCtx) 905{ 906 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation", "Multisample Interpolation")); 907 908 const tcu::UVec3 imageSizes[] = 909 { 910 tcu::UVec3(128u, 128u, 1u), 911 tcu::UVec3(137u, 191u, 1u), 912 }; 913 914 const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3)); 915 916 const vk::VkSampleCountFlagBits imageSamples[] = 917 { 918 vk::VK_SAMPLE_COUNT_2_BIT, 919 vk::VK_SAMPLE_COUNT_4_BIT, 920 vk::VK_SAMPLE_COUNT_8_BIT, 921 vk::VK_SAMPLE_COUNT_16_BIT, 922 vk::VK_SAMPLE_COUNT_32_BIT, 923 vk::VK_SAMPLE_COUNT_64_BIT, 924 }; 925 926 const deUint32 samplesElemCount = static_cast<deUint32>(sizeof(imageSamples) / sizeof(vk::VkSampleCountFlagBits)); 927 928 de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolate_at_single_sample_", "")); 929 930 for (deUint32 imageSizeNdx = 0u; imageSizeNdx < sizesElemCount; ++imageSizeNdx) 931 { 932 const tcu::UVec3 imageSize = imageSizes[imageSizeNdx]; 933 std::ostringstream imageSizeStream; 934 935 imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z(); 936 937 de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), "")); 938 939 sizeGroup->addChild(multisample::MSCase<multisample::MSCaseInterpolateAtSampleSingleSample>::createCase(testCtx, "samples_" + de::toString(1), multisample::ImageMSParams(vk::VK_SAMPLE_COUNT_1_BIT, imageSize))); 940 941 caseGroup->addChild(sizeGroup.release()); 942 } 943 944 testGroup->addChild(caseGroup.release()); 945 946 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleDistinctValues> > (testCtx, "sample_interpolate_at_distinct_values", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 947 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleIgnoresCentroid> >(testCtx, "sample_interpolate_at_ignores_centroid", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 948 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtSampleConsistency> > (testCtx, "sample_interpolate_at_consistency", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 949 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleQualifierDistinctValues> > (testCtx, "sample_qualifier_distinct_values", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 950 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtCentroidConsistency> > (testCtx, "centroid_interpolate_at_consistency", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 951 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseCentroidQualifierInsidePrimitive> > (testCtx, "centroid_qualifier_inside_primitive", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 952 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetPixelCenter> > (testCtx, "offset_interpolate_at_pixel_center", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 953 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseInterpolateAtOffsetSamplePosition> > (testCtx, "offset_interpolate_at_sample_position", imageSizes, sizesElemCount, imageSamples, samplesElemCount)); 954 955 return testGroup.release(); 956} 957 958} // pipeline 959} // vkt 960