1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2019 Advanced Micro Devices, Inc. 6 * Copyright (c) 2019 The Khronos Group Inc. 7 * Copyright (c) 2023 LunarG, Inc. 8 * Copyright (c) 2023 Nintendo 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * 22 *//*! 23 * \file 24 * \brief Tests for VK_AMD_mixed_attachment_samples 25 *//*--------------------------------------------------------------------*/ 26 27#include "vktPipelineMultisampleMixedAttachmentSamplesTests.hpp" 28#include "vktPipelineSampleLocationsUtil.hpp" 29#include "vktPipelineMakeUtil.hpp" 30#include "vktTestCase.hpp" 31#include "vktTestCaseUtil.hpp" 32#include "vktTestGroupUtil.hpp" 33 34#include "vkCmdUtil.hpp" 35#include "vkObjUtil.hpp" 36#include "vkPlatform.hpp" 37#include "vkMemUtil.hpp" 38#include "vkQueryUtil.hpp" 39#include "vkTypeUtil.hpp" 40#include "vkRefUtil.hpp" 41#include "vkBuilderUtil.hpp" 42#include "vkPrograms.hpp" 43#include "vkImageUtil.hpp" 44 45#include "deUniquePtr.hpp" 46#include "deSharedPtr.hpp" 47#include "deRandom.hpp" 48#include "deMath.h" 49 50#include "tcuVector.hpp" 51#include "tcuTestLog.hpp" 52#include "tcuImageCompare.hpp" 53#include "tcuTextureUtil.hpp" 54#include "tcuRGBA.hpp" 55 56#include <string> 57#include <vector> 58 59namespace vkt 60{ 61namespace pipeline 62{ 63namespace 64{ 65using namespace vk; 66using de::UniquePtr; 67using de::MovePtr; 68using de::SharedPtr; 69using tcu::UVec2; 70using tcu::Vec2; 71using tcu::Vec4; 72 73bool compareGreenImage (tcu::TestLog& log, const char* name, const char* description, const tcu::ConstPixelBufferAccess& image) 74{ 75 tcu::TextureLevel greenImage(image.getFormat(), image.getWidth(), image.getHeight()); 76 tcu::clear(greenImage.getAccess(), tcu::RGBA::green().toIVec()); 77 return tcu::intThresholdCompare(log, name, description, greenImage.getAccess(), image, tcu::UVec4(2u), tcu::COMPARE_LOG_RESULT); 78} 79 80VkImageAspectFlags getImageAspectFlags (const VkFormat format) 81{ 82 const tcu::TextureFormat tcuFormat = mapVkFormat(format); 83 84 if (tcuFormat.order == tcu::TextureFormat::DS) return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; 85 else if (tcuFormat.order == tcu::TextureFormat::D) return VK_IMAGE_ASPECT_DEPTH_BIT; 86 else if (tcuFormat.order == tcu::TextureFormat::S) return VK_IMAGE_ASPECT_STENCIL_BIT; 87 88 DE_ASSERT(false); 89 return 0u; 90} 91 92struct CompareData 93{ 94 Vec4 color; 95 float depth; 96 deUint32 stencil; 97 98 // Pad to 2*16 bytes, in the shader the base alignment of this structure is 16 due to vec4 99 deUint32 padding[2]; 100 101 CompareData() : color(Vec4(0.0f)), depth(0.0f), stencil(0u) 102 { 103 padding[0] = 0u; 104 padding[1] = 0u; 105 106 static_assert(sizeof(CompareData) == (2 * 16), "Wrong structure size, expected 16 bytes"); 107 } 108}; 109 110//! Make a (unused) sampler. 111Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device) 112{ 113 const VkSamplerCreateInfo samplerParams = 114 { 115 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType; 116 DE_NULL, // const void* pNext; 117 (VkSamplerCreateFlags)0, // VkSamplerCreateFlags flags; 118 VK_FILTER_NEAREST, // VkFilter magFilter; 119 VK_FILTER_NEAREST, // VkFilter minFilter; 120 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode; 121 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU; 122 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV; 123 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW; 124 0.0f, // float mipLodBias; 125 VK_FALSE, // VkBool32 anisotropyEnable; 126 1.0f, // float maxAnisotropy; 127 VK_FALSE, // VkBool32 compareEnable; 128 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp; 129 0.0f, // float minLod; 130 0.0f, // float maxLod; 131 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor; 132 VK_FALSE, // VkBool32 unnormalizedCoordinates; 133 }; 134 return createSampler(vk, device, &samplerParams); 135} 136 137Move<VkImage> makeImage (const DeviceInterface& vk, 138 const VkDevice device, 139 const VkFormat format, 140 const UVec2& size, 141 const VkSampleCountFlagBits samples, 142 const VkImageUsageFlags usage) 143{ 144 const VkImageCreateInfo imageParams = 145 { 146 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 147 DE_NULL, // const void* pNext; 148 (VkImageCreateFlags)0, // VkImageCreateFlags flags; 149 VK_IMAGE_TYPE_2D, // VkImageType imageType; 150 format, // VkFormat format; 151 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 152 1u, // deUint32 mipLevels; 153 1u, // deUint32 arrayLayers; 154 samples, // VkSampleCountFlagBits samples; 155 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 156 usage, // VkImageUsageFlags usage; 157 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 158 0u, // deUint32 queueFamilyIndexCount; 159 DE_NULL, // const deUint32* pQueueFamilyIndices; 160 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 161 }; 162 return createImage(vk, device, &imageParams); 163} 164 165inline bool isDepthFormat (const VkFormat format) 166{ 167 return (getImageAspectFlags(format) & VK_IMAGE_ASPECT_DEPTH_BIT) != 0; 168} 169 170inline bool isStencilFormat (const VkFormat format) 171{ 172 return (getImageAspectFlags(format) & VK_IMAGE_ASPECT_STENCIL_BIT) != 0; 173} 174 175//! Create a test-specific MSAA pipeline 176void preparePipelineWrapper(GraphicsPipelineWrapper& gpw, 177 const PipelineLayoutWrapper& pipelineLayout, 178 const VkRenderPass renderPass, 179 const ShaderWrapper vertexModule, 180 const ShaderWrapper fragmentModule, 181 const bool useVertexInput, 182 const deUint32 subpassNdx, 183 const UVec2& renderSize, 184 const VkImageAspectFlags depthStencilAspect, //!< Used to determine which D/S tests to turn on 185 const VkSampleCountFlagBits numSamples, 186 const bool sampleShadingEnable, 187 const bool useFragmentShadingRate, 188 const VkSampleLocationsInfoEXT* pSampleLocationsInfo = DE_NULL) 189{ 190 std::vector<VkVertexInputBindingDescription> vertexInputBindingDescriptions; 191 std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions; 192 193 // Vertex attributes: position and color 194 if (useVertexInput) 195 { 196 vertexInputBindingDescriptions.push_back (makeVertexInputBindingDescription (0u, 2 * sizeof(Vec4), VK_VERTEX_INPUT_RATE_VERTEX)); 197 vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u)); 198 vertexInputAttributeDescriptions.push_back(makeVertexInputAttributeDescription(1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, sizeof(Vec4))); 199 } 200 201 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = 202 { 203 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 204 DE_NULL, // const void* pNext; 205 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 206 static_cast<deUint32>(vertexInputBindingDescriptions.size()), // uint32_t vertexBindingDescriptionCount; 207 dataOrNullPtr(vertexInputBindingDescriptions), // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 208 static_cast<deUint32>(vertexInputAttributeDescriptions.size()), // uint32_t vertexAttributeDescriptionCount; 209 dataOrNullPtr(vertexInputAttributeDescriptions), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 210 }; 211 212 const std::vector<VkViewport> viewport { makeViewport(renderSize.x(), renderSize.y()) }; 213 const std::vector<VkRect2D> scissor { makeRect2D(renderSize.x(), renderSize.y()) }; 214 215 VkPipelineSampleLocationsStateCreateInfoEXT pipelineSampleLocationsCreateInfo = 216 { 217 VK_STRUCTURE_TYPE_PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT, // VkStructureType sType; 218 DE_NULL, // const void* pNext; 219 VK_TRUE, // VkBool32 sampleLocationsEnable; 220 VkSampleLocationsInfoEXT(), // VkSampleLocationsInfoEXT sampleLocationsInfo; 221 }; 222 223 VkPipelineMultisampleStateCreateInfo pipelineMultisampleStateInfo = 224 { 225 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 226 DE_NULL, // const void* pNext; 227 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 228 numSamples, // VkSampleCountFlagBits rasterizationSamples; 229 sampleShadingEnable, // VkBool32 sampleShadingEnable; 230 1.0f, // float minSampleShading; 231 DE_NULL, // const VkSampleMask* pSampleMask; 232 VK_FALSE, // VkBool32 alphaToCoverageEnable; 233 VK_FALSE // VkBool32 alphaToOneEnable; 234 }; 235 236 if (pSampleLocationsInfo) 237 { 238 pipelineSampleLocationsCreateInfo.sampleLocationsInfo = *pSampleLocationsInfo; 239 pipelineMultisampleStateInfo.pNext = &pipelineSampleLocationsCreateInfo; 240 } 241 242 // Simply increment the buffer 243 const VkStencilOpState stencilOpState = makeStencilOpState( 244 VK_STENCIL_OP_KEEP, // stencil fail 245 VK_STENCIL_OP_INCREMENT_AND_CLAMP, // depth & stencil pass 246 VK_STENCIL_OP_KEEP, // depth only fail 247 VK_COMPARE_OP_ALWAYS, // compare op 248 ~0u, // compare mask 249 ~0u, // write mask 250 0u); // reference 251 252 // Always pass the depth test 253 VkPipelineDepthStencilStateCreateInfo pipelineDepthStencilStateInfo = 254 { 255 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 256 DE_NULL, // const void* pNext; 257 (VkPipelineDepthStencilStateCreateFlags)0, // VkPipelineDepthStencilStateCreateFlags flags; 258 (depthStencilAspect & VK_IMAGE_ASPECT_DEPTH_BIT) != 0u, // VkBool32 depthTestEnable; 259 VK_TRUE, // VkBool32 depthWriteEnable; 260 VK_COMPARE_OP_ALWAYS, // VkCompareOp depthCompareOp; 261 VK_FALSE, // VkBool32 depthBoundsTestEnable; 262 (depthStencilAspect & VK_IMAGE_ASPECT_STENCIL_BIT) != 0u, // VkBool32 stencilTestEnable; 263 stencilOpState, // VkStencilOpState front; 264 stencilOpState, // VkStencilOpState back; 265 0.0f, // float minDepthBounds; 266 1.0f, // float maxDepthBounds; 267 }; 268 269 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 270 const VkPipelineColorBlendAttachmentState defaultBlendAttachmentState = 271 { 272 VK_FALSE, // VkBool32 blendEnable; 273 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 274 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 275 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 276 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 277 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 278 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 279 colorComponentsAll, // VkColorComponentFlags colorWriteMask; 280 }; 281 282 const VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateInfo = 283 { 284 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 285 DE_NULL, // const void* pNext; 286 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 287 VK_FALSE, // VkBool32 logicOpEnable; 288 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 289 1u, // deUint32 attachmentCount; 290 &defaultBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 291 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 292 }; 293 294 VkPipelineFragmentShadingRateStateCreateInfoKHR shadingRateStateCreateInfo 295 { 296 VK_STRUCTURE_TYPE_PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR, // VkStructureType sType; 297 DE_NULL, // const void* pNext; 298 { 2, 2 }, // VkExtent2D fragmentSize; 299 { VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR, VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR }, // VkFragmentShadingRateCombinerOpKHR combinerOps[2]; 300 }; 301 302 gpw.setDefaultRasterizationState() 303 .setupVertexInputState(&vertexInputStateInfo) 304 .setupPreRasterizationShaderState(viewport, 305 scissor, 306 pipelineLayout, 307 renderPass, 308 subpassNdx, 309 vertexModule, 310 nullptr, ShaderWrapper(), ShaderWrapper(), ShaderWrapper(), DE_NULL, 311 (useFragmentShadingRate ? &shadingRateStateCreateInfo : nullptr)) 312 .setupFragmentShaderState(pipelineLayout, 313 renderPass, 314 subpassNdx, 315 fragmentModule, 316 &pipelineDepthStencilStateInfo, 317 &pipelineMultisampleStateInfo) 318 .setupFragmentOutputState(renderPass, subpassNdx, &pipelineColorBlendStateInfo, &pipelineMultisampleStateInfo) 319 .setMonolithicPipelineLayout(pipelineLayout) 320 .buildPipeline(); 321} 322 323//! Wrap float after an increment 324inline float wrapIncFloat (float a, float min, float max) 325{ 326 return deFloatMax(min, deFloatMod(a, max)); 327} 328 329//! Generate expected data for color, depth, and stencil samples of a given image. 330//! Samples are ordered starting at pixel (0, 0) - see compute shader source for reference. 331std::vector<CompareData> generateCompareData (const deUint32 seed, 332 const UVec2& imageSize, 333 const deUint32 numCoverageSamples, 334 const deUint32 numColorSamples, 335 const deUint32 numDepthStencilSamples) 336{ 337 std::vector<CompareData> allData; 338 de::Random rng (seed); 339 340 for (deUint32 y = 0u; y < imageSize.y(); ++y) 341 for (deUint32 x = 0u; x < imageSize.x(); ++x) 342 for (deUint32 sample = 0u; sample < numCoverageSamples; ++sample) 343 { 344 CompareData cd; 345 346 if (sample < numColorSamples) 347 { 348 for (int i = 0; i < 3; ++i) 349 cd.color[i] = 0.1f * static_cast<float>(rng.getInt(1, 10)); 350 351 cd.color.w() = 1.0f; 352 } 353 354 if (sample < numDepthStencilSamples) 355 { 356 const deUint32 globalSample = sample + numColorSamples * (x + imageSize.x() * y); 357 cd.depth = wrapIncFloat(0.05f * static_cast<float>(1 + globalSample), 0.05f, 1.0f); 358 cd.stencil = 1 + globalSample % numCoverageSamples; 359 } 360 361 allData.push_back(cd); 362 } 363 364 return allData; 365} 366 367//! NDC transformation algorithm for sample locations 368template<typename SampleAccessor> 369std::vector<Vec2> ndcTransformEachSampleInPixel (const UVec2& framebufferSize, const deUint32 numSamplesPerPixel, const SampleAccessor& access) 370{ 371 std::vector<Vec2> locations; 372 373 for (deUint32 y = 0; y < framebufferSize.y(); ++y) 374 for (deUint32 x = 0; x < framebufferSize.x(); ++x) 375 for (deUint32 sampleNdx = 0; sampleNdx < numSamplesPerPixel; ++sampleNdx) 376 { 377 const Vec2& sp = access(x, y, sampleNdx); 378 const float globalX = sp.x() + static_cast<float>(x); 379 const float globalY = sp.y() + static_cast<float>(y); 380 381 // Transform to [-1, 1] space 382 locations.push_back(Vec2(-1.0f + 2.0f * (globalX / static_cast<float>(framebufferSize.x())), 383 -1.0f + 2.0f * (globalY / static_cast<float>(framebufferSize.y())))); 384 } 385 386 return locations; 387} 388 389class AccessStandardSampleLocationsArray 390{ 391public: 392 AccessStandardSampleLocationsArray (const Vec2* ptr) : m_pData (ptr) {} 393 394 const Vec2& operator ()(const deUint32 x, const deUint32 y, const deUint32 sampleNdx) const 395 { 396 DE_UNREF(x); 397 DE_UNREF(y); 398 return m_pData[sampleNdx]; 399 } 400 401private: 402 const Vec2* m_pData; 403}; 404 405class AccessMultisamplePixelGrid 406{ 407public: 408 AccessMultisamplePixelGrid (const MultisamplePixelGrid* ptr) : m_pGrid (ptr) {} 409 410 Vec2 operator ()(const deUint32 x, const deUint32 y, const deUint32 sampleNdx) const 411 { 412 const VkSampleLocationEXT& sp = m_pGrid->getSample(x, y, sampleNdx); 413 return Vec2(sp.x, sp.y); 414 } 415 416private: 417 const MultisamplePixelGrid* m_pGrid; 418}; 419 420//! Generate NDC space standard sample locations at each framebuffer pixel 421//! Data is filled starting at pixel (0,0) and for each pixel there are numSamples samples 422std::vector<Vec2> genFramebufferStandardSampleLocations (const VkSampleCountFlagBits numSamples, const UVec2& framebufferSize) 423{ 424 static const Vec2 s_location_samples_1[] = 425 { 426 Vec2(0.5f, 0.5f), 427 }; 428 static const Vec2 s_location_samples_2[] = 429 { 430 Vec2(0.75f, 0.75f), 431 Vec2(0.25f, 0.25f), 432 }; 433 static const Vec2 s_location_samples_4[] = 434 { 435 Vec2(0.375f, 0.125f), 436 Vec2(0.875f, 0.375f), 437 Vec2(0.125f, 0.625f), 438 Vec2(0.625f, 0.875f), 439 }; 440 static const Vec2 s_location_samples_8[] = 441 { 442 Vec2(0.5625f, 0.3125f), 443 Vec2(0.4375f, 0.6875f), 444 Vec2(0.8125f, 0.5625f), 445 Vec2(0.3125f, 0.1875f), 446 Vec2(0.1875f, 0.8125f), 447 Vec2(0.0625f, 0.4375f), 448 Vec2(0.6875f, 0.9375f), 449 Vec2(0.9375f, 0.0625f), 450 }; 451 static const Vec2 s_location_samples_16[] = 452 { 453 Vec2(0.5625f, 0.5625f), 454 Vec2(0.4375f, 0.3125f), 455 Vec2(0.3125f, 0.6250f), 456 Vec2(0.7500f, 0.4375f), 457 Vec2(0.1875f, 0.3750f), 458 Vec2(0.6250f, 0.8125f), 459 Vec2(0.8125f, 0.6875f), 460 Vec2(0.6875f, 0.1875f), 461 Vec2(0.3750f, 0.8750f), 462 Vec2(0.5000f, 0.0625f), 463 Vec2(0.2500f, 0.1250f), 464 Vec2(0.1250f, 0.7500f), 465 Vec2(0.0000f, 0.5000f), 466 Vec2(0.9375f, 0.2500f), 467 Vec2(0.8750f, 0.9375f), 468 Vec2(0.0625f, 0.0000f), 469 }; 470 471 const Vec2* pSampleLocation = DE_NULL; 472 473 switch (numSamples) 474 { 475 case VK_SAMPLE_COUNT_1_BIT: pSampleLocation = s_location_samples_1; break; 476 case VK_SAMPLE_COUNT_2_BIT: pSampleLocation = s_location_samples_2; break; 477 case VK_SAMPLE_COUNT_4_BIT: pSampleLocation = s_location_samples_4; break; 478 case VK_SAMPLE_COUNT_8_BIT: pSampleLocation = s_location_samples_8; break; 479 case VK_SAMPLE_COUNT_16_BIT: pSampleLocation = s_location_samples_16; break; 480 481 default: 482 DE_ASSERT(0); 483 return std::vector<Vec2>(); 484 } 485 486 return ndcTransformEachSampleInPixel(framebufferSize, static_cast<deUint32>(numSamples), AccessStandardSampleLocationsArray(pSampleLocation)); 487} 488 489//! Generate NDC space custom sample locations at each framebuffer pixel, based on the given pixel grid 490std::vector<Vec2> getSampleLocations (const MultisamplePixelGrid& pixelGrid, const UVec2& framebufferSize) 491{ 492 return ndcTransformEachSampleInPixel(framebufferSize, pixelGrid.samplesPerPixel(), AccessMultisamplePixelGrid(&pixelGrid)); 493} 494 495struct PositionColor 496{ 497 tcu::Vec4 position; 498 tcu::Vec4 color; 499 500 PositionColor (const tcu::Vec4& pos, const tcu::Vec4& col) : position(pos), color(col) {} 501}; 502 503//! Generate subpixel triangles containing the sample position, based on compare data. 504//! Stencil values are created by overlapping triangles, so the stencil pipeline state must be set up accordingly. 505std::vector<PositionColor> generateSubpixelTriangles (const UVec2& renderSize, 506 const std::vector<CompareData>& compareData, 507 const std::vector<Vec2>& sampleLocations) 508{ 509 std::vector<PositionColor> vertices; 510 511 // For each sample location (in the whole framebuffer), create a sub-pixel triangle that contains it. 512 // NDC viewport size is 2.0 in X and Y and NDC pixel width/height depends on the framebuffer resolution. 513 const Vec2 pixelSize = Vec2(2.0f) / renderSize.cast<float>(); 514 const Vec2 offset = pixelSize / 16.0f; // 4 bits precision 515 516 // Surround with a roughly centered triangle 517 const float y1 = 0.5f * offset.y(); 518 const float y2 = 0.35f * offset.y(); 519 const float x1 = 0.5f * offset.x(); 520 521 DE_ASSERT(compareData.size() == sampleLocations.size()); 522 523 for (std::size_t globalSampleNdx = 0; globalSampleNdx < sampleLocations.size(); ++globalSampleNdx) 524 { 525 const Vec2& loc = sampleLocations[globalSampleNdx]; 526 const CompareData& cd = compareData [globalSampleNdx]; 527 528 // Overdraw at the same position to get the desired stencil 529 // Draw at least once, if stencil is 0 530 for (deUint32 i = 0; i < deMaxu32(1u, cd.stencil); ++i) 531 { 532 vertices.push_back(PositionColor(Vec4(loc.x(), loc.y() - y1, cd.depth, 1.0f), cd.color)); 533 vertices.push_back(PositionColor(Vec4(loc.x() - x1, loc.y() + y2, cd.depth, 1.0f), cd.color)); 534 vertices.push_back(PositionColor(Vec4(loc.x() + x1, loc.y() + y2, cd.depth, 1.0f), cd.color)); 535 } 536 } 537 538 return vertices; 539} 540 541void reportSampleError (tcu::TestLog& log, const std::string& sampleDesc, UVec2& renderSize, const deUint32 numCoverageSamples, const deUint32 globalSampleNdx) 542{ 543 const deUint32 pixelNdx = globalSampleNdx / numCoverageSamples; 544 const deUint32 x = pixelNdx % renderSize.x(); 545 const deUint32 y = pixelNdx / renderSize.x(); 546 const deUint32 sample = globalSampleNdx % numCoverageSamples; 547 548 log << tcu::TestLog::Message << "Incorrect " << sampleDesc << " sample (" << sample << ") at pixel (" << x << ", " << y << ")" << tcu::TestLog::EndMessage; 549} 550 551void checkSampleRequirements (Context& context, 552 const VkSampleCountFlagBits numColorSamples, 553 const VkSampleCountFlagBits numDepthStencilSamples, 554 const bool requireStandardSampleLocations) 555{ 556 const VkPhysicalDeviceLimits& limits = context.getDeviceProperties().limits; 557 558 if ((limits.framebufferColorSampleCounts & numColorSamples) == 0u) 559 TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported"); 560 561 if ((limits.framebufferDepthSampleCounts & numDepthStencilSamples) == 0u) 562 TCU_THROW(NotSupportedError, "framebufferDepthSampleCounts: sample count not supported"); 563 564 if ((limits.framebufferStencilSampleCounts & numDepthStencilSamples) == 0u) 565 TCU_THROW(NotSupportedError, "framebufferStencilSampleCounts: sample count not supported"); 566 567 if ((limits.sampledImageColorSampleCounts & numColorSamples) == 0u) 568 TCU_THROW(NotSupportedError, "sampledImageColorSampleCounts: sample count not supported"); 569 570 if ((limits.sampledImageDepthSampleCounts & numDepthStencilSamples) == 0u) 571 TCU_THROW(NotSupportedError, "sampledImageDepthSampleCounts: sample count not supported"); 572 573 if ((limits.sampledImageStencilSampleCounts & numDepthStencilSamples) == 0u) 574 TCU_THROW(NotSupportedError, "sampledImageStencilSampleCounts: sample count not supported"); 575 576 // This is required to output geometry that is covering a specific sample 577 if (requireStandardSampleLocations && !limits.standardSampleLocations) 578 TCU_THROW(NotSupportedError, "standardSampleLocations: not supported"); 579} 580 581void checkImageRequirements (Context& context, 582 const VkFormat format, 583 const VkFormatFeatureFlags requiredFeatureFlags, 584 const VkImageUsageFlags requiredUsageFlags, 585 const VkSampleCountFlagBits requiredSampleCount = VK_SAMPLE_COUNT_1_BIT) 586{ 587 const InstanceInterface& vki = context.getInstanceInterface(); 588 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 589 VkImageFormatProperties imageProperties; 590 591 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, format); 592 593 if ((formatProperties.optimalTilingFeatures & requiredFeatureFlags) != requiredFeatureFlags) 594 TCU_THROW(NotSupportedError, (de::toString(format) + ": format features not supported").c_str()); 595 596 const VkResult result = vki.getPhysicalDeviceImageFormatProperties(physicalDevice, format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, requiredUsageFlags, (VkImageCreateFlags)0, &imageProperties); 597 598 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) 599 TCU_THROW(NotSupportedError, (de::toString(format) + ": format not supported").c_str()); 600 601 if ((imageProperties.sampleCounts & requiredSampleCount) != requiredSampleCount) 602 TCU_THROW(NotSupportedError, (de::toString(format) + ": sample count not supported").c_str()); 603} 604 605//! Used after a render pass color output (draw or resolve) 606void recordCopyOutputImageToBuffer (const DeviceInterface& vk, 607 const VkCommandBuffer cmdBuffer, 608 const UVec2& imageSize, 609 const VkImage srcImage, 610 const VkBuffer dstBuffer) 611{ 612 // Image read barrier after color output 613 { 614 const VkImageMemoryBarrier barrier = 615 { 616 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 617 DE_NULL, // const void* pNext; 618 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; 619 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask; 620 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout oldLayout; 621 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout; 622 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 623 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 624 srcImage, // VkImage image; 625 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u), // VkImageSubresourceRange subresourceRange; 626 }; 627 628 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 0u, DE_NULL, 1u, &barrier); 629 } 630 // Resolve image -> host buffer 631 { 632 const VkBufferImageCopy region = 633 { 634 0ull, // VkDeviceSize bufferOffset; 635 0u, // uint32_t bufferRowLength; 636 0u, // uint32_t bufferImageHeight; 637 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource; 638 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; 639 makeExtent3D(imageSize.x(), imageSize.y(), 1u), // VkExtent3D imageExtent; 640 }; 641 642 vk.cmdCopyImageToBuffer(cmdBuffer, srcImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, dstBuffer, 1u, ®ion); 643 } 644 // Buffer write barrier 645 { 646 const VkBufferMemoryBarrier barrier = 647 { 648 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 649 DE_NULL, // const void* pNext; 650 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask; 651 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 652 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 653 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 654 dstBuffer, // VkBuffer buffer; 655 0ull, // VkDeviceSize offset; 656 VK_WHOLE_SIZE, // VkDeviceSize size; 657 }; 658 659 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 660 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u); 661 } 662} 663 664namespace VerifySamples 665{ 666 667//! The parameters that define a test case 668struct TestParams 669{ 670 struct SampleCount 671 { 672 VkSampleCountFlagBits numCoverageSamples; //!< VkPipelineMultisampleStateCreateInfo::rasterizationSamples 673 VkSampleCountFlagBits numColorSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples 674 VkSampleCountFlagBits numDepthStencilSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples 675 }; 676 677 PipelineConstructionType pipelineConstructionType; //!< The wya pipeline is constructed 678 VkFormat colorFormat; //!< Color attachment format 679 VkFormat depthStencilFormat; //!< D/S attachment format. Will test both aspects if it's a mixed format 680 bool useProgrammableSampleLocations; //!< Try to use VK_EXT_sample_locations if available 681 bool useFragmentShadingRate; //!< Try to use VK_KHR_fragment_shading_rate if available 682 std::vector<SampleCount> perSubpassSamples; //!< Will use multiple subpasses if more than one element 683 684 TestParams (void) 685 : colorFormat () 686 , depthStencilFormat () 687 , useProgrammableSampleLocations () 688 , useFragmentShadingRate () 689 { 690 } 691}; 692 693//! Common data used by the test 694struct WorkingData 695{ 696 struct PerSubpass 697 { 698 deUint32 numVertices; //!< Number of vertices defined in the vertex buffer 699 Move<VkBuffer> vertexBuffer; 700 MovePtr<Allocation> vertexBufferAlloc; 701 Move<VkImage> colorImage; //!< Color image 702 Move<VkImageView> colorImageView; //!< Color attachment 703 MovePtr<Allocation> colorImageAlloc; 704 Move<VkImage> depthStencilImage; //!< Depth stencil image 705 Move<VkImageView> depthStencilImageView; //!< Depth stencil attachment 706 Move<VkImageView> depthOnlyImageView; //!< Depth aspect for shader read 707 Move<VkImageView> stencilOnlyImageView; //!< Stencil aspect for shader read 708 MovePtr<Allocation> depthStencilImageAlloc; 709 Move<VkBuffer> compareBuffer; //!< Buffer used to verify the images - comparison data 710 MovePtr<Allocation> compareBufferAlloc; 711 VkDeviceSize compareBufferSize; 712 Move<VkBuffer> resultBuffer; //!< Buffer used to verify the images - results 713 MovePtr<Allocation> resultBufferAlloc; 714 VkDeviceSize resultBufferSize; 715 deUint32 numResultElements; //!< Number of checksums in the result buffer 716 MovePtr<MultisamplePixelGrid> pixelGrid; //!< Programmable locations 717 718 PerSubpass (void) 719 : numVertices () 720 , compareBufferSize () 721 , resultBufferSize () 722 , numResultElements () 723 { 724 } 725 }; 726 727 UVec2 renderSize; //!< Size of the framebuffer 728 VkPhysicalDeviceSampleLocationsPropertiesEXT sampleLocationsProperties; //!< Used with VK_EXT_sample_locations 729 730 std::vector<de::SharedPtr<PerSubpass> > perSubpass; //!< Test may use more than one set of data 731 732 WorkingData (void) 733 : sampleLocationsProperties () 734 { 735 } 736}; 737 738void addVerificationComputeShader (SourceCollections& programCollection, 739 const VkSampleCountFlagBits numCoverageSamples, 740 const VkSampleCountFlagBits numColorSamples, 741 const VkSampleCountFlagBits numDepthStencilSamples, 742 const VkFormat depthStencilFormat, 743 const std::string& nameSuffix) 744{ 745 const bool isColorMS = (numColorSamples != VK_SAMPLE_COUNT_1_BIT); 746 const bool isDepthStencilMS = (numDepthStencilSamples != VK_SAMPLE_COUNT_1_BIT); 747 const std::string colorBit = de::toString(static_cast<deUint32>(VK_IMAGE_ASPECT_COLOR_BIT)) + "u"; 748 const std::string depthBit = de::toString(static_cast<deUint32>(VK_IMAGE_ASPECT_DEPTH_BIT)) + "u"; 749 const std::string stencilBit = de::toString(static_cast<deUint32>(VK_IMAGE_ASPECT_STENCIL_BIT)) + "u"; 750 751 std::ostringstream src; 752 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 753 << "\n" 754 << "struct CompareData {\n" 755 << " vec4 color;\n" 756 << " float depth;\n" 757 << " uint stencil;\n" 758 << "};\n" 759 << "\n" 760 << "layout(local_size_x = " << static_cast<deUint32>(numCoverageSamples) << ") in;\n" 761 // Always use this descriptor layout and ignore unused bindings 762 << "layout(set = 0, binding = 0, std430) writeonly buffer Output {\n" 763 << " uint values[];\n" 764 << "} sb_out;\n" 765 << "layout(set = 0, binding = 1, std430) readonly buffer InputCompare {\n" 766 << " CompareData data[];\n" 767 << "} sb_cmp;\n" 768 << "layout(set = 0, binding = 2) uniform sampler2D" << (isColorMS ? "MS" : "") << " colorImage;\n" 769 << "layout(set = 0, binding = 3) uniform sampler2D" << (isDepthStencilMS ? "MS" : "") <<" depthImage;\n" 770 << "layout(set = 0, binding = 4) uniform usampler2D" << (isDepthStencilMS ? "MS" : "") <<" stencilImage;\n" 771 << "\n" 772 << "void main (void)\n" 773 << "{\n" 774 775 // Data for each sample in each pixel is laid out linearly (e.g 2 samples): 776 // [pixel(0, 0) sample(0)][pixel(0, 0) sample(1)][pixel(1, 0) sample(0)][pixel(1, 0) sample(1)]... 777 778 << " uint globalIndex = gl_LocalInvocationID.x + gl_WorkGroupSize.x * (gl_WorkGroupID.x + gl_WorkGroupID.y * gl_NumWorkGroups.x);\n" 779 << " ivec2 position = ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y);\n" 780 << " int sampleNdx = int(gl_LocalInvocationID.x);\n" 781 << " uint result = 0u;\n" 782 << "\n" 783 << " // Verify color samples\n" 784 << " if (sampleNdx < " << static_cast<deUint32>(numColorSamples) << ")\n" 785 << " {\n" 786 << " vec4 color = texelFetch(colorImage, position, sampleNdx);\n" // for non-MS (1 sample) case, sampleNdx = 0 and will instead be LOD = 0 787 << " vec4 diff = abs(color - sb_cmp.data[globalIndex].color);\n" 788 << " vec4 threshold = vec4(0.02);\n" 789 << "\n" 790 << " if (all(lessThan(diff, threshold)))\n" 791 << " result |= " << colorBit << ";\n" 792 << " }\n" 793 << " else\n" 794 << " result |= " << colorBit << ";\n" // Pass, if sample doesn't exist 795 << "\n"; 796 797 if (isDepthFormat(depthStencilFormat)) 798 { 799 src << " // Verify depth samples\n" 800 << " if (sampleNdx < " << static_cast<deUint32>(numDepthStencilSamples) << ")\n" 801 << " {\n" 802 << " float depth = texelFetch(depthImage, position, sampleNdx).r;\n" 803 << " float diff = abs(depth - sb_cmp.data[globalIndex].depth);\n" 804 << " float threshold = 0.002;\n" 805 << "\n" 806 << " if (diff < threshold)\n" 807 << " result |= " << depthBit << ";\n" 808 << " }\n" 809 << " else\n" 810 << " result |= " << depthBit << ";\n" 811 << "\n"; 812 } 813 814 if (isStencilFormat(depthStencilFormat)) 815 { 816 src << " // Verify stencil samples\n" 817 << " if (sampleNdx < " << static_cast<deUint32>(numDepthStencilSamples) << ")\n" 818 << " {\n" 819 << " uint stencil = texelFetch(stencilImage, position, sampleNdx).r;\n" 820 << " uint diff = stencil - sb_cmp.data[globalIndex].stencil;\n" 821 << "\n" 822 << " if (diff == 0u)\n" 823 << " result |= " << stencilBit << ";\n" 824 << " }\n" 825 << " else\n" 826 << " result |= " << stencilBit << ";\n" 827 << "\n"; 828 } 829 830 src << " sb_out.values[globalIndex] = result;\n" 831 << "}\n"; 832 programCollection.glslSources.add("comp" + nameSuffix) << glu::ComputeSource(src.str()); 833} 834 835//! Get a compact sample count string in format X_Y_Z 836std::string getSampleCountString (const TestParams::SampleCount& samples) 837{ 838 std::ostringstream str; 839 840 str << static_cast<deUint32>(samples.numCoverageSamples) << "_" 841 << static_cast<deUint32>(samples.numColorSamples) << "_" 842 << static_cast<deUint32>(samples.numDepthStencilSamples); 843 844 return str.str(); 845} 846 847void initPrograms (SourceCollections& programCollection, const TestParams params) 848{ 849 // Vertex shader - position and color 850 { 851 std::ostringstream src; 852 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 853 << "\n" 854 << "layout(location = 0) in vec4 in_position;\n" 855 << "layout(location = 1) in vec4 in_color;\n" 856 << "layout(location = 0) out vec4 o_color;\n" 857 << "\n" 858 << "out gl_PerVertex {\n" 859 << " vec4 gl_Position;\n" 860 << "};\n" 861 << "\n" 862 << "void main(void)\n" 863 << "{\n" 864 << " gl_Position = in_position;\n" 865 << " o_color = in_color;\n" 866 << "}\n"; 867 868 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 869 } 870 871 // Fragment shader - output color from VS 872 { 873 std::ostringstream src; 874 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 875 << "\n" 876 << "layout(location = 0) in vec4 in_color;\n" 877 << "layout(location = 0) out vec4 o_color;\n" 878 << "\n" 879 << "void main(void)\n" 880 << "{\n" 881 << " o_color = in_color;\n" 882 << "}\n"; 883 884 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 885 } 886 887 // Compute shader - image verification 888 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx) 889 { 890 const TestParams::SampleCount& samples = params.perSubpassSamples[subpassNdx]; 891 addVerificationComputeShader(programCollection, 892 samples.numCoverageSamples, 893 samples.numColorSamples, 894 samples.numDepthStencilSamples, 895 params.depthStencilFormat, 896 "_" + getSampleCountString(samples)); 897 } 898} 899 900//! A simple color, depth/stencil draw. Subpasses (if more than one) are independent 901void draw (Context& context, const TestParams& params, WorkingData& wd) 902{ 903 const InstanceInterface& vki = context.getInstanceInterface(); 904 const DeviceInterface& vk = context.getDeviceInterface(); 905 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 906 const VkDevice device = context.getDevice(); 907 const deUint32 numSubpasses = static_cast<deUint32>(wd.perSubpass.size()); 908 909 RenderPassWrapper renderPass; 910 std::vector<VkSampleLocationsInfoEXT> perSubpassSampleLocationsInfo; 911 std::vector<VkAttachmentSampleLocationsEXT> attachmentSampleLocations; 912 std::vector<VkSubpassSampleLocationsEXT> subpassSampleLocations; 913 914 if (params.useProgrammableSampleLocations) 915 for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx) 916 { 917 perSubpassSampleLocationsInfo.push_back(makeSampleLocationsInfo(*wd.perSubpass[subpassNdx]->pixelGrid)); 918 } 919 920 // Create a render pass and a framebuffer 921 { 922 std::vector<VkSubpassDescription> subpasses; 923 std::vector<VkImage> images; 924 std::vector<VkImageView> attachments; 925 std::vector<VkAttachmentDescription> attachmentDescriptions; 926 std::vector<VkAttachmentReference> attachmentReferences; 927 928 // Reserve capacity to avoid invalidating pointers to elements 929 attachmentReferences.reserve(numSubpasses * 2); 930 931 for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx) 932 { 933 images.push_back(wd.perSubpass[subpassNdx]->colorImage.get()); 934 images.push_back(wd.perSubpass[subpassNdx]->depthStencilImage.get()); 935 attachments.push_back(wd.perSubpass[subpassNdx]->colorImageView.get()); 936 attachments.push_back(wd.perSubpass[subpassNdx]->depthStencilImageView.get()); 937 938 attachmentDescriptions.push_back(makeAttachmentDescription( 939 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 940 params.colorFormat, // VkFormat format; 941 params.perSubpassSamples[subpassNdx].numColorSamples, // VkSampleCountFlagBits samples; 942 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 943 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 944 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 945 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 946 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 947 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout; 948 )); 949 950 attachmentDescriptions.push_back(makeAttachmentDescription( 951 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 952 params.depthStencilFormat, // VkFormat format; 953 params.perSubpassSamples[subpassNdx].numDepthStencilSamples, // VkSampleCountFlagBits samples; 954 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 955 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 956 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp; 957 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp; 958 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 959 VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL // VkImageLayout finalLayout; 960 )); 961 962 attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); 963 const VkAttachmentReference* colorRef = &attachmentReferences.back(); 964 965 attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); 966 const VkAttachmentReference* depthStencilRef = &attachmentReferences.back(); 967 968 if (params.useProgrammableSampleLocations) 969 { 970 const VkAttachmentSampleLocationsEXT newAttachmentSampleLocations = 971 { 972 attachmentReferences.back().attachment, // uint32_t attachmentIndex; 973 perSubpassSampleLocationsInfo[subpassNdx], // VkSampleLocationsInfoEXT sampleLocationsInfo; 974 }; 975 attachmentSampleLocations.push_back(newAttachmentSampleLocations); 976 977 const VkSubpassSampleLocationsEXT newSubpassSampleLocations = 978 { 979 subpassNdx, // uint32_t subpassIndex; 980 perSubpassSampleLocationsInfo[subpassNdx], // VkSampleLocationsInfoEXT sampleLocationsInfo; 981 }; 982 subpassSampleLocations.push_back(newSubpassSampleLocations); 983 } 984 985 const VkSubpassDescription subpassDescription = 986 { 987 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 988 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 989 0u, // uint32_t inputAttachmentCount; 990 DE_NULL, // const VkAttachmentReference* pInputAttachments; 991 1u, // uint32_t colorAttachmentCount; 992 colorRef, // const VkAttachmentReference* pColorAttachments; 993 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 994 depthStencilRef, // const VkAttachmentReference* pDepthStencilAttachment; 995 0u, // uint32_t preserveAttachmentCount; 996 DE_NULL, // const uint32_t* pPreserveAttachments; 997 }; 998 999 subpasses.push_back(subpassDescription); 1000 } 1001 1002 // Assume there are no dependencies between subpasses 1003 const VkRenderPassCreateInfo renderPassInfo = 1004 { 1005 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 1006 DE_NULL, // const void* pNext; 1007 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 1008 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount; 1009 dataOrNullPtr(attachmentDescriptions), // const VkAttachmentDescription* pAttachments; 1010 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount; 1011 dataOrNullPtr(subpasses), // const VkSubpassDescription* pSubpasses; 1012 0u, // deUint32 dependencyCount; 1013 DE_NULL, // const VkSubpassDependency* pDependencies; 1014 }; 1015 1016 renderPass = RenderPassWrapper(params.pipelineConstructionType, vk, device, &renderPassInfo); 1017 renderPass.createFramebuffer(vk, device, static_cast<deUint32>(attachments.size()), dataOrNullPtr(images), dataOrNullPtr(attachments), wd.renderSize.x(), wd.renderSize.y()); 1018 } 1019 1020 const ShaderWrapper vertexModule (ShaderWrapper (vk, device, context.getBinaryCollection().get("vert"), 0u)); 1021 const ShaderWrapper fragmentModule (ShaderWrapper (vk, device, context.getBinaryCollection().get("frag"), 0u)); 1022 const PipelineLayoutWrapper pipelineLayout (params.pipelineConstructionType, vk, device); 1023 1024 std::vector<GraphicsPipelineWrapper> pipelines; 1025 1026 for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx) 1027 { 1028 const VkSampleLocationsInfoEXT* pSampleLocationsInfo = (params.useProgrammableSampleLocations ? &perSubpassSampleLocationsInfo[subpassNdx] : DE_NULL); 1029 1030 pipelines.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType); 1031 preparePipelineWrapper(pipelines.back(), pipelineLayout, *renderPass, vertexModule, fragmentModule, /*use vertex input*/ true, subpassNdx, 1032 wd.renderSize, getImageAspectFlags(params.depthStencilFormat), params.perSubpassSamples[subpassNdx].numCoverageSamples, 1033 /*use sample shading*/ true, params.useFragmentShadingRate, pSampleLocationsInfo); 1034 } 1035 1036 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex())); 1037 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1038 1039 beginCommandBuffer(vk, *cmdBuffer); 1040 1041 { 1042 std::vector<VkClearValue> clearValues; 1043 1044 for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx) 1045 { 1046 clearValues.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f)); 1047 clearValues.push_back(makeClearValueDepthStencil(1.0f, 0u)); 1048 } 1049 1050 const VkRect2D renderArea = 1051 { 1052 { 0u, 0u }, 1053 { wd.renderSize.x(), wd.renderSize.y() } 1054 }; 1055 1056 if (params.useProgrammableSampleLocations) 1057 { 1058 const VkRenderPassSampleLocationsBeginInfoEXT renderPassSampleLocationsBeginInfo = 1059 { 1060 VK_STRUCTURE_TYPE_RENDER_PASS_SAMPLE_LOCATIONS_BEGIN_INFO_EXT, // VkStructureType sType; 1061 DE_NULL, // const void* pNext; 1062 static_cast<deUint32>(attachmentSampleLocations.size()), // uint32_t attachmentInitialSampleLocationsCount; 1063 dataOrNullPtr(attachmentSampleLocations), // const VkAttachmentSampleLocationsEXT* pAttachmentInitialSampleLocations; 1064 static_cast<deUint32>(subpassSampleLocations.size()), // uint32_t postSubpassSampleLocationsCount; 1065 dataOrNullPtr(subpassSampleLocations), // const VkSubpassSampleLocationsEXT* pPostSubpassSampleLocations; 1066 }; 1067 1068 renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<deUint32>(clearValues.size()), dataOrNullPtr(clearValues), VK_SUBPASS_CONTENTS_INLINE, &renderPassSampleLocationsBeginInfo); 1069 } else 1070 renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<deUint32>(clearValues.size()), dataOrNullPtr(clearValues)); 1071 } 1072 1073 for (deUint32 subpassNdx = 0; subpassNdx < numSubpasses; ++subpassNdx) 1074 { 1075 if (subpassNdx != 0) 1076 renderPass.nextSubpass(vk, *cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); 1077 1078 const VkDeviceSize vertexBufferOffset = 0ull; 1079 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.perSubpass[subpassNdx]->vertexBuffer.get(), &vertexBufferOffset); 1080 1081 pipelines[subpassNdx].bind(*cmdBuffer); 1082 1083 vk.cmdDraw(*cmdBuffer, wd.perSubpass[subpassNdx]->numVertices, 1u, 0u, 0u); 1084 } 1085 1086 renderPass.end(vk, *cmdBuffer); 1087 1088 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 1089 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer); 1090} 1091 1092void dispatchImageCheck (Context& context, const TestParams& params, WorkingData& wd, const deUint32 subpassNdx) 1093{ 1094 const DeviceInterface& vk = context.getDeviceInterface(); 1095 const VkDevice device = context.getDevice(); 1096 WorkingData::PerSubpass& subpassData = *wd.perSubpass[subpassNdx]; 1097 1098 const Unique<VkSampler> defaultSampler (makeSampler(vk, device)); 1099 1100 // Create descriptor set 1101 1102 const Unique<VkDescriptorSetLayout> descriptorSetLayout( 1103 DescriptorSetLayoutBuilder() 1104 .addSingleBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 1105 .addSingleBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 1106 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &defaultSampler.get()) 1107 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &defaultSampler.get()) 1108 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &defaultSampler.get()) 1109 .build(vk, device)); 1110 1111 const Unique<VkDescriptorPool> descriptorPool( 1112 DescriptorPoolBuilder() 1113 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u) 1114 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 3u) 1115 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); 1116 1117 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); 1118 1119 { 1120 const VkDescriptorBufferInfo compareBufferInfo = makeDescriptorBufferInfo(*subpassData.compareBuffer, 0ull, subpassData.compareBufferSize); 1121 const VkDescriptorBufferInfo resultBufferInfo = makeDescriptorBufferInfo(*subpassData.resultBuffer, 0ull, subpassData.resultBufferSize); 1122 const VkDescriptorImageInfo colorImageInfo = makeDescriptorImageInfo(DE_NULL, *subpassData.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 1123 const VkDescriptorImageInfo depthImageInfo = makeDescriptorImageInfo(DE_NULL, *subpassData.depthOnlyImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 1124 const VkDescriptorImageInfo stencilImageInfo = makeDescriptorImageInfo(DE_NULL, *subpassData.stencilOnlyImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 1125 1126 DescriptorSetUpdateBuilder builder; 1127 1128 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo); 1129 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &compareBufferInfo); 1130 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo); 1131 1132 if (subpassData.depthOnlyImageView) 1133 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(3u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &depthImageInfo); 1134 1135 if (subpassData.stencilOnlyImageView) 1136 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(4u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &stencilImageInfo); 1137 1138 builder.update(vk, device); 1139 } 1140 1141 // Pipeline 1142 1143 const std::string shaderName ("comp_" + getSampleCountString(params.perSubpassSamples[subpassNdx])); 1144 const Unique<VkShaderModule> shaderModule (createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u)); 1145 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout)); 1146 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule)); 1147 1148 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex())); 1149 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1150 1151 beginCommandBuffer(vk, *cmdBuffer); 1152 1153 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); 1154 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 1155 1156 vk.cmdDispatch(*cmdBuffer, wd.renderSize.x(), wd.renderSize.y(), 1u); 1157 1158 { 1159 const VkBufferMemoryBarrier barrier = 1160 { 1161 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 1162 DE_NULL, // const void* pNext; 1163 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask; 1164 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 1165 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1166 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1167 *subpassData.resultBuffer, // VkBuffer buffer; 1168 0ull, // VkDeviceSize offset; 1169 VK_WHOLE_SIZE, // VkDeviceSize size; 1170 }; 1171 1172 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, 1173 (const VkMemoryBarrier*)DE_NULL, 1u, &barrier, 0u, (const VkImageMemoryBarrier*)DE_NULL); 1174 } 1175 1176 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 1177 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer); 1178 1179 invalidateMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(), subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE); 1180} 1181 1182void createPerSubpassData (Context& context, const TestParams& params, WorkingData& wd, const deUint32 subpassNdx) 1183{ 1184 const DeviceInterface& vk = context.getDeviceInterface(); 1185 const VkDevice device = context.getDevice(); 1186 MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))); 1187 const TestParams::SampleCount& samples = params.perSubpassSamples[subpassNdx]; 1188 WorkingData::PerSubpass& subpassData = *wd.perSubpass[subpassNdx]; 1189 1190 // Create images 1191 { 1192 1193 const VkImageUsageFlags colorImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; 1194 const VkImageUsageFlags depthStencilImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; 1195 1196 checkImageRequirements (context, 1197 params.colorFormat, 1198 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT, 1199 colorImageUsageFlags, 1200 samples.numColorSamples); 1201 1202 subpassData.colorImage = makeImage(vk, device, params.colorFormat, wd.renderSize, samples.numColorSamples, colorImageUsageFlags); 1203 subpassData.colorImageAlloc = bindImage(vk, device, *allocator, *subpassData.colorImage, MemoryRequirement::Any); 1204 subpassData.colorImageView = makeImageView(vk, device, *subpassData.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)); 1205 1206 checkImageRequirements (context, 1207 params.depthStencilFormat, 1208 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT, 1209 depthStencilImageUsageFlags, 1210 samples.numDepthStencilSamples); 1211 1212 subpassData.depthStencilImage = makeImage(vk, device, params.depthStencilFormat, wd.renderSize, samples.numDepthStencilSamples, depthStencilImageUsageFlags); 1213 subpassData.depthStencilImageAlloc = bindImage(vk, device, *allocator, *subpassData.depthStencilImage, MemoryRequirement::Any); 1214 subpassData.depthStencilImageView = makeImageView(vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u)); 1215 1216 if (isDepthFormat(params.depthStencilFormat)) 1217 subpassData.depthOnlyImageView = makeImageView(vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u)); 1218 1219 if (isStencilFormat(params.depthStencilFormat)) 1220 subpassData.stencilOnlyImageView = makeImageView(vk, device, *subpassData.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u)); 1221 } 1222 1223 // Create vertex and comparison buffers 1224 { 1225 const deUint32 seed = 123 + 19 * subpassNdx; 1226 const std::vector<CompareData> compareData = generateCompareData(seed, wd.renderSize, samples.numCoverageSamples, samples.numColorSamples, samples.numDepthStencilSamples); 1227 1228 subpassData.compareBufferSize = static_cast<VkDeviceSize>(sizeof(CompareData) * compareData.size()); 1229 subpassData.compareBuffer = makeBuffer(vk, device, subpassData.compareBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); 1230 subpassData.compareBufferAlloc = bindBuffer(vk, device, *allocator, *subpassData.compareBuffer, MemoryRequirement::HostVisible); 1231 1232 deMemcpy(subpassData.compareBufferAlloc->getHostPtr(), dataOrNullPtr(compareData), static_cast<std::size_t>(subpassData.compareBufferSize)); 1233 flushMappedMemoryRange(vk, device, subpassData.compareBufferAlloc->getMemory(), subpassData.compareBufferAlloc->getOffset(), VK_WHOLE_SIZE); 1234 1235 subpassData.numResultElements = static_cast<deUint32>(compareData.size()); 1236 subpassData.resultBufferSize = static_cast<VkDeviceSize>(sizeof(deUint32) * compareData.size()); 1237 subpassData.resultBuffer = makeBuffer(vk, device, subpassData.resultBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); 1238 subpassData.resultBufferAlloc = bindBuffer(vk, device, *allocator, *subpassData.resultBuffer, MemoryRequirement::HostVisible); 1239 1240 deMemset(subpassData.resultBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(subpassData.resultBufferSize)); 1241 flushMappedMemoryRange(vk, device, subpassData.resultBufferAlloc->getMemory(), subpassData.resultBufferAlloc->getOffset(), VK_WHOLE_SIZE); 1242 1243 std::vector<PositionColor> vertices; 1244 1245 if (params.useProgrammableSampleLocations) 1246 { 1247 subpassData.pixelGrid = MovePtr<MultisamplePixelGrid>(new MultisamplePixelGrid(UVec2(wd.sampleLocationsProperties.maxSampleLocationGridSize.width, 1248 wd.sampleLocationsProperties.maxSampleLocationGridSize.height), 1249 samples.numCoverageSamples)); 1250 1251 const deUint32 locationsSeed = 211 + 4 * subpassNdx; 1252 fillSampleLocationsRandom(*subpassData.pixelGrid, wd.sampleLocationsProperties.sampleLocationSubPixelBits, locationsSeed); 1253 vertices = generateSubpixelTriangles(wd.renderSize, compareData, getSampleLocations(*subpassData.pixelGrid, wd.renderSize)); 1254 } 1255 else 1256 { 1257 const std::vector<Vec2> locations = genFramebufferStandardSampleLocations(samples.numCoverageSamples, wd.renderSize); 1258 vertices = generateSubpixelTriangles(wd.renderSize, compareData, locations); 1259 } 1260 1261 const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size()); 1262 subpassData.numVertices = static_cast<deUint32>(vertices.size()); 1263 subpassData.vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 1264 subpassData.vertexBufferAlloc = bindBuffer(vk, device, *allocator, *subpassData.vertexBuffer, MemoryRequirement::HostVisible); 1265 1266 deMemcpy(subpassData.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize)); 1267 flushMappedMemoryRange(vk, device, subpassData.vertexBufferAlloc->getMemory(), subpassData.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE); 1268 } 1269} 1270 1271void checkRequirements (Context& context, TestParams params) 1272{ 1273 context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples"); 1274 1275 if (params.useProgrammableSampleLocations) 1276 context.requireDeviceFunctionality("VK_EXT_sample_locations"); 1277 1278 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx) 1279 { 1280 const TestParams::SampleCount& samples = params.perSubpassSamples[subpassNdx]; 1281 checkSampleRequirements(context, samples.numColorSamples, samples.numDepthStencilSamples, !params.useProgrammableSampleLocations); 1282 } 1283 1284 const auto& vki = context.getInstanceInterface(); 1285 const auto physicalDevice = context.getPhysicalDevice(); 1286 1287 if (params.useFragmentShadingRate) 1288 { 1289 context.requireDeviceFunctionality("VK_KHR_fragment_shading_rate"); 1290 1291 if (!context.getFragmentShadingRateFeatures().pipelineFragmentShadingRate) 1292 TCU_THROW(NotSupportedError, "pipelineFragmentShadingRate not supported"); 1293 1294 // Fetch information about supported fragment shading rates 1295 deUint32 supportedFragmentShadingRateCount = 0; 1296 vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, DE_NULL); 1297 1298 std::vector<vk::VkPhysicalDeviceFragmentShadingRateKHR> supportedFragmentShadingRates(supportedFragmentShadingRateCount, 1299 { 1300 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_KHR, 1301 DE_NULL, 1302 vk::VK_SAMPLE_COUNT_1_BIT, 1303 {1, 1} 1304 }); 1305 vki.getPhysicalDeviceFragmentShadingRatesKHR(physicalDevice, &supportedFragmentShadingRateCount, supportedFragmentShadingRates.data()); 1306 1307 deUint32 cumulativeNeededSamples = 0; 1308 for (const TestParams::SampleCount& samples : params.perSubpassSamples) 1309 cumulativeNeededSamples |= samples.numColorSamples; 1310 1311 bool requiredRateFound = false; 1312 for (const auto& rate : supportedFragmentShadingRates) 1313 { 1314 if ((rate.fragmentSize.width == 2u) && 1315 (rate.fragmentSize.height == 2u) && 1316 (rate.sampleCounts & cumulativeNeededSamples)) 1317 { 1318 requiredRateFound = true; 1319 break; 1320 } 1321 } 1322 1323 if (!requiredRateFound) 1324 TCU_THROW(NotSupportedError, "Required FragmentShadingRate not supported"); 1325 } 1326 1327 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.pipelineConstructionType); 1328} 1329 1330//! Verify the values of all samples in all attachments. 1331tcu::TestStatus test (Context& context, const TestParams params) 1332{ 1333 WorkingData wd; 1334 wd.renderSize = UVec2(2, 2); // Use a very small image, as we will verify all samples for all pixels 1335 1336 // Query state related to programmable sample locations 1337 if (params.useProgrammableSampleLocations) 1338 { 1339 const InstanceInterface& vki = context.getInstanceInterface(); 1340 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 1341 1342 wd.sampleLocationsProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT; 1343 wd.sampleLocationsProperties.pNext = DE_NULL; 1344 1345 VkPhysicalDeviceProperties2 properties = 1346 { 1347 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, // VkStructureType sType; 1348 &wd.sampleLocationsProperties, // void* pNext; 1349 VkPhysicalDeviceProperties(), // VkPhysicalDeviceProperties properties; 1350 }; 1351 1352 vki.getPhysicalDeviceProperties2(physicalDevice, &properties); 1353 1354 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx) 1355 { 1356 if ((wd.sampleLocationsProperties.sampleLocationSampleCounts & params.perSubpassSamples[subpassNdx].numCoverageSamples) == 0u) 1357 TCU_THROW(NotSupportedError, "VkSampleLocationsPropertiesAMD: sample count not supported"); 1358 } 1359 } 1360 1361 // Create subpass data 1362 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx) 1363 { 1364 wd.perSubpass.push_back(SharedPtr<WorkingData::PerSubpass>(new WorkingData::PerSubpass())); 1365 createPerSubpassData(context, params, wd, subpassNdx); 1366 } 1367 1368 // Draw test geometry 1369 draw (context, params, wd); 1370 1371 // Verify images with a compute shader 1372 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx) 1373 dispatchImageCheck (context, params, wd, subpassNdx); 1374 1375 // Test checksums 1376 for (deUint32 subpassNdx = 0; subpassNdx < static_cast<deUint32>(params.perSubpassSamples.size()); ++subpassNdx) 1377 { 1378 const deUint32* const pSampleChecksumBase = static_cast<deUint32*>(wd.perSubpass[subpassNdx]->resultBufferAlloc->getHostPtr()); 1379 const bool hasDepth = isDepthFormat(params.depthStencilFormat); 1380 const bool hasStencil = isStencilFormat(params.depthStencilFormat); 1381 bool allOk = true; 1382 1383 context.getTestContext().getLog() << tcu::TestLog::Message << "Verify images in subpass " << subpassNdx << tcu::TestLog::EndMessage; 1384 1385 for (deUint32 globalSampleNdx = 0; globalSampleNdx < wd.perSubpass[subpassNdx]->numResultElements; ++globalSampleNdx) 1386 { 1387 const TestParams::SampleCount& samples = params.perSubpassSamples[subpassNdx]; 1388 const deUint32 checksum = pSampleChecksumBase[globalSampleNdx]; 1389 1390 if ((checksum & VK_IMAGE_ASPECT_COLOR_BIT) == 0u) 1391 { 1392 reportSampleError(context.getTestContext().getLog(), "color", wd.renderSize, samples.numCoverageSamples, globalSampleNdx); 1393 allOk = false; 1394 } 1395 1396 if (hasDepth && ((checksum & VK_IMAGE_ASPECT_DEPTH_BIT) == 0u)) 1397 { 1398 reportSampleError(context.getTestContext().getLog(), "depth", wd.renderSize, samples.numCoverageSamples, globalSampleNdx); 1399 allOk = false; 1400 } 1401 1402 if (hasStencil && ((checksum & VK_IMAGE_ASPECT_STENCIL_BIT) == 0u)) 1403 { 1404 reportSampleError(context.getTestContext().getLog(), "stencil", wd.renderSize, samples.numCoverageSamples, globalSampleNdx); 1405 allOk = false; 1406 } 1407 } 1408 1409 if (!allOk) 1410 return tcu::TestStatus::fail("Multisampled image has incorrect samples"); 1411 } 1412 1413 return tcu::TestStatus::pass("Pass"); 1414} 1415 1416} // VerifySamples 1417 1418namespace ShaderBuiltins 1419{ 1420 1421struct TestParams 1422{ 1423 PipelineConstructionType pipelineConstructionType; //!< The way pipeline is constructed 1424 VkSampleCountFlagBits numCoverageSamples; //!< VkPipelineMultisampleStateCreateInfo::rasterizationSamples 1425 VkSampleCountFlagBits numColorSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples 1426 VkSampleCountFlagBits numDepthStencilSamples; //!< VkAttachmentDescription::samples and VkImageCreateInfo::samples 1427 VkFormat colorFormat; //!< Color attachment format 1428 VkFormat depthStencilFormat; //!< D/S attachment format. Will test both aspects if it's a mixed format 1429}; 1430 1431struct WorkingData 1432{ 1433 UVec2 renderSize; //!< Size of the framebuffer 1434 deUint32 numVertices; //!< Number of vertices defined in the vertex buffer 1435 Move<VkBuffer> vertexBuffer; 1436 MovePtr<Allocation> vertexBufferAlloc; 1437 Move<VkImage> colorImage; //!< Color image 1438 Move<VkImageView> colorImageView; //!< Color attachment 1439 MovePtr<Allocation> colorImageAlloc; 1440 Move<VkImage> depthStencilImage; //!< Depth stencil image 1441 Move<VkImageView> depthStencilImageView; //!< Depth stencil attachment 1442 Move<VkImageView> depthOnlyImageView; //!< Depth aspect for shader read 1443 Move<VkImageView> stencilOnlyImageView; //!< Stencil aspect for shader read 1444 MovePtr<Allocation> depthStencilImageAlloc; 1445 Move<VkImage> resolveImage; //!< Resolve image 1446 Move<VkImageView> resolveImageView; //!< Resolve attachment 1447 MovePtr<Allocation> resolveImageAlloc; 1448 Move<VkBuffer> colorBuffer; //!< Buffer used to copy resolve output 1449 MovePtr<Allocation> colorBufferAlloc; 1450 VkDeviceSize colorBufferSize; 1451 1452 WorkingData (void) 1453 : numVertices () 1454 , colorBufferSize (0) 1455 { 1456 } 1457}; 1458 1459void initPrograms (SourceCollections& programCollection, const TestParams params) 1460{ 1461 // Vertex shader - no vertex data 1462 { 1463 std::ostringstream src; 1464 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1465 << "\n" 1466 << "out gl_PerVertex {\n" 1467 << " vec4 gl_Position;\n" 1468 << "};\n" 1469 << "\n" 1470 << "void main(void)\n" 1471 << "{\n" 1472 // Specify an oversized triangle covering the whole viewport. 1473 << " switch (gl_VertexIndex)\n" 1474 << " {\n" 1475 << " case 0:\n" 1476 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 1477 << " break;\n" 1478 << " case 1:\n" 1479 << " gl_Position = vec4(-1.0, 3.0, 0.0, 1.0);\n" 1480 << " break;\n" 1481 << " case 2:\n" 1482 << " gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n" 1483 << " break;\n" 1484 << " }\n" 1485 << "}\n"; 1486 1487 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 1488 } 1489 1490 // Fragment shader 1491 { 1492 std::ostringstream src; 1493 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 1494 << "\n" 1495 << "layout(location = 0) out vec4 o_color;\n" 1496 << "\n" 1497 << "void main(void)\n" 1498 << "{\n" 1499 << " vec4 col = vec4(0.0, 0.0, 0.0, 1.0);\n" 1500 << "\n"; 1501 1502 if (params.numColorSamples == VK_SAMPLE_COUNT_1_BIT) 1503 { 1504 const deUint32 expectedMask = ((1u << static_cast<deUint32>(params.numCoverageSamples)) - 1u); 1505 1506 // Expect all covered samples to be lit, the rest is zero 1507 src << " if (gl_SampleMaskIn[0] == " << expectedMask << ")\n" 1508 << " col.g = 1.0;\n" 1509 << " else\n" 1510 << " col.r = 1.0;\n"; 1511 } 1512 else 1513 { 1514 // Expect only a matching sample to be lit 1515 src << " if (gl_SampleMaskIn[0] == (1 << gl_SampleID))\n" 1516 << " col.g = 1.0;\n" 1517 << " else\n" 1518 << " col.r = 1.0;\n" 1519 << "\n" 1520 << " if (gl_SampleID >= " << static_cast<deUint32>(params.numColorSamples) << ") // number of color samples, should not happen\n" 1521 << " col.b = 1.0;\n"; 1522 } 1523 1524 src << "\n" 1525 << " o_color = col;\n" 1526 << "}\n"; 1527 1528 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 1529 } 1530} 1531 1532//! A simple color, depth/stencil draw. Single subpass, no vertex input 1533void drawResolve (Context& context, const TestParams& params, WorkingData& wd) 1534{ 1535 const InstanceInterface& vki = context.getInstanceInterface(); 1536 const DeviceInterface& vk = context.getDeviceInterface(); 1537 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 1538 const VkDevice device = context.getDevice(); 1539 const bool needResolve = (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT); 1540 1541 RenderPassWrapper renderPass; 1542 1543 // Create a render pass and a framebuffer 1544 { 1545 std::vector<VkImage> images; 1546 std::vector<VkImageView> attachments; 1547 std::vector<VkAttachmentDescription> attachmentDescriptions; 1548 1549 images.push_back(*wd.colorImage); 1550 images.push_back(*wd.depthStencilImage); 1551 attachments.push_back(*wd.colorImageView); 1552 attachments.push_back(*wd.depthStencilImageView); 1553 1554 attachmentDescriptions.push_back(makeAttachmentDescription( 1555 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 1556 params.colorFormat, // VkFormat format; 1557 params.numColorSamples, // VkSampleCountFlagBits samples; 1558 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 1559 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 1560 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 1561 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 1562 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1563 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout; 1564 )); 1565 1566 attachmentDescriptions.push_back(makeAttachmentDescription( 1567 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 1568 params.depthStencilFormat, // VkFormat format; 1569 params.numDepthStencilSamples, // VkSampleCountFlagBits samples; 1570 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 1571 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 1572 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp; 1573 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp; 1574 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1575 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; 1576 )); 1577 1578 if (needResolve) 1579 { 1580 images.push_back(*wd.resolveImage); 1581 attachments.push_back(*wd.resolveImageView); 1582 1583 attachmentDescriptions.push_back(makeAttachmentDescription( 1584 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 1585 params.colorFormat, // VkFormat format; 1586 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 1587 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; 1588 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 1589 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 1590 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 1591 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 1592 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL // VkImageLayout finalLayout; 1593 )); 1594 } 1595 1596 const VkAttachmentReference colorRef = makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); 1597 const VkAttachmentReference depthStencilRef = makeAttachmentReference(1u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); 1598 const VkAttachmentReference resolveRef = makeAttachmentReference(2u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); 1599 1600 const VkSubpassDescription subpassDescription = 1601 { 1602 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 1603 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 1604 0u, // uint32_t inputAttachmentCount; 1605 DE_NULL, // const VkAttachmentReference* pInputAttachments; 1606 1u, // uint32_t colorAttachmentCount; 1607 &colorRef, // const VkAttachmentReference* pColorAttachments; 1608 (needResolve ? &resolveRef : DE_NULL), // const VkAttachmentReference* pResolveAttachments; 1609 &depthStencilRef, // const VkAttachmentReference* pDepthStencilAttachment; 1610 0u, // uint32_t preserveAttachmentCount; 1611 DE_NULL, // const uint32_t* pPreserveAttachments; 1612 }; 1613 1614 // Assume there are no dependencies between subpasses 1615 VkRenderPassCreateInfo renderPassInfo = 1616 { 1617 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 1618 DE_NULL, // const void* pNext; 1619 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 1620 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount; 1621 dataOrNullPtr(attachmentDescriptions), // const VkAttachmentDescription* pAttachments; 1622 1u, // deUint32 subpassCount; 1623 &subpassDescription, // const VkSubpassDescription* pSubpasses; 1624 0u, // deUint32 dependencyCount; 1625 DE_NULL, // const VkSubpassDependency* pDependencies; 1626 }; 1627 1628 renderPass = RenderPassWrapper(params.pipelineConstructionType, vk, device, &renderPassInfo); 1629 renderPass.createFramebuffer(vk, device, static_cast<deUint32>(attachments.size()), dataOrNullPtr(images), dataOrNullPtr(attachments), wd.renderSize.x(), wd.renderSize.y()); 1630 } 1631 1632 const ShaderWrapper vertexModule (ShaderWrapper (vk, device, context.getBinaryCollection().get("vert"), 0u)); 1633 const ShaderWrapper fragmentModule (ShaderWrapper (vk, device, context.getBinaryCollection().get("frag"), 0u)); 1634 const PipelineLayoutWrapper pipelineLayout (params.pipelineConstructionType, vk, device); 1635 const bool useVertexInput = false; 1636 const bool sampleShading = (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT); 1637 const deUint32 subpassNdx = 0u; 1638 GraphicsPipelineWrapper pipeline (vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType); 1639 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex())); 1640 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1641 1642 preparePipelineWrapper(pipeline, pipelineLayout, *renderPass, vertexModule, fragmentModule, useVertexInput, 1643 subpassNdx, wd.renderSize, getImageAspectFlags(params.depthStencilFormat), 1644 params.numCoverageSamples, sampleShading, false); 1645 1646 beginCommandBuffer(vk, *cmdBuffer); 1647 1648 { 1649 std::vector<VkClearValue> clearValues; 1650 clearValues.push_back(makeClearValueColorF32(0.0f, 0.0f, 0.0f, 1.0f)); 1651 clearValues.push_back(makeClearValueDepthStencil(1.0f, 0u)); 1652 1653 const VkRect2D renderArea = 1654 { 1655 { 0u, 0u }, 1656 { wd.renderSize.x(), wd.renderSize.y() } 1657 }; 1658 1659 renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<deUint32>(clearValues.size()), dataOrNullPtr(clearValues)); 1660 } 1661 1662 pipeline.bind(*cmdBuffer); 1663 vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u); 1664 1665 renderPass.end(vk, *cmdBuffer); 1666 1667 if (needResolve) 1668 recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.resolveImage, *wd.colorBuffer); 1669 else 1670 recordCopyOutputImageToBuffer(vk, *cmdBuffer, wd.renderSize, *wd.colorImage, *wd.colorBuffer); 1671 1672 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 1673 submitCommandsAndWait(vk, device, context.getUniversalQueue(), *cmdBuffer); 1674} 1675 1676void checkRequirements (Context& context, TestParams params) 1677{ 1678 context.requireDeviceFunctionality("VK_AMD_mixed_attachment_samples"); 1679 1680 checkSampleRequirements(context, params.numColorSamples, params.numDepthStencilSamples, false /* require standard sample locations */); 1681 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), params.pipelineConstructionType); 1682} 1683 1684//! Verify the values of shader builtins 1685tcu::TestStatus test (Context& context, const TestParams params) 1686{ 1687 WorkingData wd; 1688 const DeviceInterface& vk = context.getDeviceInterface(); 1689 const VkDevice device = context.getDevice(); 1690 MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))); 1691 1692 wd.renderSize = UVec2(16, 16); 1693 1694 // Create images and a color buffer 1695 { 1696 1697 const VkImageUsageFlags colorImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; 1698 const VkImageUsageFlags depthStencilImageUsageFlags = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; 1699 1700 checkImageRequirements (context, 1701 params.colorFormat, 1702 VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT, 1703 colorImageUsageFlags, 1704 params.numColorSamples); 1705 1706 wd.colorImage = makeImage(vk, device, params.colorFormat, wd.renderSize, params.numColorSamples, colorImageUsageFlags); 1707 wd.colorImageAlloc = bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any); 1708 wd.colorImageView = makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)); 1709 1710 if (params.numColorSamples != VK_SAMPLE_COUNT_1_BIT) 1711 { 1712 wd.resolveImage = makeImage(vk, device, params.colorFormat, wd.renderSize, VK_SAMPLE_COUNT_1_BIT, colorImageUsageFlags); 1713 wd.resolveImageAlloc = bindImage(vk, device, *allocator, *wd.resolveImage, MemoryRequirement::Any); 1714 wd.resolveImageView = makeImageView(vk, device, *wd.resolveImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)); 1715 } 1716 1717 // Resolve result 1718 wd.colorBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat)) * wd.renderSize.x() * wd.renderSize.y()); 1719 wd.colorBuffer = makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT); 1720 wd.colorBufferAlloc = bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible); 1721 1722 deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize)); 1723 flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE); 1724 1725 checkImageRequirements (context, 1726 params.depthStencilFormat, 1727 VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, 1728 depthStencilImageUsageFlags, 1729 params.numDepthStencilSamples); 1730 1731 wd.depthStencilImage = makeImage(vk, device, params.depthStencilFormat, wd.renderSize, params.numDepthStencilSamples, depthStencilImageUsageFlags); 1732 wd.depthStencilImageAlloc = bindImage(vk, device, *allocator, *wd.depthStencilImage, MemoryRequirement::Any); 1733 wd.depthStencilImageView = makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(getImageAspectFlags(params.depthStencilFormat), 0u, 1u, 0u, 1u)); 1734 1735 if (isDepthFormat(params.depthStencilFormat)) 1736 wd.depthOnlyImageView = makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u)); 1737 1738 if (isStencilFormat(params.depthStencilFormat)) 1739 wd.stencilOnlyImageView = makeImageView(vk, device, *wd.depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, params.depthStencilFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u)); 1740 } 1741 1742 // Draw, resolve, and copy to color buffer (see the fragment shader for details) 1743 drawResolve(context, params, wd); 1744 1745 // Verify resolved image 1746 { 1747 const tcu::ConstPixelBufferAccess image (tcu::ConstPixelBufferAccess(mapVkFormat(params.colorFormat), tcu::IVec3(wd.renderSize.x(), wd.renderSize.y(), 1),wd.colorBufferAlloc->getHostPtr())); 1748 1749 if (compareGreenImage(context.getTestContext().getLog(), "resolve0", "Resolved test image", image)) 1750 return tcu::TestStatus::pass("Pass"); 1751 else 1752 return tcu::TestStatus::fail("Some samples were incorrect"); 1753 } 1754} 1755 1756} // ShaderBuiltins 1757 1758std::string getSampleCountGroupName(const VkSampleCountFlagBits coverageCount, 1759 const VkSampleCountFlagBits colorCount, 1760 const VkSampleCountFlagBits depthStencilCount) 1761{ 1762 std::ostringstream str; 1763 str << "coverage_" << static_cast<deUint32>(coverageCount) 1764 << "_color_" << static_cast<deUint32>(colorCount) 1765 << "_depth_stencil_" << static_cast<deUint32>(depthStencilCount); 1766 return str.str(); 1767} 1768 1769std::string getFormatShortString (const VkFormat format) 1770{ 1771 std::string s(de::toLower(getFormatName(format))); 1772 return s.substr(10); 1773} 1774 1775std::string getFormatCaseName (const VkFormat colorFormat, 1776 const VkFormat depthStencilFormat) 1777{ 1778 std::ostringstream str; 1779 str << getFormatShortString(colorFormat) << "_" << getFormatShortString(depthStencilFormat); 1780 return str.str(); 1781} 1782 1783void createMixedAttachmentSamplesTestsInGroup (tcu::TestCaseGroup* rootGroup, PipelineConstructionType pipelineConstructionType, bool useFragmentShadingRate) 1784{ 1785 const VkFormat colorFormatRange[] = 1786 { 1787 VK_FORMAT_R8G8B8A8_UNORM, 1788 // If you add more, make sure it is handled in the test/shader 1789 }; 1790 1791 const VkFormat depthStencilFormatRange[] = 1792 { 1793 VK_FORMAT_D16_UNORM, 1794 VK_FORMAT_X8_D24_UNORM_PACK32, 1795 VK_FORMAT_D32_SFLOAT, 1796 VK_FORMAT_S8_UINT, 1797 VK_FORMAT_D16_UNORM_S8_UINT, 1798 VK_FORMAT_D24_UNORM_S8_UINT, 1799 VK_FORMAT_D32_SFLOAT_S8_UINT, 1800 }; 1801 1802 // Minimal set of formats to cover depth and stencil 1803 const VkFormat depthStencilReducedFormatRange[] = 1804 { 1805 VK_FORMAT_D16_UNORM, //!< Must be supported 1806 VK_FORMAT_D24_UNORM_S8_UINT, //!< Either this, or the next one must be supported 1807 VK_FORMAT_D32_SFLOAT_S8_UINT, 1808 }; 1809 1810 struct SampleCase 1811 { 1812 VkSampleCountFlagBits colorSamples; 1813 VkSampleCountFlagBits depthStencilSamples; 1814 }; 1815 1816 // Currently supported EQAA cases 1817 static const SampleCase singlePassCases[] = 1818 { 1819 // Less color than depth/stencil 1820 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT }, 1821 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT }, 1822 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT }, 1823 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_16_BIT }, 1824 { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT }, 1825 { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT }, 1826 { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_16_BIT }, 1827 { VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT }, 1828 { VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_16_BIT }, 1829 { VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT }, 1830 }; 1831 1832 // Multi-subpass cases 1833 1834 static const SampleCase caseSubpassIncreaseColor_1[] = 1835 { 1836 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT }, 1837 { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT }, 1838 }; 1839 static const SampleCase caseSubpassIncreaseColor_2[] = 1840 { 1841 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT }, 1842 { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT }, 1843 { VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT }, 1844 }; 1845 static const SampleCase caseSubpassDecreaseColor_1[] = 1846 { 1847 { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT }, 1848 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_4_BIT }, 1849 }; 1850 static const SampleCase caseSubpassDecreaseColor_2[] = 1851 { 1852 { VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT }, 1853 { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_8_BIT }, 1854 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_8_BIT }, 1855 }; 1856 static const SampleCase caseSubpassIncreaseCoverage_1[] = 1857 { 1858 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT }, 1859 { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT }, 1860 }; 1861 static const SampleCase caseSubpassIncreaseCoverage_2[] = 1862 { 1863 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT }, 1864 { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT }, 1865 { VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT }, 1866 }; 1867 static const SampleCase caseSubpassDecreaseCoverage_1[] = 1868 { 1869 { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT }, 1870 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT }, 1871 }; 1872 static const SampleCase caseSubpassDecreaseCoverage_2[] = 1873 { 1874 { VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT }, 1875 { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT }, 1876 { VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT }, 1877 }; 1878 1879 static const struct 1880 { 1881 const char* const caseName; 1882 const deUint32 numSampleCases; 1883 const SampleCase* pSampleCase; 1884 } subpassCases[] = 1885 { 1886 { "multi_subpass_decrease_color_4", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_1), caseSubpassDecreaseColor_1 }, 1887 { "multi_subpass_decrease_color_8", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseColor_2), caseSubpassDecreaseColor_2 }, 1888 { "multi_subpass_decrease_coverage_4", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_1), caseSubpassDecreaseCoverage_1 }, 1889 { "multi_subpass_decrease_coverage_8", DE_LENGTH_OF_ARRAY(caseSubpassDecreaseCoverage_2), caseSubpassDecreaseCoverage_2 }, 1890 { "multi_subpass_increase_color_4", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_1), caseSubpassIncreaseColor_1 }, 1891 { "multi_subpass_increase_color_8", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseColor_2), caseSubpassIncreaseColor_2 }, 1892 { "multi_subpass_increase_coverage_4", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_1), caseSubpassIncreaseCoverage_1 }, 1893 { "multi_subpass_increase_coverage_8", DE_LENGTH_OF_ARRAY(caseSubpassIncreaseCoverage_2), caseSubpassIncreaseCoverage_2 }, 1894 }; 1895 1896 // Test 1: Per-sample expected value check 1897 { 1898 MovePtr<tcu::TestCaseGroup> standardLocationsGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_standard_locations")); 1899 MovePtr<tcu::TestCaseGroup> programmableLocationsGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), "verify_programmable_locations")); 1900 1901 tcu::TestCaseGroup* locationsGroups[2] = 1902 { 1903 standardLocationsGroup.get(), 1904 programmableLocationsGroup.get() 1905 }; 1906 1907 for (deUint32 groupNdx = 0u; groupNdx < DE_LENGTH_OF_ARRAY(locationsGroups); ++groupNdx) 1908 { 1909 // Single subpass cases 1910 for (deUint32 caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx) 1911 { 1912 VerifySamples::TestParams::SampleCount samples; 1913 samples.numColorSamples = singlePassCases[caseNdx].colorSamples; 1914 samples.numDepthStencilSamples = singlePassCases[caseNdx].depthStencilSamples; 1915 samples.numCoverageSamples = de::max(samples.numColorSamples, samples.numDepthStencilSamples); 1916 1917 VerifySamples::TestParams params; 1918 params.pipelineConstructionType = pipelineConstructionType; 1919 params.perSubpassSamples.push_back(samples); 1920 params.useProgrammableSampleLocations = (locationsGroups[groupNdx] == programmableLocationsGroup.get()); 1921 params.useFragmentShadingRate = useFragmentShadingRate; 1922 1923 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(new tcu::TestCaseGroup( 1924 rootGroup->getTestContext(), getSampleCountGroupName(samples.numCoverageSamples, samples.numColorSamples, samples.numDepthStencilSamples).c_str(), "")); 1925 1926 for (const VkFormat *pDepthStencilFormat = depthStencilFormatRange; pDepthStencilFormat != DE_ARRAY_END(depthStencilFormatRange); ++pDepthStencilFormat) 1927 for (const VkFormat *pColorFormat = colorFormatRange; pColorFormat != DE_ARRAY_END(colorFormatRange); ++pColorFormat) 1928 { 1929 params.colorFormat = *pColorFormat; 1930 params.depthStencilFormat = *pDepthStencilFormat; 1931 1932 addFunctionCaseWithPrograms( 1933 sampleCaseGroup.get(), 1934 getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(), 1935 VerifySamples::checkRequirements, 1936 VerifySamples::initPrograms, 1937 VerifySamples::test, params); 1938 } 1939 1940 locationsGroups[groupNdx]->addChild(sampleCaseGroup.release()); 1941 } 1942 1943 // Multi subpass cases 1944 for (deUint32 caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(subpassCases); ++caseNdx) 1945 { 1946 VerifySamples::TestParams params; 1947 params.pipelineConstructionType = pipelineConstructionType; 1948 params.useProgrammableSampleLocations = (locationsGroups[groupNdx] == programmableLocationsGroup.get()); 1949 params.useFragmentShadingRate = useFragmentShadingRate; 1950 1951 for (deUint32 subpassNdx = 0; subpassNdx < subpassCases[caseNdx].numSampleCases; ++subpassNdx) 1952 { 1953 VerifySamples::TestParams::SampleCount samples; 1954 samples.numColorSamples = subpassCases[caseNdx].pSampleCase[subpassNdx].colorSamples; 1955 samples.numDepthStencilSamples = subpassCases[caseNdx].pSampleCase[subpassNdx].depthStencilSamples; 1956 samples.numCoverageSamples = de::max(samples.numColorSamples, samples.numDepthStencilSamples); 1957 params.perSubpassSamples.push_back(samples); 1958 } 1959 1960 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(new tcu::TestCaseGroup(rootGroup->getTestContext(), subpassCases[caseNdx].caseName)); 1961 1962 for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange; pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat) 1963 for (const VkFormat *pColorFormat = colorFormatRange; pColorFormat != DE_ARRAY_END(colorFormatRange); ++pColorFormat) 1964 { 1965 params.colorFormat = *pColorFormat; 1966 params.depthStencilFormat = *pDepthStencilFormat; 1967 1968 addFunctionCaseWithPrograms( 1969 sampleCaseGroup.get(), 1970 getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(), 1971 VerifySamples::checkRequirements, 1972 VerifySamples::initPrograms, 1973 VerifySamples::test, params); 1974 } 1975 1976 locationsGroups[groupNdx]->addChild(sampleCaseGroup.release()); 1977 } 1978 } 1979 1980 rootGroup->addChild(standardLocationsGroup.release()); 1981 rootGroup->addChild(programmableLocationsGroup.release()); 1982 } 1983 1984 // Test 2: Shader built-ins check 1985 if (!useFragmentShadingRate) 1986 { 1987 MovePtr<tcu::TestCaseGroup> builtinsGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), "shader_builtins")); 1988 1989 for (deUint32 caseNdx = 0u; caseNdx < DE_LENGTH_OF_ARRAY(singlePassCases); ++caseNdx) 1990 { 1991 ShaderBuiltins::TestParams params; 1992 params.pipelineConstructionType = pipelineConstructionType; 1993 params.numColorSamples = singlePassCases[caseNdx].colorSamples; 1994 params.numDepthStencilSamples = singlePassCases[caseNdx].depthStencilSamples; 1995 params.numCoverageSamples = de::max(params.numColorSamples, params.numDepthStencilSamples); 1996 1997 MovePtr<tcu::TestCaseGroup> sampleCaseGroup(new tcu::TestCaseGroup( 1998 rootGroup->getTestContext(), getSampleCountGroupName(params.numCoverageSamples, params.numColorSamples, params.numDepthStencilSamples).c_str(), "")); 1999 2000 for (const VkFormat *pDepthStencilFormat = depthStencilReducedFormatRange; pDepthStencilFormat != DE_ARRAY_END(depthStencilReducedFormatRange); ++pDepthStencilFormat) 2001 for (const VkFormat *pColorFormat = colorFormatRange; pColorFormat != DE_ARRAY_END(colorFormatRange); ++pColorFormat) 2002 { 2003 params.colorFormat = *pColorFormat; 2004 params.depthStencilFormat = *pDepthStencilFormat; 2005 2006 addFunctionCaseWithPrograms( 2007 sampleCaseGroup.get(), 2008 getFormatCaseName(params.colorFormat, params.depthStencilFormat).c_str(), 2009 ShaderBuiltins::checkRequirements, 2010 ShaderBuiltins::initPrograms, 2011 ShaderBuiltins::test, 2012 params); 2013 } 2014 2015 builtinsGroup->addChild(sampleCaseGroup.release()); 2016 } 2017 2018 rootGroup->addChild(builtinsGroup.release()); 2019 } 2020} 2021 2022} // anonymous ns 2023 2024tcu::TestCaseGroup* createMultisampleMixedAttachmentSamplesTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, bool useFragmentShadingRate) 2025{ 2026 // Test a graphics pipeline with varying sample count per color and depth/stencil attachments 2027 return createTestGroup(testCtx, "mixed_attachment_samples", createMixedAttachmentSamplesTestsInGroup, pipelineConstructionType, useFragmentShadingRate); 2028} 2029 2030} // pipeline 2031} // vkt 2032