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 vktPipelineMultisampleShaderBuiltInTests.cpp 23* \brief Multisample Shader BuiltIn Tests 24*//*--------------------------------------------------------------------*/ 25 26#include "vktPipelineMultisampleShaderBuiltInTests.hpp" 27#include "vktPipelineMultisampleBaseResolveAndPerSampleFetch.hpp" 28#include "vktPipelineMakeUtil.hpp" 29 30#include "vkBuilderUtil.hpp" 31#include "vkQueryUtil.hpp" 32#include "vkObjUtil.hpp" 33#include "vkImageWithMemory.hpp" 34#include "vkBufferWithMemory.hpp" 35#include "vkBarrierUtil.hpp" 36#include "vkCmdUtil.hpp" 37#include "vkTypeUtil.hpp" 38 39#include "tcuVectorUtil.hpp" 40#include "tcuTestLog.hpp" 41 42#include <set> 43#include <cmath> 44 45using std::set; 46 47namespace vkt 48{ 49namespace pipeline 50{ 51namespace multisample 52{ 53 54using namespace vk; 55 56struct VertexDataNdc 57{ 58 VertexDataNdc (const tcu::Vec4& posNdc) : positionNdc(posNdc) {} 59 60 tcu::Vec4 positionNdc; 61}; 62 63MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdc (void) 64{ 65 MultisampleInstanceBase::VertexDataDesc vertexDataDesc; 66 67 vertexDataDesc.verticesCount = 4u; 68 vertexDataDesc.dataStride = sizeof(VertexDataNdc); 69 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; 70 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; 71 72 const VkVertexInputAttributeDescription vertexAttribPositionNdc = 73 { 74 0u, // deUint32 location; 75 0u, // deUint32 binding; 76 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 77 DE_OFFSET_OF(VertexDataNdc, positionNdc), // deUint32 offset; 78 }; 79 80 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); 81 82 return vertexDataDesc; 83} 84 85void uploadVertexDataNdc (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton) 86{ 87 std::vector<VertexDataNdc> vertices; 88 89 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f))); 90 vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f))); 91 vertices.push_back(VertexDataNdc(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f))); 92 vertices.push_back(VertexDataNdc(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f))); 93 94 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize)); 95} 96 97struct VertexDataNdcScreen 98{ 99 VertexDataNdcScreen (const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {} 100 101 tcu::Vec4 positionNdc; 102 tcu::Vec2 positionScreen; 103}; 104 105MultisampleInstanceBase::VertexDataDesc getVertexDataDescriptonNdcScreen (void) 106{ 107 MultisampleInstanceBase::VertexDataDesc vertexDataDesc; 108 109 vertexDataDesc.verticesCount = 4u; 110 vertexDataDesc.dataStride = sizeof(VertexDataNdcScreen); 111 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride; 112 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; 113 114 const VkVertexInputAttributeDescription vertexAttribPositionNdc = 115 { 116 0u, // deUint32 location; 117 0u, // deUint32 binding; 118 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 119 DE_OFFSET_OF(VertexDataNdcScreen, positionNdc), // deUint32 offset; 120 }; 121 122 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc); 123 124 const VkVertexInputAttributeDescription vertexAttribPositionScreen = 125 { 126 1u, // deUint32 location; 127 0u, // deUint32 binding; 128 VK_FORMAT_R32G32_SFLOAT, // VkFormat format; 129 DE_OFFSET_OF(VertexDataNdcScreen, positionScreen), // deUint32 offset; 130 }; 131 132 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen); 133 134 return vertexDataDesc; 135} 136 137void uploadVertexDataNdcScreen (const Allocation& vertexBufferAllocation, const MultisampleInstanceBase::VertexDataDesc& vertexDataDescripton, const tcu::Vec2& screenSize) 138{ 139 std::vector<VertexDataNdcScreen> vertices; 140 141 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f))); 142 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), 0.0f))); 143 vertices.push_back(VertexDataNdcScreen(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSize.y()))); 144 vertices.push_back(VertexDataNdcScreen(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSize.x(), screenSize.y()))); 145 146 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize)); 147} 148 149bool checkForErrorMS (const vk::VkImageCreateInfo& imageMSInfo, const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, const deUint32 errorCompNdx) 150{ 151 const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples); 152 153 for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) 154 for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) 155 for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) 156 { 157 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 158 { 159 const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[errorCompNdx]; 160 161 if (errorComponent > 0) 162 return true; 163 } 164 } 165 166 return false; 167} 168 169bool checkForErrorRS (const vk::VkImageCreateInfo& imageRSInfo, const tcu::ConstPixelBufferAccess& dataRS, const deUint32 errorCompNdx) 170{ 171 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) 172 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) 173 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) 174 { 175 const deUint32 errorComponent = dataRS.getPixelUint(x, y, z)[errorCompNdx]; 176 177 if (errorComponent > 0) 178 return true; 179 } 180 181 return false; 182} 183 184template <typename CaseClassName> 185class MSCase : public MSCaseBaseResolveAndPerSampleFetch 186{ 187public: 188 MSCase (tcu::TestContext& testCtx, 189 const std::string& name, 190 const ImageMSParams& imageMSParams) 191 : MSCaseBaseResolveAndPerSampleFetch(testCtx, name, imageMSParams) {} 192 193 virtual void checkSupport (Context& context) const; 194 void init (void); 195 void initPrograms (vk::SourceCollections& programCollection) const; 196 TestInstance* createInstance (Context& context) const; 197 static MultisampleCaseBase* createCase (tcu::TestContext& testCtx, 198 const std::string& name, 199 const ImageMSParams& imageMSParams); 200}; 201#ifndef CTS_USES_VULKANSC 202template <typename CaseClassName> 203void MSCase<CaseClassName>::checkSupport(Context& context) const 204{ 205 checkGraphicsPipelineLibrarySupport(context); 206} 207#endif // CTS_USES_VULKANSC 208 209template <typename CaseClassName> 210MultisampleCaseBase* MSCase<CaseClassName>::createCase (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams) 211{ 212 return new MSCase<CaseClassName>(testCtx, name, imageMSParams); 213} 214 215template <typename InstanceClassName> 216class MSInstance : public MSInstanceBaseResolveAndPerSampleFetch 217{ 218public: 219 MSInstance (Context& context, 220 const ImageMSParams& imageMSParams) 221 : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) {} 222 223 VertexDataDesc getVertexDataDescripton (void) const; 224 void uploadVertexData (const Allocation& vertexBufferAllocation, 225 const VertexDataDesc& vertexDataDescripton) const; 226 227 tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 228 const vk::VkImageCreateInfo& imageRSInfo, 229 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 230 const tcu::ConstPixelBufferAccess& dataRS) const; 231 232 virtual VkPipelineMultisampleStateCreateInfo getMSStateCreateInfo (const ImageMSParams& imageMSParams) const 233 { 234 return MSInstanceBaseResolveAndPerSampleFetch::getMSStateCreateInfo(imageMSParams); 235 } 236}; 237 238class MSInstanceSampleID; 239 240template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleID>::getVertexDataDescripton (void) const 241{ 242 return getVertexDataDescriptonNdc(); 243} 244 245template<> void MSInstance<MSInstanceSampleID>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 246{ 247 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 248} 249 250template<> tcu::TestStatus MSInstance<MSInstanceSampleID>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 251 const vk::VkImageCreateInfo& imageRSInfo, 252 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 253 const tcu::ConstPixelBufferAccess& dataRS) const 254{ 255 DE_UNREF(imageRSInfo); 256 DE_UNREF(dataRS); 257 258 const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples); 259 260 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 261 { 262 for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) 263 for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) 264 for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) 265 { 266 const deUint32 sampleID = dataPerSample[sampleNdx].getPixelUint(x, y, z).x(); 267 268 if (sampleID != sampleNdx) 269 return tcu::TestStatus::fail("gl_SampleID does not have correct value"); 270 } 271 } 272 273 return tcu::TestStatus::pass("Passed"); 274} 275 276class MSCaseSampleID; 277 278template<> void MSCase<MSCaseSampleID>::checkSupport (Context& context) const 279{ 280 checkGraphicsPipelineLibrarySupport(context); 281 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 282} 283 284template<> void MSCase<MSCaseSampleID>::init (void) 285{ 286 m_testCtx.getLog() 287 << tcu::TestLog::Message 288 << "Writing gl_SampleID to the red channel of the texture and verifying texture values.\n" 289 << "Expecting value N at sample index N of a multisample texture.\n" 290 << tcu::TestLog::EndMessage; 291 292 MultisampleCaseBase::init(); 293} 294 295template<> void MSCase<MSCaseSampleID>::initPrograms (vk::SourceCollections& programCollection) const 296{ 297 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 298 299 // Create vertex shader 300 std::ostringstream vs; 301 302 vs << "#version 440\n" 303 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 304 << "\n" 305 << "out gl_PerVertex {\n" 306 << " vec4 gl_Position;\n" 307 << "};\n" 308 << "void main (void)\n" 309 << "{\n" 310 << " gl_Position = vs_in_position_ndc;\n" 311 << "}\n"; 312 313 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 314 315 // Create fragment shader 316 std::ostringstream fs; 317 318 fs << "#version 440\n" 319 << "\n" 320 << "layout(location = 0) out vec4 fs_out_color;\n" 321 << "\n" 322 << "void main (void)\n" 323 << "{\n" 324 << " fs_out_color = vec4(float(gl_SampleID) / float(255), 0.0, 0.0, 1.0);\n" 325 << "}\n"; 326 327 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 328} 329 330template<> TestInstance* MSCase<MSCaseSampleID>::createInstance (Context& context) const 331{ 332 return new MSInstance<MSInstanceSampleID>(context, m_imageMSParams); 333} 334 335class MSInstanceSamplePosDistribution; 336 337template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosDistribution>::getVertexDataDescripton (void) const 338{ 339 return getVertexDataDescriptonNdc(); 340} 341 342template<> void MSInstance<MSInstanceSamplePosDistribution>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 343{ 344 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 345} 346 347template<> tcu::TestStatus MSInstance<MSInstanceSamplePosDistribution>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 348 const vk::VkImageCreateInfo& imageRSInfo, 349 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 350 const tcu::ConstPixelBufferAccess& dataRS) const 351{ 352 const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples); 353 354 // approximate Bates distribution as normal 355 const float variance = (1.0f / (12.0f * (float)numSamples)); 356 const float standardDeviation = deFloatSqrt(variance); 357 358 // 95% of means of sample positions are within 2 standard deviations if 359 // they were randomly assigned. Sample patterns are expected to be more 360 // uniform than a random pattern. 361 const float distanceThreshold = 2.0f * standardDeviation; 362 363 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) 364 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) 365 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) 366 { 367 const deUint32 errorComponent = dataRS.getPixelUint(x, y, z).z(); 368 369 if (errorComponent > 0) 370 return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]"); 371 372 if (numSamples >= VK_SAMPLE_COUNT_4_BIT) 373 { 374 const tcu::Vec2 averageSamplePos = tcu::Vec2((float)dataRS.getPixelUint(x, y, z).x() / 255.0f, (float)dataRS.getPixelUint(x, y, z).y() / 255.0f); 375 const tcu::Vec2 distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f)); 376 377 if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold) 378 return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel"); 379 } 380 } 381 382 for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) 383 for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) 384 for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) 385 { 386 std::vector<tcu::Vec2> samplePositions(numSamples); 387 388 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 389 { 390 const deUint32 errorComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z).z(); 391 392 if (errorComponent > 0) 393 return tcu::TestStatus::fail("gl_SamplePosition is not within interval [0,1]"); 394 395 samplePositions[sampleNdx] = tcu::Vec2( (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).x() / 255.0f, 396 (float)dataPerSample[sampleNdx].getPixelUint(x, y, z).y() / 255.0f); 397 } 398 399 for (deUint32 sampleNdxA = 0u; sampleNdxA < numSamples; ++sampleNdxA) 400 for (deUint32 sampleNdxB = sampleNdxA + 1u; sampleNdxB < numSamples; ++sampleNdxB) 401 { 402 if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB]) 403 return tcu::TestStatus::fail("Two samples have the same position"); 404 } 405 406 if (numSamples >= VK_SAMPLE_COUNT_4_BIT) 407 { 408 tcu::Vec2 averageSamplePos(0.0f, 0.0f); 409 410 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 411 { 412 averageSamplePos.x() += samplePositions[sampleNdx].x(); 413 averageSamplePos.y() += samplePositions[sampleNdx].y(); 414 } 415 416 averageSamplePos.x() /= (float)numSamples; 417 averageSamplePos.y() /= (float)numSamples; 418 419 const tcu::Vec2 distanceFromCenter = tcu::abs(averageSamplePos - tcu::Vec2(0.5f, 0.5f)); 420 421 if (distanceFromCenter.x() > distanceThreshold || distanceFromCenter.y() > distanceThreshold) 422 return tcu::TestStatus::fail("Sample positions are not uniformly distributed within the pixel"); 423 } 424 } 425 426 return tcu::TestStatus::pass("Passed"); 427} 428 429class MSCaseSamplePosDistribution; 430 431template<> void MSCase<MSCaseSamplePosDistribution>::checkSupport (Context& context) const 432{ 433 checkGraphicsPipelineLibrarySupport(context); 434 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 435} 436 437template<> void MSCase<MSCaseSamplePosDistribution>::init (void) 438{ 439 m_testCtx.getLog() 440 << tcu::TestLog::Message 441 << "Verifying gl_SamplePosition value with multisample targets:\n" 442 << " a) Expect legal sample position.\n" 443 << " b) Sample position is unique within the set of all sample positions of a pixel.\n" 444 << " c) Sample position distribution is uniform or almost uniform.\n" 445 << tcu::TestLog::EndMessage; 446 447 MultisampleCaseBase::init(); 448} 449 450template<> void MSCase<MSCaseSamplePosDistribution>::initPrograms (vk::SourceCollections& programCollection) const 451{ 452 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 453 454 // Create vertex shader 455 std::ostringstream vs; 456 457 vs << "#version 440\n" 458 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 459 << "\n" 460 << "out gl_PerVertex {\n" 461 << " vec4 gl_Position;\n" 462 << "};\n" 463 << "void main (void)\n" 464 << "{\n" 465 << " gl_Position = vs_in_position_ndc;\n" 466 << "}\n"; 467 468 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 469 470 // Create fragment shader 471 std::ostringstream fs; 472 473 fs << "#version 440\n" 474 << "\n" 475 << "layout(location = 0) out vec4 fs_out_color;\n" 476 << "\n" 477 << "void main (void)\n" 478 << "{\n" 479 << " if (gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0 || gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0)\n" 480 " fs_out_color = vec4(0.0, 0.0, 1.0, 1.0);\n" 481 " else\n" 482 " fs_out_color = vec4(gl_SamplePosition.x, gl_SamplePosition.y, 0.0, 1.0);\n" 483 "}\n"; 484 485 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 486} 487 488template<> TestInstance* MSCase<MSCaseSamplePosDistribution>::createInstance (Context& context) const 489{ 490 return new MSInstance<MSInstanceSamplePosDistribution>(context, m_imageMSParams); 491} 492 493class MSInstanceSamplePosCorrectness; 494 495template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSamplePosCorrectness>::getVertexDataDescripton (void) const 496{ 497 return getVertexDataDescriptonNdcScreen(); 498} 499 500template<> void MSInstance<MSInstanceSamplePosCorrectness>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 501{ 502 const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize); 503 504 uploadVertexDataNdcScreen(vertexBufferAllocation, vertexDataDescripton, tcu::Vec2(static_cast<float>(layerSize.x()), static_cast<float>(layerSize.y()))); 505} 506 507template<> tcu::TestStatus MSInstance<MSInstanceSamplePosCorrectness>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 508 const vk::VkImageCreateInfo& imageRSInfo, 509 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 510 const tcu::ConstPixelBufferAccess& dataRS) const 511{ 512 if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) 513 return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition"); 514 515 if (checkForErrorRS(imageRSInfo, dataRS, 0)) 516 return tcu::TestStatus::fail("Varying values are not sampled at gl_SamplePosition"); 517 518 return tcu::TestStatus::pass("Passed"); 519} 520 521class MSCaseSamplePosCorrectness; 522 523template<> void MSCase<MSCaseSamplePosCorrectness>::checkSupport (Context& context) const 524{ 525 checkGraphicsPipelineLibrarySupport(context); 526 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 527} 528 529template<> void MSCase<MSCaseSamplePosCorrectness>::init (void) 530{ 531 m_testCtx.getLog() 532 << tcu::TestLog::Message 533 << "Verifying gl_SamplePosition correctness:\n" 534 << " 1) Varying values should be sampled at the sample position.\n" 535 << " => fract(position_screen) == gl_SamplePosition\n" 536 << tcu::TestLog::EndMessage; 537 538 MultisampleCaseBase::init(); 539} 540 541template<> void MSCase<MSCaseSamplePosCorrectness>::initPrograms (vk::SourceCollections& programCollection) const 542{ 543 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 544 545 // Create vertex shaders 546 std::ostringstream vs; 547 548 vs << "#version 440\n" 549 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 550 << "layout(location = 1) in vec2 vs_in_position_screen;\n" 551 << "\n" 552 << "layout(location = 0) sample out vec2 vs_out_position_screen;\n" 553 << "\n" 554 << "out gl_PerVertex {\n" 555 << " vec4 gl_Position;\n" 556 << "};\n" 557 << "void main (void)\n" 558 << "{\n" 559 << " gl_Position = vs_in_position_ndc;\n" 560 << " vs_out_position_screen = vs_in_position_screen;\n" 561 << "}\n"; 562 563 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 564 565 // Create fragment shader 566 std::ostringstream fs; 567 568 fs << "#version 440\n" 569 << "layout(location = 0) sample in vec2 fs_in_position_screen;\n" 570 << "\n" 571 << "layout(location = 0) out vec4 fs_out_color;\n" 572 << "\n" 573 << "void main (void)\n" 574 << "{\n" 575 << " const float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" 576 << " const ivec2 nearby_pixel = ivec2(floor(fs_in_position_screen));\n" 577 << " bool ok = false;\n" 578 << "\n" 579 << " // sample at edge + inaccuaries may cause us to round to any neighboring pixel\n" 580 << " // check all neighbors for any match\n" 581 << " for (int dy = -1; dy <= 1; ++dy)\n" 582 << " for (int dx = -1; dx <= 1; ++dx)\n" 583 << " {\n" 584 << " ivec2 current_pixel = nearby_pixel + ivec2(dx, dy);\n" 585 << " vec2 position_inside_pixel = vec2(current_pixel) + gl_SamplePosition;\n" 586 << " vec2 position_diff = abs(position_inside_pixel - fs_in_position_screen);\n" 587 << "\n" 588 << " if (all(lessThan(position_diff, vec2(threshold))))\n" 589 << " ok = true;\n" 590 << " }\n" 591 << "\n" 592 << " if (ok)\n" 593 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 594 << " else\n" 595 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 596 << "}\n"; 597 598 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 599} 600 601template<> TestInstance* MSCase<MSCaseSamplePosCorrectness>::createInstance (Context& context) const 602{ 603 return new MSInstance<MSInstanceSamplePosCorrectness>(context, m_imageMSParams); 604} 605 606class MSInstanceSampleMaskPattern : public MSInstanceBaseResolveAndPerSampleFetch 607{ 608public: 609 MSInstanceSampleMaskPattern (Context& context, 610 const ImageMSParams& imageMSParams); 611 612 VkPipelineMultisampleStateCreateInfo getMSStateCreateInfo (const ImageMSParams& imageMSParams) const; 613 614 const VkDescriptorSetLayout* createMSPassDescSetLayout (const ImageMSParams& imageMSParams); 615 616 const VkDescriptorSet* createMSPassDescSet (const ImageMSParams& imageMSParams, 617 const VkDescriptorSetLayout* descSetLayout); 618 619 VertexDataDesc getVertexDataDescripton (void) const; 620 621 void uploadVertexData (const Allocation& vertexBufferAllocation, 622 const VertexDataDesc& vertexDataDescripton) const; 623 624 tcu::TestStatus verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 625 const vk::VkImageCreateInfo& imageRSInfo, 626 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 627 const tcu::ConstPixelBufferAccess& dataRS) const; 628protected: 629 630 VkSampleMask m_sampleMask; 631 Move<VkDescriptorSetLayout> m_descriptorSetLayout; 632 Move<VkDescriptorPool> m_descriptorPool; 633 Move<VkDescriptorSet> m_descriptorSet; 634 de::MovePtr<BufferWithMemory> m_buffer; 635}; 636 637MSInstanceSampleMaskPattern::MSInstanceSampleMaskPattern (Context& context, const ImageMSParams& imageMSParams) : MSInstanceBaseResolveAndPerSampleFetch(context, imageMSParams) 638{ 639 m_sampleMask = 0xAAAAAAAAu & ((1u << imageMSParams.numSamples) - 1u); 640} 641 642VkPipelineMultisampleStateCreateInfo MSInstanceSampleMaskPattern::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const 643{ 644 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = 645 { 646 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 647 DE_NULL, // const void* pNext; 648 (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags; 649 imageMSParams.numSamples, // VkSampleCountFlagBits rasterizationSamples; 650 VK_FALSE, // VkBool32 sampleShadingEnable; 651 imageMSParams.shadingRate, // float minSampleShading; 652 &m_sampleMask, // const VkSampleMask* pSampleMask; 653 VK_FALSE, // VkBool32 alphaToCoverageEnable; 654 VK_FALSE, // VkBool32 alphaToOneEnable; 655 }; 656 657 return multisampleStateInfo; 658} 659 660const VkDescriptorSetLayout* MSInstanceSampleMaskPattern::createMSPassDescSetLayout (const ImageMSParams& imageMSParams) 661{ 662 DE_UNREF(imageMSParams); 663 664 const DeviceInterface& deviceInterface = m_context.getDeviceInterface(); 665 const VkDevice device = m_context.getDevice(); 666 667 // Create descriptor set layout 668 m_descriptorSetLayout = DescriptorSetLayoutBuilder() 669 .addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT) 670 .build(deviceInterface, device); 671 672 return &m_descriptorSetLayout.get(); 673} 674 675const VkDescriptorSet* MSInstanceSampleMaskPattern::createMSPassDescSet (const ImageMSParams& imageMSParams, const VkDescriptorSetLayout* descSetLayout) 676{ 677 DE_UNREF(imageMSParams); 678 679 const DeviceInterface& deviceInterface = m_context.getDeviceInterface(); 680 const VkDevice device = m_context.getDevice(); 681 Allocator& allocator = m_context.getDefaultAllocator(); 682 683 // Create descriptor pool 684 m_descriptorPool = DescriptorPoolBuilder() 685 .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u) 686 .build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 687 688 // Create descriptor set 689 m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *descSetLayout); 690 691 const VkBufferCreateInfo bufferSampleMaskInfo = makeBufferCreateInfo(sizeof(VkSampleMask), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); 692 693 m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(deviceInterface, device, allocator, bufferSampleMaskInfo, MemoryRequirement::HostVisible)); 694 695 deMemcpy(m_buffer->getAllocation().getHostPtr(), &m_sampleMask, sizeof(VkSampleMask)); 696 697 flushAlloc(deviceInterface, device, m_buffer->getAllocation()); 698 699 const VkDescriptorBufferInfo descBufferInfo = makeDescriptorBufferInfo(**m_buffer, 0u, sizeof(VkSampleMask)); 700 701 DescriptorSetUpdateBuilder() 702 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descBufferInfo) 703 .update(deviceInterface, device); 704 705 return &m_descriptorSet.get(); 706} 707 708MultisampleInstanceBase::VertexDataDesc MSInstanceSampleMaskPattern::getVertexDataDescripton (void) const 709{ 710 return getVertexDataDescriptonNdc(); 711} 712 713void MSInstanceSampleMaskPattern::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 714{ 715 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 716} 717 718tcu::TestStatus MSInstanceSampleMaskPattern::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 719 const vk::VkImageCreateInfo& imageRSInfo, 720 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 721 const tcu::ConstPixelBufferAccess& dataRS) const 722{ 723 DE_UNREF(imageRSInfo); 724 DE_UNREF(dataRS); 725 726 if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) 727 return tcu::TestStatus::fail("gl_SampleMaskIn bits have not been killed by pSampleMask state"); 728 729 return tcu::TestStatus::pass("Passed"); 730} 731 732class MSCaseSampleMaskPattern; 733 734template<> void MSCase<MSCaseSampleMaskPattern>::init (void) 735{ 736 m_testCtx.getLog() 737 << tcu::TestLog::Message 738 << "Verifying gl_SampleMaskIn value with pSampleMask state. gl_SampleMaskIn does not contain any bits set that are have been killed by pSampleMask state. Expecting:\n" 739 << "Expected result: gl_SampleMaskIn AND ~(pSampleMask) should be zero.\n" 740 << tcu::TestLog::EndMessage; 741 742 MultisampleCaseBase::init(); 743} 744 745template<> void MSCase<MSCaseSampleMaskPattern>::initPrograms (vk::SourceCollections& programCollection) const 746{ 747 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 748 749 // Create vertex shader 750 std::ostringstream vs; 751 752 vs << "#version 440\n" 753 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 754 << "\n" 755 << "out gl_PerVertex {\n" 756 << " vec4 gl_Position;\n" 757 << "};\n" 758 << "void main (void)\n" 759 << "{\n" 760 << " gl_Position = vs_in_position_ndc;\n" 761 << "}\n"; 762 763 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 764 765 // Create fragment shader 766 std::ostringstream fs; 767 768 fs << "#version 440\n" 769 << "\n" 770 << "layout(location = 0) out vec4 fs_out_color;\n" 771 << "\n" 772 << "layout(set = 0, binding = 0, std140) uniform SampleMaskBlock\n" 773 << "{\n" 774 << " int sampleMaskPattern;\n" 775 << "};" 776 << "\n" 777 << "void main (void)\n" 778 << "{\n" 779 << " if ((gl_SampleMaskIn[0] & ~sampleMaskPattern) != 0)\n" 780 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 781 << " else\n" 782 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 783 << "}\n"; 784 785 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 786} 787 788template<> TestInstance* MSCase<MSCaseSampleMaskPattern>::createInstance (Context& context) const 789{ 790 return new MSInstanceSampleMaskPattern(context, m_imageMSParams); 791} 792 793class MSInstanceSampleMaskBitCount; 794 795template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskBitCount>::getVertexDataDescripton (void) const 796{ 797 return getVertexDataDescriptonNdc(); 798} 799 800template<> void MSInstance<MSInstanceSampleMaskBitCount>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 801{ 802 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 803} 804 805template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskBitCount>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 806 const vk::VkImageCreateInfo& imageRSInfo, 807 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 808 const tcu::ConstPixelBufferAccess& dataRS) const 809{ 810 DE_UNREF(imageRSInfo); 811 DE_UNREF(dataRS); 812 813 if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) 814 return tcu::TestStatus::fail("gl_SampleMaskIn has an illegal number of bits for some shader invocations"); 815 816 return tcu::TestStatus::pass("Passed"); 817} 818 819class MSCaseSampleMaskBitCount; 820 821template<> void MSCase<MSCaseSampleMaskBitCount>::checkSupport (Context& context) const 822{ 823 checkGraphicsPipelineLibrarySupport(context); 824 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 825} 826 827template<> void MSCase<MSCaseSampleMaskBitCount>::init (void) 828{ 829 m_testCtx.getLog() 830 << tcu::TestLog::Message 831 << "Verifying gl_SampleMaskIn.\n" 832 << " Fragment shader will be invoked numSamples times.\n" 833 << " => gl_SampleMaskIn should have a number of bits that depends on the shading rate.\n" 834 << tcu::TestLog::EndMessage; 835 836 MultisampleCaseBase::init(); 837} 838 839template<> void MSCase<MSCaseSampleMaskBitCount>::initPrograms (vk::SourceCollections& programCollection) const 840{ 841 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 842 843 // Create vertex shader 844 std::ostringstream vs; 845 846 vs << "#version 440\n" 847 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 848 << "\n" 849 << "out gl_PerVertex {\n" 850 << " vec4 gl_Position;\n" 851 << "};\n" 852 << "void main (void)\n" 853 << "{\n" 854 << " gl_Position = vs_in_position_ndc;\n" 855 << "}\n"; 856 857 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 858 859 // Create fragment shader 860 std::ostringstream fs; 861 862 // The worst case scenario would be all invocations except one covering a single sample, and then one invocation covering the rest. 863 const int minInvocations = static_cast<int>(std::ceil(static_cast<float>(m_imageMSParams.numSamples) * m_imageMSParams.shadingRate)); 864 const int minCount = 1; 865 const int maxCount = m_imageMSParams.numSamples - (minInvocations - 1); 866 867 fs << "#version 440\n" 868 << "\n" 869 << "layout(location = 0) out vec4 fs_out_color;\n" 870 << "\n" 871 << "void main (void)\n" 872 << "{\n" 873 << " const int maskBitCount = bitCount(gl_SampleMaskIn[0]);\n" 874 << "\n" 875 << " if (maskBitCount < " << minCount << " || maskBitCount > " << maxCount << ")\n" 876 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 877 << " else\n" 878 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 879 << "}\n"; 880 881 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 882} 883 884template<> TestInstance* MSCase<MSCaseSampleMaskBitCount>::createInstance (Context& context) const 885{ 886 return new MSInstance<MSInstanceSampleMaskBitCount>(context, m_imageMSParams); 887} 888 889class MSInstanceSampleMaskCorrectBit; 890 891template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskCorrectBit>::getVertexDataDescripton (void) const 892{ 893 return getVertexDataDescriptonNdc(); 894} 895 896template<> void MSInstance<MSInstanceSampleMaskCorrectBit>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 897{ 898 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 899} 900 901template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskCorrectBit>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 902 const vk::VkImageCreateInfo& imageRSInfo, 903 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 904 const tcu::ConstPixelBufferAccess& dataRS) const 905{ 906 DE_UNREF(imageRSInfo); 907 DE_UNREF(dataRS); 908 909 if (checkForErrorMS(imageMSInfo, dataPerSample, 0)) 910 return tcu::TestStatus::fail("The bit corresponsing to current gl_SampleID is not set in gl_SampleMaskIn"); 911 912 return tcu::TestStatus::pass("Passed"); 913} 914 915class MSCaseSampleMaskCorrectBit; 916 917template<> void MSCase<MSCaseSampleMaskCorrectBit>::checkSupport (Context& context) const 918{ 919 checkGraphicsPipelineLibrarySupport(context); 920 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); 921} 922 923template<> void MSCase<MSCaseSampleMaskCorrectBit>::init (void) 924{ 925 m_testCtx.getLog() 926 << tcu::TestLog::Message 927 << "Verifying gl_SampleMaskIn.\n" 928 << " Fragment shader will be invoked numSamples times.\n" 929 << " => In each invocation gl_SampleMaskIn should have the bit set that corresponds to gl_SampleID.\n" 930 << tcu::TestLog::EndMessage; 931 932 MultisampleCaseBase::init(); 933} 934 935template<> void MSCase<MSCaseSampleMaskCorrectBit>::initPrograms (vk::SourceCollections& programCollection) const 936{ 937 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 938 939 // Create vertex shader 940 std::ostringstream vs; 941 942 vs << "#version 440\n" 943 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 944 << "\n" 945 << "out gl_PerVertex {\n" 946 << " vec4 gl_Position;\n" 947 << "};\n" 948 << "void main (void)\n" 949 << "{\n" 950 << " gl_Position = vs_in_position_ndc;\n" 951 << "}\n"; 952 953 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 954 955 // Create fragment shader 956 std::ostringstream fs; 957 958 fs << "#version 440\n" 959 << "\n" 960 << "layout(location = 0) out vec4 fs_out_color;\n" 961 << "\n" 962 << "void main (void)\n" 963 << "{\n" 964 << " if (((gl_SampleMaskIn[0] >> gl_SampleID) & 0x01) == 0x01)\n" 965 << " fs_out_color = vec4(0.0, 1.0, 0.0, 1.0);\n" 966 << " else\n" 967 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 968 << "}\n"; 969 970 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 971} 972 973template<> TestInstance* MSCase<MSCaseSampleMaskCorrectBit>::createInstance (Context& context) const 974{ 975 return new MSInstance<MSInstanceSampleMaskCorrectBit>(context, m_imageMSParams); 976} 977 978class MSInstanceSampleMaskWrite; 979 980template<> MultisampleInstanceBase::VertexDataDesc MSInstance<MSInstanceSampleMaskWrite>::getVertexDataDescripton (void) const 981{ 982 return getVertexDataDescriptonNdc(); 983} 984 985template<> void MSInstance<MSInstanceSampleMaskWrite>::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const 986{ 987 uploadVertexDataNdc(vertexBufferAllocation, vertexDataDescripton); 988} 989 990//! Creates VkPipelineMultisampleStateCreateInfo with sample shading disabled. 991template<> VkPipelineMultisampleStateCreateInfo MSInstance<MSInstanceSampleMaskWrite>::getMSStateCreateInfo (const ImageMSParams& imageMSParams) const 992{ 993 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo = 994 { 995 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 996 DE_NULL, // const void* pNext; 997 (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags; 998 imageMSParams.numSamples, // VkSampleCountFlagBits rasterizationSamples; 999 VK_FALSE, // VkBool32 sampleShadingEnable; 1000 imageMSParams.shadingRate, // float minSampleShading; 1001 DE_NULL, // const VkSampleMask* pSampleMask; 1002 VK_FALSE, // VkBool32 alphaToCoverageEnable; 1003 VK_FALSE, // VkBool32 alphaToOneEnable; 1004 }; 1005 1006 return multisampleStateInfo; 1007} 1008 1009template<> tcu::TestStatus MSInstance<MSInstanceSampleMaskWrite>::verifyImageData (const vk::VkImageCreateInfo& imageMSInfo, 1010 const vk::VkImageCreateInfo& imageRSInfo, 1011 const std::vector<tcu::ConstPixelBufferAccess>& dataPerSample, 1012 const tcu::ConstPixelBufferAccess& dataRS) const 1013{ 1014 const deUint32 numSamples = static_cast<deUint32>(imageMSInfo.samples); 1015 1016 for (deUint32 z = 0u; z < imageMSInfo.extent.depth; ++z) 1017 for (deUint32 y = 0u; y < imageMSInfo.extent.height; ++y) 1018 for (deUint32 x = 0u; x < imageMSInfo.extent.width; ++x) 1019 { 1020 for (deUint32 sampleNdx = 0u; sampleNdx < numSamples; ++sampleNdx) 1021 { 1022 const deUint32 firstComponent = dataPerSample[sampleNdx].getPixelUint(x, y, z)[0]; 1023 1024 if (firstComponent != 0u && firstComponent != 255u) 1025 return tcu::TestStatus::fail("Expected color to be zero or saturated on the first channel"); 1026 } 1027 } 1028 1029 for (deUint32 z = 0u; z < imageRSInfo.extent.depth; ++z) 1030 for (deUint32 y = 0u; y < imageRSInfo.extent.height; ++y) 1031 for (deUint32 x = 0u; x < imageRSInfo.extent.width; ++x) 1032 { 1033 const float firstComponent = dataRS.getPixel(x, y, z)[0]; 1034 1035 if (deFloatAbs(firstComponent - 0.5f) > 0.02f) 1036 return tcu::TestStatus::fail("Expected resolve color to be half intensity on the first channel"); 1037 } 1038 1039 return tcu::TestStatus::pass("Passed"); 1040} 1041 1042class MSCaseSampleMaskWrite; 1043 1044template<> void MSCase<MSCaseSampleMaskWrite>::init (void) 1045{ 1046 m_testCtx.getLog() 1047 << tcu::TestLog::Message 1048 << "Discarding half of the samples using gl_SampleMask." 1049 << "Expecting half intensity on multisample targets (numSamples > 1)\n" 1050 << tcu::TestLog::EndMessage; 1051 1052 MultisampleCaseBase::init(); 1053} 1054 1055template<> void MSCase<MSCaseSampleMaskWrite>::initPrograms (vk::SourceCollections& programCollection) const 1056{ 1057 MSCaseBaseResolveAndPerSampleFetch::initPrograms(programCollection); 1058 1059 // Create vertex shader 1060 std::ostringstream vs; 1061 1062 vs << "#version 440\n" 1063 << "layout(location = 0) in vec4 vs_in_position_ndc;\n" 1064 << "\n" 1065 << "out gl_PerVertex {\n" 1066 << " vec4 gl_Position;\n" 1067 << "};\n" 1068 << "void main (void)\n" 1069 << "{\n" 1070 << " gl_Position = vs_in_position_ndc;\n" 1071 << "}\n"; 1072 1073 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str()); 1074 1075 // Create fragment shader 1076 std::ostringstream fs; 1077 1078 fs << "#version 440\n" 1079 << "\n" 1080 << "layout(location = 0) out vec4 fs_out_color;\n" 1081 << "\n" 1082 << "void main (void)\n" 1083 << "{\n" 1084 << " gl_SampleMask[0] = 0xAAAAAAAA;\n" 1085 << "\n" 1086 << " fs_out_color = vec4(1.0, 0.0, 0.0, 1.0);\n" 1087 << "}\n"; 1088 1089 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str()); 1090} 1091 1092template<> TestInstance* MSCase<MSCaseSampleMaskWrite>::createInstance (Context& context) const 1093{ 1094 return new MSInstance<MSInstanceSampleMaskWrite>(context, m_imageMSParams); 1095} 1096 1097const set<deUint32> kValidSquareSampleCounts = 1098{ 1099 vk::VK_SAMPLE_COUNT_1_BIT, 1100 vk::VK_SAMPLE_COUNT_2_BIT, 1101 vk::VK_SAMPLE_COUNT_4_BIT, 1102 vk::VK_SAMPLE_COUNT_8_BIT, 1103 vk::VK_SAMPLE_COUNT_16_BIT, 1104}; 1105 1106void assertSquareSampleCount (deUint32 sampleCount) 1107{ 1108 DE_ASSERT(kValidSquareSampleCounts.find(sampleCount) != kValidSquareSampleCounts.end()); 1109 DE_UNREF(sampleCount); // for release builds. 1110} 1111 1112// When dealing with N samples, each coordinate (x, y) will be used to decide which samples will be written to, using N/2 bits for 1113// each of the X and Y values. Take into account this returns 0 for 1 sample. 1114deUint32 bitsPerCoord (deUint32 numSamples) 1115{ 1116 assertSquareSampleCount(numSamples); 1117 return (numSamples / 2u); 1118} 1119 1120// These tests will try to verify all write or mask bit combinations for the given sample count, and will verify one combination per 1121// image pixel. This means the following image sizes need to be used: 1122// - 2 samples: 2x2 1123// - 4 samples: 4x4 1124// - 8 samples: 16x16 1125// - 16 samples: 256x256 1126// In other words, images will be square with 2^(samples-1) pixels on each side. 1127vk::VkExtent2D imageSize (deUint32 sampleCount) 1128{ 1129 assertSquareSampleCount(sampleCount); 1130 1131 // Special case: 2x1 image (not actually square). 1132 if (sampleCount == vk::VK_SAMPLE_COUNT_1_BIT) 1133 return vk::VkExtent2D{2u, 1u}; 1134 1135 // Other cases: square image as described above. 1136 const auto dim = (1u<<(sampleCount>>1u)); 1137 return vk::VkExtent2D{dim, dim}; 1138} 1139 1140vk::VkExtent3D getExtent3D (deUint32 sampleCount) 1141{ 1142 const auto size = imageSize(sampleCount); 1143 return vk::VkExtent3D{size.width, size.height, 1u}; 1144} 1145 1146std::string getShaderDecl (const tcu::Vec4& color) 1147{ 1148 std::ostringstream declaration; 1149 declaration << "vec4(" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")"; 1150 return declaration.str(); 1151} 1152 1153struct WriteSampleParams 1154{ 1155 vk::PipelineConstructionType pipelineConstructionType; 1156 vk::VkSampleCountFlagBits sampleCount; 1157}; 1158 1159class WriteSampleTest : public vkt::TestCase 1160{ 1161public: 1162 WriteSampleTest (tcu::TestContext& testCtx, const std::string& name, const WriteSampleParams& params) 1163 : vkt::TestCase(testCtx, name), m_params(params) 1164 {} 1165 virtual ~WriteSampleTest (void) {} 1166 1167 virtual void initPrograms (vk::SourceCollections& programCollection) const; 1168 virtual vkt::TestInstance* createInstance (Context& context) const; 1169 virtual void checkSupport (Context& context) const; 1170 1171 static const tcu::Vec4 kClearColor; 1172 static const tcu::Vec4 kBadColor; 1173 static const tcu::Vec4 kGoodColor; 1174 static const tcu::Vec4 kWriteColor; 1175 1176 static constexpr vk::VkFormat kImageFormat = vk::VK_FORMAT_R8G8B8A8_UNORM; 1177 1178 // Keep these two in sync. 1179 static constexpr vk::VkImageUsageFlags kUsageFlags = (vk::VK_IMAGE_USAGE_STORAGE_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT); 1180 static constexpr vk::VkFormatFeatureFlags kFeatureFlags = (vk::VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT); 1181 1182private: 1183 WriteSampleParams m_params; 1184}; 1185 1186const tcu::Vec4 WriteSampleTest::kClearColor {0.0f, 0.0f, 0.0f, 1.0f}; 1187const tcu::Vec4 WriteSampleTest::kBadColor {1.0f, 0.0f, 0.0f, 1.0f}; 1188const tcu::Vec4 WriteSampleTest::kGoodColor {0.0f, 1.0f, 0.0f, 1.0f}; 1189const tcu::Vec4 WriteSampleTest::kWriteColor {0.0f, 0.0f, 1.0f, 1.0f}; 1190 1191class WriteSampleTestInstance : public vkt::TestInstance 1192{ 1193public: 1194 WriteSampleTestInstance (vkt::Context& context, const WriteSampleParams& params) 1195 : vkt::TestInstance(context), m_params(params) 1196 {} 1197 1198 virtual ~WriteSampleTestInstance (void) {} 1199 1200 virtual tcu::TestStatus iterate (void); 1201 1202private: 1203 WriteSampleParams m_params; 1204}; 1205 1206void WriteSampleTest::checkSupport (Context& context) const 1207{ 1208 const auto& vki = context.getInstanceInterface(); 1209 const auto physicalDevice = context.getPhysicalDevice(); 1210 1211 // Check multisample storage images support. 1212 const auto features = vk::getPhysicalDeviceFeatures(vki, physicalDevice); 1213 if (!features.shaderStorageImageMultisample) 1214 TCU_THROW(NotSupportedError, "Using multisample images as storage is not supported"); 1215 1216 // Check the specific image format. 1217 const auto properties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat); 1218 if (!(properties.optimalTilingFeatures & kFeatureFlags)) 1219 TCU_THROW(NotSupportedError, "Format does not support the required features"); 1220 1221 // Check the supported sample count. 1222 const auto imgProps = vk::getPhysicalDeviceImageFormatProperties(vki, physicalDevice, kImageFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, kUsageFlags, 0u); 1223 if (!(imgProps.sampleCounts & m_params.sampleCount)) 1224 TCU_THROW(NotSupportedError, "Format does not support the required sample count"); 1225 1226 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType); 1227} 1228 1229void WriteSampleTest::initPrograms (vk::SourceCollections& programCollection) const 1230{ 1231 std::ostringstream writeColorDecl, goodColorDecl, badColorDecl, clearColorDecl, allColorDecl; 1232 1233 writeColorDecl << " vec4 wcolor = " << getShaderDecl(kWriteColor) << ";\n"; 1234 goodColorDecl << " vec4 bcolor = " << getShaderDecl(kBadColor) << ";\n"; 1235 badColorDecl << " vec4 gcolor = " << getShaderDecl(kGoodColor) << ";\n"; 1236 clearColorDecl << " vec4 ccolor = " << getShaderDecl(kClearColor) << ";\n"; 1237 allColorDecl << writeColorDecl.str() << goodColorDecl.str() << badColorDecl.str() << clearColorDecl.str(); 1238 1239 std::ostringstream shaderWrite; 1240 1241 const auto bpc = de::toString(bitsPerCoord(m_params.sampleCount)); 1242 const auto count = de::toString(m_params.sampleCount); 1243 1244 shaderWrite 1245 << "#version 450\n" 1246 << "\n" 1247 << "layout (rgba8, set=0, binding=0) uniform image2DMS writeImg;\n" 1248 << "layout (rgba8, set=0, binding=1) uniform image2D verificationImg;\n" 1249 << "\n" 1250 << "void main()\n" 1251 << "{\n" 1252 << writeColorDecl.str() 1253 << " uvec2 ucoords = uvec2(gl_GlobalInvocationID.xy);\n" 1254 << " ivec2 icoords = ivec2(ucoords);\n" 1255 << " uint writeMask = ((ucoords.x << " << bpc << ") | ucoords.y);\n" 1256 << " for (uint i = 0; i < " << count << "; ++i)\n" 1257 << " {\n" 1258 << " if ((writeMask & (1 << i)) != 0)\n" 1259 << " imageStore(writeImg, icoords, int(i), wcolor);\n" 1260 << " }\n" 1261 << "}\n" 1262 ; 1263 1264 std::ostringstream shaderVerify; 1265 1266 shaderVerify 1267 << "#version 450\n" 1268 << "\n" 1269 << "layout (rgba8, set=0, binding=0) uniform image2DMS writeImg;\n" 1270 << "layout (rgba8, set=0, binding=1) uniform image2D verificationImg;\n" 1271 << "\n" 1272 << "void main()\n" 1273 << "{\n" 1274 << allColorDecl.str() 1275 << " uvec2 ucoords = uvec2(gl_GlobalInvocationID.xy);\n" 1276 << " ivec2 icoords = ivec2(ucoords);\n" 1277 << " uint writeMask = ((ucoords.x << " << bpc << ") | ucoords.y);\n" 1278 << " bool ok = true;\n" 1279 << " for (uint i = 0; i < " << count << "; ++i)\n" 1280 << " {\n" 1281 << " bool expectWrite = ((writeMask & (1 << i)) != 0);\n" 1282 << " vec4 sampleColor = imageLoad(writeImg, icoords, int(i));\n" 1283 << " vec4 wantedColor = (expectWrite ? wcolor : ccolor);\n" 1284 << " ok = ok && (sampleColor == wantedColor);\n" 1285 << " }\n" 1286 << " vec4 resultColor = (ok ? gcolor : bcolor);\n" 1287 << " imageStore(verificationImg, icoords, resultColor);\n" 1288 << "}\n" 1289 ; 1290 1291 programCollection.glslSources.add("write") << glu::ComputeSource(shaderWrite.str()); 1292 programCollection.glslSources.add("verify") << glu::ComputeSource(shaderVerify.str()); 1293} 1294 1295vkt::TestInstance* WriteSampleTest::createInstance (Context& context) const 1296{ 1297 return new WriteSampleTestInstance{context, m_params}; 1298} 1299 1300tcu::TestStatus WriteSampleTestInstance::iterate (void) 1301{ 1302 const auto& vkd = m_context.getDeviceInterface(); 1303 const auto device = m_context.getDevice(); 1304 auto& allocator = m_context.getDefaultAllocator(); 1305 const auto queue = m_context.getUniversalQueue(); 1306 const auto queueIndex = m_context.getUniversalQueueFamilyIndex(); 1307 const auto extent3D = getExtent3D(m_params.sampleCount); 1308 1309 // Create storage image and verification image. 1310 const vk::VkImageCreateInfo storageImageInfo = 1311 { 1312 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 1313 nullptr, // const void* pNext; 1314 0u, // VkImageCreateFlags flags; 1315 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType; 1316 WriteSampleTest::kImageFormat, // VkFormat format; 1317 extent3D, // VkExtent3D extent; 1318 1u, // deUint32 mipLevels; 1319 1u, // deUint32 arrayLayers; 1320 m_params.sampleCount, // VkSampleCountFlagBits samples; 1321 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 1322 WriteSampleTest::kUsageFlags, // VkImageUsageFlags usage; 1323 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1324 1u, // deUint32 queueFamilyIndexCount; 1325 &queueIndex, // const deUint32* pQueueFamilyIndices; 1326 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1327 }; 1328 1329 const vk::VkImageCreateInfo verificationImageInfo = 1330 { 1331 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 1332 nullptr, // const void* pNext; 1333 0u, // VkImageCreateFlags flags; 1334 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType; 1335 WriteSampleTest::kImageFormat, // VkFormat format; 1336 extent3D, // VkExtent3D extent; 1337 1u, // deUint32 mipLevels; 1338 1u, // deUint32 arrayLayers; 1339 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 1340 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 1341 WriteSampleTest::kUsageFlags, // VkImageUsageFlags usage; 1342 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1343 1u, // deUint32 queueFamilyIndexCount; 1344 &queueIndex, // const deUint32* pQueueFamilyIndices; 1345 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1346 }; 1347 1348 vk::ImageWithMemory storageImgPrt {vkd, device, allocator, storageImageInfo, vk::MemoryRequirement::Any}; 1349 vk::ImageWithMemory verificationImgPtr {vkd, device, allocator, verificationImageInfo, vk::MemoryRequirement::Any}; 1350 1351 const vk::VkImageSubresourceRange kSubresourceRange = 1352 { 1353 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 1354 0u, // deUint32 baseMipLevel; 1355 1u, // deUint32 levelCount; 1356 0u, // deUint32 baseArrayLayer; 1357 1u, // deUint32 layerCount; 1358 }; 1359 1360 auto storageImgViewPtr = vk::makeImageView(vkd, device, storageImgPrt.get(), vk::VK_IMAGE_VIEW_TYPE_2D, WriteSampleTest::kImageFormat, kSubresourceRange); 1361 auto verificationImgViewPtr = vk::makeImageView(vkd, device, verificationImgPtr.get(), vk::VK_IMAGE_VIEW_TYPE_2D, WriteSampleTest::kImageFormat, kSubresourceRange); 1362 1363 // Prepare a staging buffer to check verification image. 1364 const auto tcuFormat = vk::mapVkFormat(WriteSampleTest::kImageFormat); 1365 const VkDeviceSize bufferSize = extent3D.width * extent3D.height * extent3D.depth * tcu::getPixelSize(tcuFormat); 1366 const auto stagingBufferInfo = vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT); 1367 vk::BufferWithMemory stagingBuffer {vkd, device, allocator, stagingBufferInfo, MemoryRequirement::HostVisible}; 1368 1369 // Descriptor set layout. 1370 vk::DescriptorSetLayoutBuilder layoutBuilder; 1371 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT); 1372 layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT); 1373 auto descriptorSetLayout = layoutBuilder.build(vkd, device); 1374 1375 // Descriptor pool. 1376 vk::DescriptorPoolBuilder poolBuilder; 1377 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u); 1378 auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 1379 1380 // Descriptor set. 1381 const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get()); 1382 1383 // Update descriptor set using the images. 1384 const auto storageImgDescriptorInfo = vk::makeDescriptorImageInfo(DE_NULL, storageImgViewPtr.get(), vk::VK_IMAGE_LAYOUT_GENERAL); 1385 const auto verificationImgDescriptorInfo = vk::makeDescriptorImageInfo(DE_NULL, verificationImgViewPtr.get(), vk::VK_IMAGE_LAYOUT_GENERAL); 1386 1387 vk::DescriptorSetUpdateBuilder updateBuilder; 1388 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &storageImgDescriptorInfo); 1389 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &verificationImgDescriptorInfo); 1390 updateBuilder.update(vkd, device); 1391 1392 // Create write and verification compute pipelines. 1393 auto shaderWriteModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("write"), 0u); 1394 auto shaderVerifyModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("verify"), 0u); 1395 auto pipelineLayout = vk::makePipelineLayout(vkd, device, descriptorSetLayout.get()); 1396 1397 const vk::VkComputePipelineCreateInfo writePipelineCreateInfo = 1398 { 1399 vk::VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, 1400 nullptr, 1401 0u, // flags 1402 { // compute shader 1403 vk::VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 1404 nullptr, // const void* pNext; 1405 0u, // VkPipelineShaderStageCreateFlags flags; 1406 vk::VK_SHADER_STAGE_COMPUTE_BIT, // VkShaderStageFlagBits stage; 1407 shaderWriteModule.getModule(), // VkShaderModule module; 1408 "main", // const char* pName; 1409 nullptr, // const VkSpecializationInfo* pSpecializationInfo; 1410 }, 1411 pipelineLayout.get(), // layout 1412 DE_NULL, // basePipelineHandle 1413 0, // basePipelineIndex 1414 }; 1415 1416 auto verificationPipelineCreateInfo = writePipelineCreateInfo; 1417 verificationPipelineCreateInfo.stage.module = shaderVerifyModule.getModule(); 1418 1419 auto writePipeline = vk::createComputePipeline(vkd, device, DE_NULL, &writePipelineCreateInfo); 1420 auto verificationPipeline = vk::createComputePipeline(vkd, device, DE_NULL, &verificationPipelineCreateInfo); 1421 1422 // Transition images to the correct layout and buffers at different stages. 1423 auto storageImgPreClearBarrier = vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, storageImgPrt.get(), kSubresourceRange); 1424 auto storageImgPreShaderBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, vk::VK_IMAGE_LAYOUT_GENERAL, storageImgPrt.get(), kSubresourceRange); 1425 auto verificationImgPreShaderBarrier = vk::makeImageMemoryBarrier(0, vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, verificationImgPtr.get(), kSubresourceRange); 1426 auto storageImgPreVerificationBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, storageImgPrt.get(), kSubresourceRange); 1427 auto verificationImgPostBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verificationImgPtr.get(), kSubresourceRange); 1428 auto bufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, stagingBuffer.get(), 0ull, bufferSize); 1429 1430 // Command buffer. 1431 auto cmdPool = vk::makeCommandPool(vkd, device, queueIndex); 1432 auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY); 1433 auto cmdBuffer = cmdBufferPtr.get(); 1434 1435 // Clear color for the storage image. 1436 const auto clearColor = vk::makeClearValueColor(WriteSampleTest::kClearColor); 1437 1438 const vk::VkBufferImageCopy copyRegion = 1439 { 1440 0ull, // VkDeviceSize bufferOffset; 1441 extent3D.width, // deUint32 bufferRowLength; 1442 extent3D.height, // deUint32 bufferImageHeight; 1443 { // VkImageSubresourceLayers imageSubresource; 1444 vk::VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 1445 0u, // deUint32 mipLevel; 1446 0u, // deUint32 baseArrayLayer; 1447 1u, // deUint32 layerCount; 1448 }, 1449 { 0, 0, 0 }, // VkOffset3D imageOffset; 1450 extent3D, // VkExtent3D imageExtent; 1451 }; 1452 1453 // Record and submit commands. 1454 vk::beginCommandBuffer(vkd, cmdBuffer); 1455 // Clear storage image. 1456 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreClearBarrier); 1457 vkd.cmdClearColorImage(cmdBuffer, storageImgPrt.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor.color, 1u, &kSubresourceRange); 1458 1459 // Bind write pipeline and descriptor set. 1460 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, writePipeline.get()); 1461 vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0, 1u, &descriptorSet.get(), 0u, nullptr); 1462 1463 // Transition images to the appropriate layout before running the shader. 1464 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreShaderBarrier); 1465 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &verificationImgPreShaderBarrier); 1466 1467 // Run shader. 1468 vkd.cmdDispatch(cmdBuffer, extent3D.width, extent3D.height, extent3D.depth); 1469 1470 // Bind verification pipeline. 1471 vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, verificationPipeline.get()); 1472 1473 // Make sure writes happen before reads in the second dispatch for the storage image. 1474 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &storageImgPreVerificationBarrier); 1475 1476 // Run verification shader. 1477 vkd.cmdDispatch(cmdBuffer, extent3D.width, extent3D.height, extent3D.depth); 1478 1479 // Change verification image layout to prepare the transfer. 1480 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &verificationImgPostBarrier); 1481 1482 // Copy verification image to staging buffer. 1483 vkd.cmdCopyImageToBuffer(cmdBuffer, verificationImgPtr.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer.get(), 1u, ©Region); 1484 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr); 1485 1486 vk::endCommandBuffer(vkd, cmdBuffer); 1487 1488 // Run shaders. 1489 vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer); 1490 1491 // Read buffer pixels. 1492 const auto& bufferAlloc = stagingBuffer.getAllocation(); 1493 vk::invalidateAlloc(vkd, device, bufferAlloc); 1494 1495 // Copy buffer data to texture level and verify all pixels have the proper color. 1496 tcu::TextureLevel texture {tcuFormat, static_cast<int>(extent3D.width), static_cast<int>(extent3D.height), static_cast<int>(extent3D.depth)}; 1497 const auto access = texture.getAccess(); 1498 deMemcpy(access.getDataPtr(), reinterpret_cast<char*>(bufferAlloc.getHostPtr()) + bufferAlloc.getOffset(), static_cast<size_t>(bufferSize)); 1499 1500 for (int i = 0; i < access.getWidth(); ++i) 1501 for (int j = 0; j < access.getHeight(); ++j) 1502 for (int k = 0; k < access.getDepth(); ++k) 1503 { 1504 if (access.getPixel(i, j, k) != WriteSampleTest::kGoodColor) 1505 { 1506 std::ostringstream msg; 1507 msg << "Invalid result at pixel (" << i << ", " << j << ", " << k << "); check error mask for more details"; 1508 m_context.getTestContext().getLog() << tcu::TestLog::Image("ErrorMask", "Indicates which pixels have unexpected values", access); 1509 return tcu::TestStatus::fail(msg.str()); 1510 } 1511 } 1512 1513 return tcu::TestStatus::pass("Pass"); 1514} 1515 1516using WriteSampleMaskParams = WriteSampleParams; 1517 1518class WriteSampleMaskTestCase : public vkt::TestCase 1519{ 1520public: 1521 WriteSampleMaskTestCase (tcu::TestContext& testCtx, const std::string& name, const WriteSampleMaskParams& params); 1522 virtual ~WriteSampleMaskTestCase (void) {} 1523 1524 virtual void checkSupport (Context& context) const; 1525 virtual void initPrograms (vk::SourceCollections& programCollection) const; 1526 virtual TestInstance* createInstance (Context& context) const; 1527 static deUint32 getBufferElems (deUint32 sampleCount); 1528 1529 static const tcu::Vec4 kClearColor; 1530 static const tcu::Vec4 kWriteColor; 1531 1532 static constexpr vk::VkFormat kImageFormat = vk::VK_FORMAT_R8G8B8A8_UNORM; 1533 static constexpr vk::VkImageUsageFlags kUsageFlags = (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT); 1534 static constexpr vk::VkFormatFeatureFlags kFeatureFlags = (vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT); 1535 1536private: 1537 WriteSampleMaskParams m_params; 1538}; 1539 1540const tcu::Vec4 WriteSampleMaskTestCase::kClearColor {0.0f, 0.0f, 0.0f, 1.0f}; 1541const tcu::Vec4 WriteSampleMaskTestCase::kWriteColor {0.0f, 0.0f, 1.0f, 1.0f}; 1542 1543class WriteSampleMaskTestInstance : public vkt::TestInstance 1544{ 1545public: 1546 WriteSampleMaskTestInstance (Context& context, const WriteSampleMaskParams& params); 1547 virtual ~WriteSampleMaskTestInstance (void) {} 1548 1549 virtual tcu::TestStatus iterate (void); 1550 1551private: 1552 WriteSampleMaskParams m_params; 1553}; 1554 1555WriteSampleMaskTestCase::WriteSampleMaskTestCase (tcu::TestContext& testCtx, const std::string& name, const WriteSampleMaskParams& params) 1556 : vkt::TestCase (testCtx, name) 1557 , m_params (params) 1558{} 1559 1560void WriteSampleMaskTestCase::checkSupport (Context& context) const 1561{ 1562 const auto& vki = context.getInstanceInterface(); 1563 const auto physicalDevice = context.getPhysicalDevice(); 1564 1565 // Check if sampleRateShading is supported. 1566 if(!vk::getPhysicalDeviceFeatures(vki, physicalDevice).sampleRateShading) 1567 TCU_THROW(NotSupportedError, "Sample rate shading is not supported"); 1568 1569 // Check the specific image format. 1570 const auto properties = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat); 1571 if (!(properties.optimalTilingFeatures & kFeatureFlags)) 1572 TCU_THROW(NotSupportedError, "Format does not support the required features"); 1573 1574 // Check the supported sample count. 1575 const auto imgProps = vk::getPhysicalDeviceImageFormatProperties(vki, physicalDevice, kImageFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL, kUsageFlags, 0u); 1576 if (!(imgProps.sampleCounts & m_params.sampleCount)) 1577 TCU_THROW(NotSupportedError, "Format does not support the required sample count"); 1578 1579 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType); 1580} 1581 1582void WriteSampleMaskTestCase::initPrograms (vk::SourceCollections& programCollection) const 1583{ 1584 const auto bpc = de::toString(bitsPerCoord(m_params.sampleCount)); 1585 const auto size = imageSize(m_params.sampleCount); 1586 const auto bufferElems = getBufferElems(m_params.sampleCount); 1587 1588 // Passthrough vertex shader. 1589 std::ostringstream vertShader; 1590 1591 vertShader 1592 << "#version 450\n" 1593 << "layout (location=0) in vec2 inPos;\n" 1594 << "void main()\n" 1595 << "{\n" 1596 << " gl_Position = vec4(inPos, 0.0, 1.0);\n" 1597 << "}\n" 1598 ; 1599 1600 // Fragment shader common header. 1601 std::ostringstream fragHeader; 1602 1603 fragHeader 1604 << "#version 450\n" 1605 << "\n" 1606 // The color attachment is useless for the second subpass but avoids having to use an empty subpass and verifying the sample 1607 // count is valid for it. 1608 << "layout (location=0) out vec4 outColor;\n" 1609 << "\n" 1610 << "vec4 wcolor = " << getShaderDecl(kWriteColor) << ";\n" 1611 << "vec4 ccolor = " << getShaderDecl(kClearColor) << ";\n" 1612 << "\n" 1613 ; 1614 1615 const auto fragHeaderStr = fragHeader.str(); 1616 1617 // Fragment shader setting the sample mask and writing to the output color attachment. The sample mask will guarantee each image 1618 // pixel gets a different combination of sample bits set, allowing the fragment shader to write in that sample or not, from all 1619 // zeros in pixel (0, 0) to all ones in the opposite corner. 1620 std::ostringstream fragShaderWrite; 1621 1622 fragShaderWrite 1623 << fragHeaderStr 1624 << "void main()\n" 1625 << "{\n" 1626 << " uvec2 ucoords = uvec2(gl_FragCoord);\n" 1627 << " ivec2 icoords = ivec2(ucoords);\n" 1628 << " gl_SampleMask[0] = int((ucoords.x << " << bpc << ") | ucoords.y);\n" 1629 << " outColor = wcolor;\n" 1630 << "}\n" 1631 ; 1632 1633 // Fragment shader reading from the previous output color attachment and copying the state to an SSBO for verification. 1634 std::ostringstream fragShaderCheck; 1635 1636 const bool isMultiSample = (m_params.sampleCount != vk::VK_SAMPLE_COUNT_1_BIT); 1637 fragShaderCheck 1638 << fragHeaderStr 1639 << "layout(set=0, binding=0, input_attachment_index=0) uniform subpassInput" << (isMultiSample ? "MS" : "") << " inputAttachment;\n" 1640 << "layout(set=0, binding=1, std430) buffer StorageBuffer {\n" 1641 << " int writeFlags[" << bufferElems << "];\n" 1642 << "} sb;\n" 1643 << "\n" 1644 << "void main()\n" 1645 << "{\n" 1646 << " uvec2 ucoords = uvec2(gl_FragCoord);\n" 1647 << " ivec2 icoords = ivec2(ucoords);\n" 1648 << " uint bufferp = ((ucoords.y * " << size.width << " + ucoords.x) * " << m_params.sampleCount << ") + uint(gl_SampleID);\n" 1649 << " vec4 storedc = subpassLoad(inputAttachment" << (isMultiSample ? ", gl_SampleID" : "") << ");\n" 1650 << " sb.writeFlags[bufferp] = ((storedc == wcolor) ? 1 : ((storedc == ccolor) ? 0 : 2));\n" 1651 << " outColor = storedc;\n" 1652 << "}\n" 1653 ; 1654 1655 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.str()); 1656 programCollection.glslSources.add("frag_write") << glu::FragmentSource(fragShaderWrite.str()); 1657 programCollection.glslSources.add("frag_check") << glu::FragmentSource(fragShaderCheck.str()); 1658} 1659 1660TestInstance* WriteSampleMaskTestCase::createInstance (Context& context) const 1661{ 1662 return new WriteSampleMaskTestInstance(context, m_params); 1663} 1664 1665deUint32 WriteSampleMaskTestCase::getBufferElems (deUint32 sampleCount) 1666{ 1667 const auto imgSize = imageSize(sampleCount); 1668 return (imgSize.width * imgSize.height * sampleCount); 1669} 1670 1671WriteSampleMaskTestInstance::WriteSampleMaskTestInstance (Context& context, const WriteSampleMaskParams& params) 1672 : vkt::TestInstance (context) 1673 , m_params (params) 1674{} 1675 1676tcu::TestStatus WriteSampleMaskTestInstance::iterate (void) 1677{ 1678 const auto& vki = m_context.getInstanceInterface(); 1679 const auto& vkd = m_context.getDeviceInterface(); 1680 const auto physicalDevice = m_context.getPhysicalDevice(); 1681 const auto device = m_context.getDevice(); 1682 auto& alloc = m_context.getDefaultAllocator(); 1683 const auto queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 1684 const auto queue = m_context.getUniversalQueue(); 1685 1686 static constexpr auto kImageFormat = WriteSampleMaskTestCase::kImageFormat; 1687 static constexpr auto kImageUsage = WriteSampleMaskTestCase::kUsageFlags; 1688 const auto kImageExtent = getExtent3D(m_params.sampleCount); 1689 const auto kBufferElems = WriteSampleMaskTestCase::getBufferElems(m_params.sampleCount); 1690 const auto kBufferSize = static_cast<vk::VkDeviceSize>(kBufferElems * sizeof(deInt32)); 1691 1692 // Create image. 1693 const vk::VkImageCreateInfo imageCreateInfo = 1694 { 1695 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 1696 nullptr, // const void* pNext; 1697 0u, // VkImageCreateFlags flags; 1698 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType; 1699 kImageFormat, // VkFormat format; 1700 kImageExtent, // VkExtent3D extent; 1701 1u, // deUint32 mipLevels; 1702 1u, // deUint32 arrayLayers; 1703 m_params.sampleCount, // VkSampleCountFlagBits samples; 1704 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 1705 kImageUsage, // VkImageUsageFlags usage; 1706 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 1707 0u, // deUint32 queueFamilyIndexCount; 1708 nullptr, // const deUint32* pQueueFamilyIndices; 1709 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1710 }; 1711 1712 const vk::ImageWithMemory colorImage (vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any); 1713 const vk::ImageWithMemory auxiliarImage (vkd, device, alloc, imageCreateInfo, vk::MemoryRequirement::Any); // For the second subpass. 1714 1715 // Image views. 1716 const auto subresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 1717 const auto colorImageView = vk::makeImageView(vkd, device, colorImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, subresourceRange); 1718 const auto auxiliarImageView = vk::makeImageView(vkd, device, auxiliarImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, subresourceRange); 1719 1720 // Create storage buffer used to verify results. 1721 const vk::BufferWithMemory storageBuffer(vkd, device, alloc, vk::makeBufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), vk::MemoryRequirement::HostVisible); 1722 1723 // Full-screen quad. 1724 const std::vector<tcu::Vec2> quadVertices = 1725 { 1726 tcu::Vec2(-1.0f, 1.0f), // Lower left 1727 tcu::Vec2( 1.0f, 1.0f), // Lower right 1728 tcu::Vec2( 1.0f, -1.0f), // Top right. 1729 tcu::Vec2(-1.0f, 1.0f), // Lower left 1730 tcu::Vec2( 1.0f, -1.0f), // Top right. 1731 tcu::Vec2(-1.0f, -1.0f), // Top left. 1732 }; 1733 1734 // Vertex buffer. 1735 const auto vertexBufferSize = static_cast<vk::VkDeviceSize>(quadVertices.size() * sizeof(decltype(quadVertices)::value_type)); 1736 const vk::BufferWithMemory vertexBuffer (vkd, device, alloc, vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), vk::MemoryRequirement::HostVisible); 1737 const auto& vertexBufferAlloc = vertexBuffer.getAllocation(); 1738 void* vertexBufferPtr = vertexBufferAlloc.getHostPtr(); 1739 const vk::VkDeviceSize vertexBufferOffset = 0; 1740 deMemcpy(vertexBufferPtr, quadVertices.data(), static_cast<size_t>(vertexBufferSize)); 1741 vk::flushAlloc(vkd, device, vertexBufferAlloc); 1742 1743 // Descriptor set layout. 1744 vk::DescriptorSetLayoutBuilder setLayoutBuilder; 1745 setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, vk::VK_SHADER_STAGE_FRAGMENT_BIT); 1746 setLayoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT); 1747 const auto descriptorSetLayout = setLayoutBuilder.build(vkd, device); 1748 1749 // Descriptor pool and set. 1750 vk::DescriptorPoolBuilder poolBuilder; 1751 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u); 1752 poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u); 1753 const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 1754 const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get()); 1755 1756 // Render pass. 1757 const std::vector<vk::VkAttachmentDescription> attachments = 1758 { 1759 // Main color attachment. 1760 { 1761 0u, // VkAttachmentDescriptionFlags flags; 1762 kImageFormat, // VkFormat format; 1763 m_params.sampleCount, // VkSampleCountFlagBits samples; 1764 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 1765 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 1766 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 1767 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 1768 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1769 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout finalLayout; 1770 }, 1771 // Auxiliar color attachment for the check pass. 1772 { 1773 0u, // VkAttachmentDescriptionFlags flags; 1774 kImageFormat, // VkFormat format; 1775 m_params.sampleCount, // VkSampleCountFlagBits samples; 1776 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; 1777 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; 1778 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 1779 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 1780 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1781 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout; 1782 }, 1783 }; 1784 1785 const vk::VkAttachmentReference colorAttachmentReference = 1786 { 1787 0u, // deUint32 attachment; 1788 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; 1789 }; 1790 1791 const vk::VkAttachmentReference colorAsInputAttachment = 1792 { 1793 0u, // deUint32 attachment; 1794 vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout layout; 1795 }; 1796 1797 const vk::VkAttachmentReference auxiliarAttachmentReference = 1798 { 1799 1u, // deUint32 attachment; 1800 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout; 1801 }; 1802 1803 const std::vector<vk::VkSubpassDescription> subpasses = 1804 { 1805 // First subpass writing to the main attachment. 1806 { 1807 0u, // VkSubpassDescriptionFlags flags; 1808 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 1809 0u, // deUint32 inputAttachmentCount; 1810 nullptr, // const VkAttachmentReference* pInputAttachments; 1811 1u, // deUint32 colorAttachmentCount; 1812 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments; 1813 nullptr, // const VkAttachmentReference* pResolveAttachments; 1814 nullptr, // const VkAttachmentReference* pDepthStencilAttachment; 1815 0u, // deUint32 preserveAttachmentCount; 1816 nullptr, // const deUint32* pPreserveAttachments; 1817 }, 1818 // Second subpass writing to the auxiliar attachment. 1819 { 1820 0u, // VkSubpassDescriptionFlags flags; 1821 vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 1822 1u, // deUint32 inputAttachmentCount; 1823 &colorAsInputAttachment, // const VkAttachmentReference* pInputAttachments; 1824 1u, // deUint32 colorAttachmentCount; 1825 &auxiliarAttachmentReference, // const VkAttachmentReference* pColorAttachments; 1826 nullptr, // const VkAttachmentReference* pResolveAttachments; 1827 nullptr, // const VkAttachmentReference* pDepthStencilAttachment; 1828 0u, // deUint32 preserveAttachmentCount; 1829 nullptr, // const deUint32* pPreserveAttachments; 1830 }, 1831 }; 1832 1833 const std::vector<vk::VkSubpassDependency> subpassDependencies = 1834 { 1835 // First subpass writes to the color attachment and second subpass reads it as an input attachment. 1836 { 1837 0u, // deUint32 srcSubpass; 1838 1u, // deUint32 dstSubpass; 1839 vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask; 1840 vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags dstStageMask; 1841 vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; 1842 vk::VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, // VkAccessFlags dstAccessMask; 1843 0u, // VkDependencyFlags dependencyFlags; 1844 }, 1845 }; 1846 1847 const vk::VkRenderPassCreateInfo renderPassInfo = 1848 { 1849 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 1850 nullptr, // const void* pNext; 1851 0u, // VkRenderPassCreateFlags flags; 1852 static_cast<deUint32>(attachments.size()), // deUint32 attachmentCount; 1853 attachments.data(), // const VkAttachmentDescription* pAttachments; 1854 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount; 1855 subpasses.data(), // const VkSubpassDescription* pSubpasses; 1856 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount; 1857 subpassDependencies.data(), // const VkSubpassDependency* pDependencies; 1858 }; 1859 RenderPassWrapper renderPass (m_params.pipelineConstructionType, vkd, device, &renderPassInfo); 1860 1861 // Framebuffer. 1862 const std::vector<vk::VkImage> images = 1863 { 1864 colorImage.get(), 1865 auxiliarImage.get(), 1866 }; 1867 const std::vector<vk::VkImageView> imageViews = 1868 { 1869 colorImageView.get(), 1870 auxiliarImageView.get(), 1871 }; 1872 renderPass.createFramebuffer(vkd, device, static_cast<deUint32>(imageViews.size()), images.data(), imageViews.data(), kImageExtent.width, kImageExtent.height); 1873 1874 // Empty pipeline layout for the first subpass. 1875 const PipelineLayoutWrapper emptyPipelineLayout (m_params.pipelineConstructionType, vkd, device); 1876 1877 // Pipeline layout for the second subpass. 1878 const PipelineLayoutWrapper checkPipelineLayout (m_params.pipelineConstructionType, vkd, device, descriptorSetLayout.get()); 1879 1880 // Shader modules. 1881 const auto vertModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u); 1882 const auto writeModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag_write"), 0u); 1883 const auto checkModule = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag_check"), 0u); 1884 1885 const std::vector<vk::VkVertexInputBindingDescription> vertexBindings = 1886 { 1887 { 1888 0u, // deUint32 binding; 1889 static_cast<deUint32>(sizeof(decltype(quadVertices)::value_type)), // deUint32 stride; 1890 vk::VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate; 1891 }, 1892 }; 1893 1894 const std::vector<vk::VkVertexInputAttributeDescription> vertexAttributes = 1895 { 1896 { 1897 0u, // deUint32 location; 1898 0u, // deUint32 binding; 1899 vk::VK_FORMAT_R32G32_SFLOAT, // VkFormat format; 1900 0u, // deUint32 offset; 1901 }, 1902 }; 1903 1904 const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo = 1905 { 1906 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 1907 nullptr, // const void* pNext; 1908 0u, // VkPipelineVertexInputStateCreateFlags flags; 1909 static_cast<deUint32>(vertexBindings.size()), // deUint32 vertexBindingDescriptionCount; 1910 vertexBindings.data(), // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 1911 static_cast<deUint32>(vertexAttributes.size()), // deUint32 vertexAttributeDescriptionCount; 1912 vertexAttributes.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 1913 }; 1914 1915 const vk::VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo = 1916 { 1917 vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 1918 nullptr, // const void* pNext; 1919 0u, // VkPipelineInputAssemblyStateCreateFlags flags; 1920 vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology; 1921 VK_FALSE, // VkBool32 primitiveRestartEnable; 1922 }; 1923 1924 const std::vector<VkViewport> viewport { vk::makeViewport(kImageExtent) }; 1925 const std::vector<VkRect2D> scissor { vk::makeRect2D(kImageExtent) }; 1926 1927 const vk::VkPipelineMultisampleStateCreateInfo multisampleInfo = 1928 { 1929 vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 1930 nullptr, // const void* pNext; 1931 0u, // VkPipelineMultisampleStateCreateFlags flags; 1932 m_params.sampleCount, // VkSampleCountFlagBits rasterizationSamples; 1933 VK_FALSE, // VkBool32 sampleShadingEnable; 1934 1.0f, // float minSampleShading; 1935 nullptr, // const VkSampleMask* pSampleMask; 1936 VK_FALSE, // VkBool32 alphaToCoverageEnable; 1937 VK_FALSE, // VkBool32 alphaToOneEnable; 1938 }; 1939 1940 const auto stencilState = vk::makeStencilOpState(vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_STENCIL_OP_KEEP, vk::VK_COMPARE_OP_ALWAYS, 0xFFu, 0xFFu, 0u); 1941 1942 const vk::VkPipelineDepthStencilStateCreateInfo depthStencilInfo = 1943 { 1944 vk::VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 1945 nullptr, // const void* pNext; 1946 0u, // VkPipelineDepthStencilStateCreateFlags flags; 1947 VK_FALSE, // VkBool32 depthTestEnable; 1948 VK_FALSE, // VkBool32 depthWriteEnable; 1949 vk::VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp; 1950 VK_FALSE, // VkBool32 depthBoundsTestEnable; 1951 VK_FALSE, // VkBool32 stencilTestEnable; 1952 stencilState, // VkStencilOpState front; 1953 stencilState, // VkStencilOpState back; 1954 0.0f, // float minDepthBounds; 1955 1.0f, // float maxDepthBounds; 1956 }; 1957 1958 const vk::VkPipelineColorBlendAttachmentState colorBlendAttachmentState = 1959 { 1960 VK_FALSE, // VkBool32 blendEnable; 1961 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcColorBlendFactor; 1962 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 1963 vk::VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 1964 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor srcAlphaBlendFactor; 1965 vk::VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 1966 vk::VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 1967 ( // VkColorComponentFlags colorWriteMask; 1968 vk::VK_COLOR_COMPONENT_R_BIT | 1969 vk::VK_COLOR_COMPONENT_G_BIT | 1970 vk::VK_COLOR_COMPONENT_B_BIT | 1971 vk::VK_COLOR_COMPONENT_A_BIT ), 1972 }; 1973 1974 const vk::VkPipelineColorBlendStateCreateInfo colorBlendInfo = 1975 { 1976 vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 1977 nullptr, // const void* pNext; 1978 0u, // VkPipelineColorBlendStateCreateFlags flags; 1979 VK_FALSE, // VkBool32 logicOpEnable; 1980 vk::VK_LOGIC_OP_NO_OP, // VkLogicOp logicOp; 1981 1u, // deUint32 attachmentCount; 1982 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 1983 { .0f, .0f, .0f, .0f }, // float blendConstants[4]; 1984 }; 1985 1986 const vk::VkPipelineDynamicStateCreateInfo dynamicStateInfo = 1987 { 1988 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType; 1989 nullptr, // const void* pNext; 1990 0u, // VkPipelineDynamicStateCreateFlags flags; 1991 0u, // deUint32 dynamicStateCount; 1992 nullptr, // const VkDynamicState* pDynamicStates; 1993 }; 1994 1995 // Pipeline for the first subpass. 1996 vk::GraphicsPipelineWrapper firstSubpassPipeline(vki, vkd, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 1997 firstSubpassPipeline.setDynamicState(&dynamicStateInfo) 1998 .setDefaultRasterizationState() 1999 .setupVertexInputState(&vertexInputInfo, &inputAssemblyInfo) 2000 .setupPreRasterizationShaderState(viewport, scissor, emptyPipelineLayout, *renderPass, 0u, vertModule) 2001 .setupFragmentShaderState(emptyPipelineLayout, *renderPass, 0u, writeModule, &depthStencilInfo, &multisampleInfo) 2002 .setupFragmentOutputState(*renderPass, 0u, &colorBlendInfo, &multisampleInfo) 2003 .setMonolithicPipelineLayout(emptyPipelineLayout) 2004 .buildPipeline(); 2005 2006 // Pipeline for the second subpass. 2007 vk::GraphicsPipelineWrapper secondSubpassPipeline(vki, vkd, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 2008 secondSubpassPipeline.setDynamicState(&dynamicStateInfo) 2009 .setDefaultRasterizationState() 2010 .setupVertexInputState(&vertexInputInfo, &inputAssemblyInfo) 2011 .setupPreRasterizationShaderState(viewport, scissor, checkPipelineLayout, *renderPass, 1u, vertModule) 2012 .setupFragmentShaderState(checkPipelineLayout, *renderPass, 1u, checkModule, &depthStencilInfo, &multisampleInfo) 2013 .setupFragmentOutputState(*renderPass, 1u, &colorBlendInfo, &multisampleInfo) 2014 .setMonolithicPipelineLayout(checkPipelineLayout) 2015 .buildPipeline(); 2016 2017 // Command pool and command buffer. 2018 const auto cmdPool = vk::makeCommandPool(vkd, device, queueFamilyIndex); 2019 const auto cmdBufferPtr = vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY); 2020 const auto cmdBuffer = cmdBufferPtr.get(); 2021 2022 // Update descriptor set. 2023 vk::DescriptorSetUpdateBuilder updateBuilder; 2024 const auto imageInfo = vk::makeDescriptorImageInfo(DE_NULL, colorImageView.get(), vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 2025 const auto bufferInfo = vk::makeDescriptorBufferInfo(storageBuffer.get(), 0u, VK_WHOLE_SIZE); 2026 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfo); 2027 updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo); 2028 updateBuilder.update(vkd, device); 2029 2030 // Output buffer pipeline barrier. 2031 const auto bufferBarrier = vk::makeBufferMemoryBarrier(vk::VK_ACCESS_SHADER_WRITE_BIT, vk::VK_ACCESS_HOST_READ_BIT, storageBuffer.get(), 0ull, VK_WHOLE_SIZE); 2032 2033 // Run pipelines. 2034 vk::beginCommandBuffer(vkd, cmdBuffer); 2035 2036 renderPass.begin(vkd, cmdBuffer, vk::makeRect2D(kImageExtent), WriteSampleMaskTestCase::kClearColor); 2037 vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset); 2038 firstSubpassPipeline.bind(cmdBuffer); 2039 vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(quadVertices.size()), 1u, 0u, 0u); 2040 2041 renderPass.nextSubpass(vkd, cmdBuffer, vk::VK_SUBPASS_CONTENTS_INLINE); 2042 secondSubpassPipeline.bind(cmdBuffer); 2043 vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, checkPipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr); 2044 vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(quadVertices.size()), 1u, 0u, 0u); 2045 2046 renderPass.end(vkd, cmdBuffer); 2047 vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, nullptr, 1u, &bufferBarrier, 0u, nullptr); 2048 vk::endCommandBuffer(vkd, cmdBuffer); 2049 2050 vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer); 2051 2052 // Check buffer contents. 2053 auto& bufferAlloc = storageBuffer.getAllocation(); 2054 const void* bufferPtr = bufferAlloc.getHostPtr(); 2055 std::vector<deInt32> bufferContents (kBufferElems, 0); 2056 2057 vk::invalidateAlloc(vkd, device, bufferAlloc); 2058 deMemcpy(bufferContents.data(), bufferPtr, static_cast<size_t>(kBufferSize)); 2059 2060 const auto sampleCount = static_cast<deUint32>(m_params.sampleCount); 2061 const auto bpc = bitsPerCoord(sampleCount); 2062 2063 for (deUint32 x = 0; x < kImageExtent.width; ++x) 2064 for (deUint32 y = 0; y < kImageExtent.height; ++y) 2065 { 2066 // Samples on which we expect writes. 2067 const deUint32 sampleMask = ((x << bpc) | y); 2068 2069 // Starting location for the pixel sample values in the buffer. 2070 const deUint32 pixelOffset = (y * kImageExtent.width + x) * sampleCount; 2071 2072 for (deUint32 s = 0; s < sampleCount; ++s) 2073 { 2074 const deUint32 sampleIndex = pixelOffset + s; 2075 const deInt32& value = bufferContents[sampleIndex]; 2076 2077 if (value != 0 && value != 1) 2078 { 2079 // Garbage! 2080 std::ostringstream msg; 2081 msg << "Found garbage value " << value << " in buffer position " << sampleIndex << " (x=" << x << ", y=" << y << ", sample=" << s << ")"; 2082 return tcu::TestStatus::fail(msg.str()); 2083 } 2084 2085 const deInt32 expected = (((sampleMask & (1u << s)) != 0u) ? 1 : 0); 2086 if (value != expected) 2087 { 2088 std::ostringstream msg; 2089 msg << "Read " << value << " while expecting " << expected << " in buffer position " << sampleIndex << " (x=" << x << ", y=" << y << ", sample=" << s << ")"; 2090 return tcu::TestStatus::fail(msg.str()); 2091 } 2092 } 2093 } 2094 2095 return tcu::TestStatus::pass("Pass"); 2096} 2097 2098} // multisample 2099 2100tcu::TestCaseGroup* createMultisampleShaderBuiltInTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType) 2101{ 2102 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_shader_builtin")); 2103 2104 const tcu::UVec3 imageSizes[] = 2105 { 2106 tcu::UVec3(128u, 128u, 1u), 2107 tcu::UVec3(137u, 191u, 1u), 2108 }; 2109 2110 const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3)); 2111 2112 const vk::VkSampleCountFlagBits samplesSetFull[] = 2113 { 2114 vk::VK_SAMPLE_COUNT_2_BIT, 2115 vk::VK_SAMPLE_COUNT_4_BIT, 2116 vk::VK_SAMPLE_COUNT_8_BIT, 2117 vk::VK_SAMPLE_COUNT_16_BIT, 2118 vk::VK_SAMPLE_COUNT_32_BIT, 2119 vk::VK_SAMPLE_COUNT_64_BIT, 2120 }; 2121 2122 const deUint32 samplesSetFullCount = static_cast<deUint32>(sizeof(samplesSetFull) / sizeof(vk::VkSampleCountFlagBits)); 2123 2124 testGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleID> >(testCtx, "sample_id", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount)); 2125 2126 de::MovePtr<tcu::TestCaseGroup> samplePositionGroup(new tcu::TestCaseGroup(testCtx, "sample_position")); 2127 2128 samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosDistribution> >(testCtx, "distribution", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount)); 2129 samplePositionGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSamplePosCorrectness> > (testCtx, "correctness", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetFull, samplesSetFullCount)); 2130 2131 testGroup->addChild(samplePositionGroup.release()); 2132 2133 const vk::VkSampleCountFlagBits samplesSetReduced[] = 2134 { 2135 vk::VK_SAMPLE_COUNT_2_BIT, 2136 vk::VK_SAMPLE_COUNT_4_BIT, 2137 vk::VK_SAMPLE_COUNT_8_BIT, 2138 vk::VK_SAMPLE_COUNT_16_BIT, 2139 vk::VK_SAMPLE_COUNT_32_BIT, 2140 }; 2141 2142 const deUint32 samplesSetReducedCount = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(samplesSetReduced)); 2143 2144 de::MovePtr<tcu::TestCaseGroup> sampleMaskGroup(new tcu::TestCaseGroup(testCtx, "sample_mask")); 2145 2146 sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskPattern> > (testCtx, "pattern", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); 2147 sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> > (testCtx, "bit_count", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); 2148 sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskBitCount> > (testCtx, "bit_count_0_5", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount, multisample::ComponentData{}, 0.5f)); 2149 sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskCorrectBit> >(testCtx, "correct_bit", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); 2150 sampleMaskGroup->addChild(makeMSGroup<multisample::MSCase<multisample::MSCaseSampleMaskWrite> > (testCtx, "write", pipelineConstructionType, imageSizes, sizesElemCount, samplesSetReduced, samplesSetReducedCount)); 2151 2152 testGroup->addChild(sampleMaskGroup.release()); 2153 2154 // Write image sample tests using a storage images (tests construct only compute pipeline). 2155 if (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC) 2156 { 2157 // Test OpImageWrite with a sample ID 2158 de::MovePtr<tcu::TestCaseGroup> imageWriteSampleGroup(new tcu::TestCaseGroup(testCtx, "image_write_sample")); 2159 2160 for (auto count : multisample::kValidSquareSampleCounts) 2161 { 2162 if (count == vk::VK_SAMPLE_COUNT_1_BIT) 2163 continue; 2164 2165 multisample::WriteSampleParams params { pipelineConstructionType, static_cast<vk::VkSampleCountFlagBits>(count) }; 2166 const auto countStr = de::toString(count); 2167 imageWriteSampleGroup->addChild(new multisample::WriteSampleTest(testCtx, countStr + "_samples", params)); 2168 } 2169 2170 testGroup->addChild(imageWriteSampleGroup.release()); 2171 } 2172 2173 // Write to gl_SampleMask from the fragment shader. 2174 { 2175 de::MovePtr<tcu::TestCaseGroup> writeSampleMaskGroup(new tcu::TestCaseGroup(testCtx, "write_sample_mask")); 2176 2177 for (auto count : multisample::kValidSquareSampleCounts) 2178 { 2179 multisample::WriteSampleMaskParams params { pipelineConstructionType, static_cast<vk::VkSampleCountFlagBits>(count) }; 2180 const auto countStr = de::toString(count); 2181 writeSampleMaskGroup->addChild(new multisample::WriteSampleMaskTestCase(testCtx, countStr + "_samples", params)); 2182 } 2183 2184 testGroup->addChild(writeSampleMaskGroup.release()); 2185 } 2186 2187 return testGroup.release(); 2188} 2189 2190} // pipeline 2191} // vkt 2192