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_shader_fragment_mask 25 *//*--------------------------------------------------------------------*/ 26 27#include "vktPipelineMultisampleShaderFragmentMaskTests.hpp" 28#include "vktPipelineMakeUtil.hpp" 29#include "vktTestCase.hpp" 30#include "vktTestCaseUtil.hpp" 31#include "vktTestGroupUtil.hpp" 32#include "vktCustomInstancesDevices.hpp" 33#include "tcuCommandLine.hpp" 34 35#include "vkCmdUtil.hpp" 36#include "vkObjUtil.hpp" 37#include "vkPlatform.hpp" 38#include "vkMemUtil.hpp" 39#include "vkQueryUtil.hpp" 40#include "vkTypeUtil.hpp" 41#include "vkRefUtil.hpp" 42#include "vkBuilderUtil.hpp" 43#include "vkPrograms.hpp" 44#include "vkImageUtil.hpp" 45 46#include "deUniquePtr.hpp" 47#include "deSharedPtr.hpp" 48#include "deRandom.hpp" 49 50#include "tcuVector.hpp" 51#include "tcuTestLog.hpp" 52#include "tcuImageCompare.hpp" 53#include "tcuTestLog.hpp" 54#include "tcuTextureUtil.hpp" 55 56#include <string> 57#include <vector> 58#include <set> 59 60namespace vkt 61{ 62namespace pipeline 63{ 64namespace 65{ 66using namespace vk; 67using de::MovePtr; 68using de::SharedPtr; 69using tcu::UVec2; 70using tcu::UVec4; 71using tcu::Vec2; 72using tcu::Vec4; 73 74typedef SharedPtr<Unique<VkImageView> > ImageViewSp; 75 76struct PositionColor 77{ 78 tcu::Vec4 position; 79 VkClearColorValue color; 80 81 PositionColor (const tcu::Vec4& pos, const tcu::UVec4& col) : position(pos) 82 { 83 deMemcpy(color.uint32, col.getPtr(), sizeof(color.uint32)); 84 } 85 86 PositionColor (const tcu::Vec4& pos, const tcu::Vec4& col) : position(pos) 87 { 88 deMemcpy(color.float32, col.getPtr(), sizeof(color.float32)); 89 } 90 91 PositionColor (const PositionColor& rhs) 92 : position (rhs.position) 93 , color (rhs.color) 94 { 95 } 96}; 97 98//! Make a (unused) sampler. 99Move<VkSampler> makeSampler (const DeviceInterface& vk, const VkDevice device) 100{ 101 const VkSamplerCreateInfo samplerParams = 102 { 103 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType; 104 DE_NULL, // const void* pNext; 105 (VkSamplerCreateFlags)0, // VkSamplerCreateFlags flags; 106 VK_FILTER_NEAREST, // VkFilter magFilter; 107 VK_FILTER_NEAREST, // VkFilter minFilter; 108 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode; 109 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU; 110 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV; 111 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW; 112 0.0f, // float mipLodBias; 113 VK_FALSE, // VkBool32 anisotropyEnable; 114 1.0f, // float maxAnisotropy; 115 VK_FALSE, // VkBool32 compareEnable; 116 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp; 117 0.0f, // float minLod; 118 0.0f, // float maxLod; 119 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor; 120 VK_FALSE, // VkBool32 unnormalizedCoordinates; 121 }; 122 return createSampler(vk, device, &samplerParams); 123} 124 125Move<VkImage> makeImage (const DeviceInterface& vk, 126 const VkDevice device, 127 const VkFormat format, 128 const UVec2& size, 129 const deUint32 layers, 130 const VkSampleCountFlagBits samples, 131 const VkImageUsageFlags usage) 132{ 133 const VkImageCreateInfo imageParams = 134 { 135 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 136 DE_NULL, // const void* pNext; 137 (VkImageCreateFlags)0, // VkImageCreateFlags flags; 138 VK_IMAGE_TYPE_2D, // VkImageType imageType; 139 format, // VkFormat format; 140 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent; 141 1u, // deUint32 mipLevels; 142 layers, // deUint32 arrayLayers; 143 samples, // VkSampleCountFlagBits samples; 144 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 145 usage, // VkImageUsageFlags usage; 146 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 147 0u, // deUint32 queueFamilyIndexCount; 148 DE_NULL, // const deUint32* pQueueFamilyIndices; 149 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 150 }; 151 return createImage(vk, device, &imageParams); 152} 153 154std::vector<PositionColor> genShapes (const VkFormat colorFormat) 155{ 156 std::vector<PositionColor> vertices; 157 158 if (colorFormat == VK_FORMAT_R8G8B8A8_UNORM) 159 { 160 vertices.push_back(PositionColor(Vec4( 0.0f, -0.75f, 0.0f, 1.0f), Vec4(0.5f, 0.5f, 0.5f, 1.0f))); 161 vertices.push_back(PositionColor(Vec4(-0.75f, 0.75f, 0.0f, 1.0f), Vec4(1.0f, 0.5f, 0.5f, 1.0f))); 162 vertices.push_back(PositionColor(Vec4( 0.75f, 0.65f, 0.0f, 1.0f), Vec4(0.0f, 0.5f, 1.0f, 1.0f))); 163 } 164 else 165 { 166 vertices.push_back(PositionColor(Vec4( 0.0f, -0.75f, 0.0f, 1.0f), UVec4(0xabcdu, 0u, 0u, 0u))); 167 vertices.push_back(PositionColor(Vec4(-0.75f, 0.75f, 0.0f, 1.0f), UVec4(0xbcdeu, 0u, 0u, 0u))); 168 vertices.push_back(PositionColor(Vec4( 0.75f, 0.65f, 0.0f, 1.0f), UVec4(0xcdefu, 0u, 0u, 0u))); 169 } 170 171 return vertices; 172} 173 174//! Map color image format to a convenient format used in vertex attributes 175VkFormat getVertexInputColorFormat (const VkFormat colorImageFormat) 176{ 177 switch (tcu::getTextureChannelClass(mapVkFormat(colorImageFormat).type)) 178 { 179 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 180 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 181 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 182 return VK_FORMAT_R32G32B32A32_SFLOAT; 183 184 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 185 return VK_FORMAT_R32G32B32A32_SINT; 186 187 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 188 return VK_FORMAT_R32G32B32A32_UINT; 189 190 default: 191 DE_ASSERT(0); 192 return VK_FORMAT_UNDEFINED; 193 } 194} 195 196enum SampleSource 197{ 198 SAMPLE_SOURCE_IMAGE, //!< texel fetch from an image 199 SAMPLE_SOURCE_SUBPASS_INPUT, //!< texel fetch from an input attachment 200}; 201 202// Class to wrap a singleton device for use in fragment mask tests, 203// which require the VK_AMD_shader_fragment extension. 204class SingletonDevice 205{ 206 SingletonDevice(Context& context) 207 : m_context(context) 208 , m_logicalDevice() 209 { 210 const float queuePriority = 1.0; 211 const VkDeviceQueueCreateInfo queues[] = 212 { 213 { 214 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 215 DE_NULL, 216 (VkDeviceQueueCreateFlags)0, 217 m_context.getUniversalQueueFamilyIndex(), 218 1u, // queueCount 219 &queuePriority, // pQueuePriorities 220 } 221 }; 222 223 const auto& vkp = m_context.getPlatformInterface(); 224 const auto& vki = m_context.getInstanceInterface(); 225 const auto instance = m_context.getInstance(); 226 const auto physicalDevice = m_context.getPhysicalDevice(); 227 std::vector<const char*> creationExtensions = m_context.getDeviceCreationExtensions(); 228 229 VkPhysicalDeviceFeatures2 features2 = initVulkanStructure(); 230 VkPhysicalDeviceDescriptorBufferFeaturesEXT descriptorBufferFeatures = initVulkanStructure(); 231 VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT graphicsPipelineLibraryFeatures = initVulkanStructure(); 232 VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamicRenderingFeatures = initVulkanStructure(); 233 VkPhysicalDeviceShaderObjectFeaturesEXT shaderObjectFeatures = initVulkanStructure(&dynamicRenderingFeatures); 234 235 m_context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2"); 236 const auto addFeatures = makeStructChainAdder(&features2); 237 238 if (m_context.isDeviceFunctionalitySupported("VK_EXT_descriptor_buffer")) 239 addFeatures(&descriptorBufferFeatures); 240 241 if (m_context.isDeviceFunctionalitySupported("VK_EXT_graphics_pipeline_library")) 242 addFeatures(&graphicsPipelineLibraryFeatures); 243 244 if (m_context.isDeviceFunctionalitySupported("VK_EXT_shader_object")) 245 addFeatures(&shaderObjectFeatures); 246 247 vki.getPhysicalDeviceFeatures2(physicalDevice, &features2); 248 descriptorBufferFeatures.descriptorBuffer = VK_FALSE; 249 features2.features.robustBufferAccess = VK_FALSE; // Disable robustness features. 250 creationExtensions.push_back("VK_AMD_shader_fragment_mask"); 251 252 VkDeviceCreateInfo createInfo = initVulkanStructure(&features2); 253 createInfo.flags = 0u; 254 createInfo.queueCreateInfoCount = de::arrayLength(queues); 255 createInfo.pQueueCreateInfos = queues; 256 createInfo.enabledLayerCount = 0u; 257 createInfo.ppEnabledLayerNames = nullptr; 258 createInfo.enabledExtensionCount = de::sizeU32(creationExtensions); 259 createInfo.ppEnabledExtensionNames = de::dataOrNull(creationExtensions); 260 createInfo.pEnabledFeatures = nullptr; 261 262 m_logicalDevice = createCustomDevice( 263 m_context.getTestContext().getCommandLine().isValidationEnabled(), 264 vkp, 265 instance, 266 vki, 267 physicalDevice, 268 &createInfo, 269 nullptr); 270 271 m_deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(vkp, instance, *m_logicalDevice, m_context.getUsedApiVersion())); 272 } 273 274public: 275 ~SingletonDevice() 276 { 277 } 278 279 static VkDevice getDevice(Context& context) 280 { 281 if (!m_singletonDevice) 282 m_singletonDevice = SharedPtr<SingletonDevice>(new SingletonDevice(context)); 283 DE_ASSERT(m_singletonDevice); 284 return m_singletonDevice->m_logicalDevice.get(); 285 } 286 287 static VkQueue getUniversalQueue(Context& context) 288 { 289 return getDeviceQueue(getDeviceInterface(context), getDevice(context), context.getUniversalQueueFamilyIndex(), 0); 290 } 291 292 static const DeviceInterface& getDeviceInterface(Context& context) 293 { 294 if (!m_singletonDevice) 295 m_singletonDevice = SharedPtr<SingletonDevice>(new SingletonDevice(context)); 296 DE_ASSERT(m_singletonDevice); 297 return *(m_singletonDevice->m_deviceDriver.get()); 298 } 299 300 static void destroy() 301 { 302 m_singletonDevice.clear(); 303 } 304 305private: 306 const Context& m_context; 307 Move<vk::VkDevice> m_logicalDevice; 308 de::MovePtr<vk::DeviceDriver> m_deviceDriver; 309 static SharedPtr<SingletonDevice> m_singletonDevice; 310}; 311 312SharedPtr<SingletonDevice> SingletonDevice::m_singletonDevice; 313 314//! The parameters that define a test case 315struct TestParams 316{ 317 PipelineConstructionType pipelineConstructionType; 318 UVec2 renderSize; 319 deUint32 numLayers; //!< 1 or N for layered image 320 SampleSource sampleSource; //!< source of texel fetch 321 VkSampleCountFlagBits numColorSamples; 322 VkFormat colorFormat; //!< Color attachment format 323 324 TestParams (void) 325 : numLayers () 326 , sampleSource (SAMPLE_SOURCE_IMAGE) 327 , numColorSamples () 328 , colorFormat () 329 { 330 } 331}; 332 333void checkRequirements (Context& context, TestParams params) 334{ 335 const auto& vki = context.getInstanceInterface(); 336 const auto physicalDevice = context.getPhysicalDevice(); 337 338 const auto& supportedExtensions = enumerateCachedDeviceExtensionProperties(vki, physicalDevice); 339 if (!isExtensionStructSupported(supportedExtensions, RequiredExtension("VK_AMD_shader_fragment_mask"))) 340 TCU_THROW(NotSupportedError, "VK_AMD_shader_fragment_mask not supported"); 341 342 const auto& limits = context.getDeviceProperties().limits; 343 344 if ((limits.framebufferColorSampleCounts & params.numColorSamples) == 0u) 345 TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported"); 346 347 if ((isIntFormat(params.colorFormat) || isUintFormat(params.colorFormat))) 348 { 349 if ((limits.sampledImageIntegerSampleCounts & params.numColorSamples) == 0u) 350 TCU_THROW(NotSupportedError, "sampledImageIntegerSampleCounts: sample count not supported"); 351 } 352 else 353 { 354 if ((limits.sampledImageColorSampleCounts & params.numColorSamples) == 0u) 355 TCU_THROW(NotSupportedError, "sampledImageColorSampleCounts: sample count not supported"); 356 } 357 358 // In the subpass input case we have to store fetch results into a buffer for subsequent verification in a compute shader. 359 const bool requireFragmentStores = (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT); 360 361 if (requireFragmentStores) 362 { 363 if (!context.getDeviceFeatures().fragmentStoresAndAtomics) 364 TCU_THROW(NotSupportedError, "fragmentStoresAndAtomics: feature not supported"); 365 } 366 367 checkPipelineConstructionRequirements(vki, physicalDevice, params.pipelineConstructionType); 368} 369 370//! Common data used by the test 371struct WorkingData 372{ 373 deUint32 numVertices; //!< Number of vertices defined in the vertex buffer 374 Move<VkBuffer> vertexBuffer; 375 MovePtr<Allocation> vertexBufferAlloc; 376 Move<VkImage> colorImage; //!< Color image 377 MovePtr<Allocation> colorImageAlloc; 378 Move<VkImageView> colorImageView; //!< Color image view spanning all layers 379 Move<VkBuffer> colorBuffer; //!< Buffer used to copy image data 380 MovePtr<Allocation> colorBufferAlloc; 381 VkDeviceSize colorBufferSize; 382 Move<VkSampler> defaultSampler; //!< Unused sampler, we are using texel fetches 383 384 WorkingData (void) 385 : numVertices () 386 , colorBufferSize () 387 { 388 } 389}; 390 391void initPrograms (SourceCollections& programCollection, const TestParams params) 392{ 393 std::string colorType; //!< color pixel type used by image functions 394 std::string colorBufferType; //!< packed pixel type as stored in a ssbo 395 std::string colorBufferPack; //!< a cast or a function call when writing back color format to the ssbo 396 std::string colorFragInQualifier; //!< fragment shader color input qualifier 397 std::string samplerPrefix; //!< u, i, or empty 398 399 switch (params.colorFormat) 400 { 401 case VK_FORMAT_R8G8B8A8_UNORM: 402 colorType = "vec4"; 403 colorBufferType = "uint"; 404 colorBufferPack = "packUnorm4x8"; 405 break; 406 407 case VK_FORMAT_R32_UINT: 408 colorType = "uint"; 409 colorBufferType = "uint"; 410 colorBufferPack = colorBufferType; 411 colorFragInQualifier = "flat"; 412 samplerPrefix = "u"; 413 break; 414 415 case VK_FORMAT_R32_SINT: 416 colorType = "int"; 417 colorBufferType = "int"; 418 colorBufferPack = colorBufferType; 419 colorFragInQualifier = "flat"; 420 samplerPrefix = "i"; 421 break; 422 423 default: 424 DE_FATAL("initPrograms not handled for this color format"); 425 break; 426 } 427 428 // Vertex shader - position and color 429 { 430 std::ostringstream src; 431 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 432 << "\n" 433 << "layout(location = 0) in vec4 in_position;\n" 434 << "layout(location = 1) in " << colorType << " in_color;\n" 435 << "layout(location = 0) out " << colorType << " o_color;\n" 436 << "\n" 437 << "out gl_PerVertex {\n" 438 << " vec4 gl_Position;\n" 439 << "};\n" 440 << "\n" 441 << "void main(void)\n" 442 << "{\n" 443 // Introduce a variance in geometry per instance index which maps to the image layer 444 << " float a = 0.25 * float(gl_InstanceIndex);\n" 445 << " mat3 rm = mat3( cos(a), sin(a), 0.0,\n" 446 << " -sin(a), cos(a), 0.0,\n" 447 << " 0.0, 0.0, 1.0);\n" 448 << " vec2 rpos = (rm * vec3(in_position.xy, 1.0)).xy;\n" 449 << "\n" 450 << " gl_Position = vec4(rpos, in_position.zw);\n" 451 << " o_color = in_color;\n" 452 << "}\n"; 453 454 programCollection.glslSources.add("vert") << glu::VertexSource(src.str()); 455 } 456 457 // Vertex shader - no vertex data, fill viewport with one primitive 458 { 459 std::ostringstream src; 460 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 461 << "\n" 462 << "out gl_PerVertex {\n" 463 << " vec4 gl_Position;\n" 464 << "};\n" 465 << "\n" 466 << "void main(void)\n" 467 << "{\n" 468 // Specify an oversized triangle covering the whole viewport. 469 << " switch (gl_VertexIndex)\n" 470 << " {\n" 471 << " case 0:\n" 472 << " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n" 473 << " break;\n" 474 << " case 1:\n" 475 << " gl_Position = vec4(-1.0, 3.0, 0.0, 1.0);\n" 476 << " break;\n" 477 << " case 2:\n" 478 << " gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n" 479 << " break;\n" 480 << " }\n" 481 << "}\n"; 482 483 programCollection.glslSources.add("vert_full") << glu::VertexSource(src.str()); 484 } 485 486 // Fragment shader - output color from VS 487 { 488 std::ostringstream src; 489 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 490 << "\n" 491 << "layout(location = 0) in " << colorFragInQualifier << " " << colorType << " in_color;\n" 492 << "layout(location = 0) out " << colorType << " o_color;\n" 493 << "\n" 494 << "void main(void)\n" 495 << "{\n" 496 << " o_color = in_color;\n" 497 << "}\n"; 498 499 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str()); 500 } 501 502 // Fragment shader - FMASK fetch from an input attachment 503 if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT) 504 { 505 std::ostringstream src; 506 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 507 << "#extension GL_AMD_shader_fragment_mask : enable\n" 508 << "\n" 509 << "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n" 510 << "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n" 511 << " " << colorBufferType << " color[];\n" 512 << "} sb_out;\n" 513 << "layout(input_attachment_index = 0, set = 0, binding = 2) uniform " << samplerPrefix << "subpassInputMS" << " input_attach;\n" 514 << "\n" 515 << "void main(void)\n" 516 << "{\n" 517 << " ivec2 p = ivec2(gl_FragCoord.xy);\n" 518 << " int width = " << params.renderSize.x() << ";\n" 519 << " int numSamples = " << static_cast<deUint32>(params.numColorSamples) << ";\n" 520 << " int colorOutNdx = numSamples * (p.x + width * p.y);\n" 521 << "\n" 522 << " uint mask = fragmentMaskFetchAMD(input_attach);\n" 523 << " for (int sampleNdx = 0; sampleNdx < numSamples; ++sampleNdx)\n" 524 << " {\n" 525 << " int fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n" 526 << " " << samplerPrefix << "vec4 color = fragmentFetchAMD(input_attach, fragNdx);\n" 527 << " sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n" 528 << " }\n" 529 << "}\n"; 530 531 programCollection.glslSources.add("frag_fmask_fetch") << glu::FragmentSource(src.str()); 532 } 533 534 // Generate compute shaders 535 const struct ComputeShaderParams 536 { 537 const char* name; 538 bool isFmaskFetch; 539 bool enabled; 540 } computeShaders[] = 541 { 542 // name // FMASK? // enabled? 543 { "comp_fetch", false, true, }, 544 { "comp_fmask_fetch", true, (params.sampleSource != SAMPLE_SOURCE_SUBPASS_INPUT) }, 545 }; 546 547 for (const ComputeShaderParams* pShaderParams = computeShaders; pShaderParams != DE_ARRAY_END(computeShaders); ++pShaderParams) 548 if (pShaderParams->enabled) 549 { 550 const std::string samplingPos = (params.numLayers == 1 ? "ivec2(gl_WorkGroupID.xy)" 551 : "ivec3(gl_WorkGroupID)"); 552 std::ostringstream src; 553 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" 554 << (pShaderParams->isFmaskFetch ? "#extension GL_AMD_shader_fragment_mask : enable\n" : "") 555 << "#define NUM_SAMPLES " << static_cast<deUint32>(params.numColorSamples) << "\n" 556 << "\n" 557 << "layout(local_size_x = NUM_SAMPLES) in;\n" // one work group per pixel, each sample gets a local invocation 558 << "\n" 559 << "layout(set = 0, binding = 0) uniform " << samplerPrefix << "sampler2DMS" << (params.numLayers > 1 ? "Array" : "") << " u_image;\n" 560 << "layout(set = 0, binding = 1, std430) writeonly buffer ColorOutput {\n" 561 << " " << colorBufferType << " color[];\n" 562 << "} sb_out;\n" 563 << "\n" 564 << "void main(void)\n" 565 << "{\n" 566 << " int sampleNdx = int(gl_LocalInvocationID.x);\n" 567 << " int colorOutNdx = NUM_SAMPLES * int(gl_WorkGroupID.x +\n" 568 << " gl_WorkGroupID.y * gl_NumWorkGroups.x +\n" 569 << " gl_WorkGroupID.z * gl_NumWorkGroups.x * gl_NumWorkGroups.y);\n" 570 << "\n"; 571 if (pShaderParams->isFmaskFetch) 572 { 573 src << " uint mask = fragmentMaskFetchAMD(u_image, " << samplingPos << ");\n" 574 << " int fragNdx = int((mask >> (4 * sampleNdx)) & 0xf);\n" 575 << " " << samplerPrefix << "vec4 color = fragmentFetchAMD(u_image, " << samplingPos << ", fragNdx);\n" 576 << " sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n"; 577 } 578 else 579 { 580 src << " " << samplerPrefix << "vec4 color = texelFetch(u_image, " << samplingPos << ", sampleNdx);\n" 581 << " sb_out.color[colorOutNdx + sampleNdx] = " << colorBufferPack << "(color);\n"; 582 } 583 src << "}\n"; 584 585 programCollection.glslSources.add(pShaderParams->name) << glu::ComputeSource(src.str()); 586 } 587} 588 589std::vector<VkClearValue> genClearValues (const VkFormat format, const deUint32 count) 590{ 591 std::vector<VkClearValue> clearValues; 592 de::Random rng (332); 593 594 switch (format) 595 { 596 case VK_FORMAT_R8G8B8A8_UNORM: 597 for (deUint32 i = 0u; i < count; ++i) 598 clearValues.push_back(makeClearValueColorF32(rng.getFloat(), rng.getFloat(), rng.getFloat(), 1.0f)); 599 break; 600 601 case VK_FORMAT_R32_UINT: 602 case VK_FORMAT_R32_SINT: 603 for (deUint32 i = 0u; i < count; ++i) 604 clearValues.push_back(makeClearValueColorU32(rng.getUint32(), 0u, 0u, 0u)); 605 break; 606 607 default: 608 DE_FATAL("Clear color not defined for this format"); 609 break; 610 } 611 612 return clearValues; 613} 614 615//! For subpass load case draw and fetch must happen within the same render pass. 616void drawAndSampleInputAttachment (Context& context, const TestParams& params, WorkingData& wd) 617{ 618 DE_ASSERT(params.numLayers == 1u); // subpass load with single-layer image 619 620 const InstanceInterface& vki = context.getInstanceInterface(); 621 const DeviceInterface& vk = SingletonDevice::getDeviceInterface(context); 622 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 623 const VkDevice device = SingletonDevice::getDevice(context); 624 625 RenderPassWrapper renderPass; 626 627 // Create descriptor set 628 const Unique<VkDescriptorSetLayout> descriptorSetLayout (DescriptorSetLayoutBuilder() 629 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, &wd.defaultSampler.get()) 630 .addSingleBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT) 631 .addSingleBinding (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT) 632 .build(vk, device)); 633 634 const Unique<VkDescriptorPool> descriptorPool (DescriptorPoolBuilder() 635 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 636 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 637 .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) 638 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); 639 640 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); 641 642 { 643 const VkDescriptorImageInfo colorImageInfo = makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 644 const VkDescriptorBufferInfo bufferInfo = makeDescriptorBufferInfo(*wd.colorBuffer, 0u, wd.colorBufferSize); 645 646 DescriptorSetUpdateBuilder builder; 647 648 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo); 649 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo); 650 651 if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT) 652 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &colorImageInfo); 653 654 builder.update(vk, device); 655 } 656 657 // Create a render pass and a framebuffer 658 { 659 std::vector<VkSubpassDescription> subpasses; 660 std::vector<VkSubpassDependency> subpassDependencies; 661 std::vector<VkImage> images; 662 std::vector<VkImageView> attachments; 663 std::vector<VkAttachmentDescription> attachmentDescriptions; 664 std::vector<VkAttachmentReference> attachmentReferences; 665 666 // Reserve capacity to avoid invalidating pointers to elements 667 attachmentReferences.reserve(2); // color image + input attachment 668 669 // Create a MS draw subpass 670 { 671 images.push_back(*wd.colorImage); 672 attachments.push_back(*wd.colorImageView); 673 674 attachmentDescriptions.push_back(makeAttachmentDescription( 675 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 676 params.colorFormat, // VkFormat format; 677 params.numColorSamples, // VkSampleCountFlagBits samples; 678 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 679 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 680 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 681 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 682 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 683 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout; 684 )); 685 686 attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); 687 const VkAttachmentReference* colorRef = &attachmentReferences.back(); 688 689 const VkSubpassDescription subpassDescription = 690 { 691 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 692 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 693 0u, // uint32_t inputAttachmentCount; 694 DE_NULL, // const VkAttachmentReference* pInputAttachments; 695 1u, // uint32_t colorAttachmentCount; 696 colorRef, // const VkAttachmentReference* pColorAttachments; 697 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 698 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 699 0u, // uint32_t preserveAttachmentCount; 700 DE_NULL, // const uint32_t* pPreserveAttachments; 701 }; 702 703 subpasses.push_back(subpassDescription); 704 } 705 706 // Create a sampling subpass 707 { 708 attachmentReferences.push_back(makeAttachmentReference(0u, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)); 709 const VkAttachmentReference* inputRef = &attachmentReferences.back(); 710 711 // No color attachment, side effects only 712 VkSubpassDescription subpassDescription = 713 { 714 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 715 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 716 1u, // uint32_t inputAttachmentCount; 717 inputRef, // const VkAttachmentReference* pInputAttachments; 718 0u, // uint32_t colorAttachmentCount; 719 DE_NULL, // const VkAttachmentReference* pColorAttachments; 720 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 721 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 722 0u, // uint32_t preserveAttachmentCount; 723 DE_NULL, // const uint32_t* pPreserveAttachments; 724 }; 725 726 subpasses.push_back(subpassDescription); 727 } 728 729 // Serialize the subpasses 730 { 731 const VkAccessFlags dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT 732 | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT 733 | VK_ACCESS_SHADER_WRITE_BIT; 734 const VkSubpassDependency dependency = 735 { 736 0u, // uint32_t srcSubpass; 737 1u, // uint32_t dstSubpass; 738 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags srcStageMask; 739 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, // VkPipelineStageFlags dstStageMask; 740 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags srcAccessMask; 741 dstAccessMask, // VkAccessFlags dstAccessMask; 742 VK_DEPENDENCY_BY_REGION_BIT, // VkDependencyFlags dependencyFlags; 743 }; 744 subpassDependencies.push_back(dependency); 745 } 746 747 VkRenderPassCreateInfo renderPassInfo = 748 { 749 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 750 DE_NULL, // const void* pNext; 751 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 752 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount; 753 dataOrNullPtr(attachmentDescriptions), // const VkAttachmentDescription* pAttachments; 754 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount; 755 dataOrNullPtr(subpasses), // const VkSubpassDescription* pSubpasses; 756 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount; 757 dataOrNullPtr(subpassDependencies), // const VkSubpassDependency* pDependencies; 758 }; 759 760 renderPass = RenderPassWrapper(params.pipelineConstructionType, vk, device, &renderPassInfo); 761 renderPass.createFramebuffer(vk, device, static_cast<deUint32>(attachments.size()), dataOrNullPtr(images), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y()); 762 } 763 764 const std::vector<VkViewport> viewports { makeViewport(params.renderSize) }; 765 const std::vector<VkRect2D> scissors { makeRect2D(params.renderSize) }; 766 767 VkPipelineMultisampleStateCreateInfo multisampleStateInfo 768 { 769 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 770 DE_NULL, // const void* pNext; 771 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 772 params.numColorSamples, // VkSampleCountFlagBits rasterizationSamples; 773 VK_FALSE, // VkBool32 sampleShadingEnable; 774 1.0f, // float minSampleShading; 775 DE_NULL, // const VkSampleMask* pSampleMask; 776 VK_FALSE, // VkBool32 alphaToCoverageEnable; 777 VK_FALSE // VkBool32 alphaToOneEnable; 778 }; 779 780 const VkPipelineColorBlendAttachmentState defaultBlendAttachmentState 781 { 782 VK_FALSE, // VkBool32 blendEnable; 783 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 784 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 785 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 786 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 787 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 788 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 789 0xf, // VkColorComponentFlags colorWriteMask; 790 }; 791 792 VkPipelineColorBlendStateCreateInfo colorBlendStateInfo 793 { 794 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 795 DE_NULL, // const void* pNext; 796 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 797 VK_FALSE, // VkBool32 logicOpEnable; 798 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 799 1u, // deUint32 attachmentCount; 800 &defaultBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 801 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 802 }; 803 804 const ShaderWrapper vertexModuleDraw (ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u)); 805 const ShaderWrapper fragmentModuleDraw (ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u)); 806 807 // Create pipelines for MS draw 808 const PipelineLayoutWrapper pipelineLayout (params.pipelineConstructionType, vk, device, *descriptorSetLayout); 809 GraphicsPipelineWrapper pipelineDraw (vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType); 810 { 811 // Vertex attributes: position and color 812 VkVertexInputBindingDescription vertexInputBindingDescriptions = makeVertexInputBindingDescription(0u, sizeof(PositionColor), VK_VERTEX_INPUT_RATE_VERTEX); 813 std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions 814 { 815 makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u), 816 makeVertexInputAttributeDescription(1u, 0u, getVertexInputColorFormat(params.colorFormat), sizeof(Vec4)) 817 }; 818 819 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo 820 { 821 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 822 DE_NULL, // const void* pNext; 823 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 824 1u, // uint32_t vertexBindingDescriptionCount; 825 &vertexInputBindingDescriptions, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 826 static_cast<deUint32>(vertexInputAttributeDescriptions.size()), // uint32_t vertexAttributeDescriptionCount; 827 vertexInputAttributeDescriptions.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 828 }; 829 830 pipelineDraw.setDefaultRasterizationState() 831 .setDefaultDepthStencilState() 832 .setupVertexInputState(&vertexInputStateInfo) 833 .setupPreRasterizationShaderState(viewports, 834 scissors, 835 pipelineLayout, 836 *renderPass, 837 0u, 838 vertexModuleDraw) 839 .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragmentModuleDraw, DE_NULL, &multisampleStateInfo) 840 .setupFragmentOutputState(*renderPass, 0u, &colorBlendStateInfo, &multisampleStateInfo) 841 .setMonolithicPipelineLayout(pipelineLayout) 842 .buildPipeline(); 843 } 844 845 // Sampling pass is single-sampled, output to storage buffer 846 const ShaderWrapper vertexModuleSample (ShaderWrapper(vk, device, context.getBinaryCollection().get("vert_full"), 0u)); 847 const ShaderWrapper fragmentModuleSample (ShaderWrapper(vk, device, context.getBinaryCollection().get("frag_fmask_fetch"), 0u)); 848 849 // Sampling pipeline 850 GraphicsPipelineWrapper pipelineSample(vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType); 851 { 852 VkPipelineVertexInputStateCreateInfo vertexInputStateInfo; 853 deMemset(&vertexInputStateInfo, 0, sizeof(vertexInputStateInfo)); 854 vertexInputStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; 855 856 multisampleStateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; 857 colorBlendStateInfo.attachmentCount = 0u; 858 859 pipelineSample.setDefaultRasterizationState() 860 .setDefaultDepthStencilState() 861 .setupVertexInputState(&vertexInputStateInfo) 862 .setupPreRasterizationShaderState(viewports, 863 scissors, 864 pipelineLayout, 865 *renderPass, 866 1u, 867 vertexModuleSample) 868 .setupFragmentShaderState(pipelineLayout, *renderPass, 1u, fragmentModuleSample, DE_NULL, &multisampleStateInfo) 869 .setupFragmentOutputState(*renderPass, 1u, &colorBlendStateInfo, &multisampleStateInfo) 870 .setMonolithicPipelineLayout(pipelineLayout) 871 .buildPipeline(); 872 } 873 874 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex())); 875 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 876 877 beginCommandBuffer(vk, *cmdBuffer); 878 879 { 880 // Generate clear values 881 std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers); 882 883 const VkRect2D renderArea = 884 { 885 { 0u, 0u }, 886 { params.renderSize.x(), params.renderSize.y() } 887 }; 888 renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<deUint32>(clearValues.size()), dataOrNullPtr(clearValues)); 889 } 890 891 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 892 893 { 894 const VkDeviceSize vertexBufferOffset = 0ull; 895 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset); 896 } 897 898 pipelineDraw.bind(*cmdBuffer); 899 vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, 0u); 900 901 renderPass.nextSubpass(vk, *cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); 902 903 pipelineSample.bind(*cmdBuffer); 904 vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u); // fill the framebuffer, geometry defined in the VS 905 906 renderPass.end(vk, *cmdBuffer); 907 908 // Buffer write barrier 909 { 910 const VkBufferMemoryBarrier barrier = 911 { 912 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 913 DE_NULL, // const void* pNext; 914 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask; 915 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 916 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 917 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 918 *wd.colorBuffer, // VkBuffer buffer; 919 0ull, // VkDeviceSize offset; 920 VK_WHOLE_SIZE, // VkDeviceSize size; 921 }; 922 923 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0u, DE_NULL, 1u, &barrier, DE_NULL, 0u); 924 } 925 926 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 927 submitCommandsAndWait(vk, device, SingletonDevice::getUniversalQueue(context), *cmdBuffer); 928 929 invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE); 930} 931 932//! Only draw a multisampled image 933void draw (Context& context, const TestParams& params, WorkingData& wd) 934{ 935 const InstanceInterface & vki = context.getInstanceInterface(); 936 const DeviceInterface& vk = SingletonDevice::getDeviceInterface(context); 937 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 938 const VkDevice device = SingletonDevice::getDevice(context); 939 940 std::vector<ImageViewSp> imageViews; 941 RenderPassWrapper renderPass; 942 943 // Create color attachments 944 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx) 945 { 946 imageViews.push_back(ImageViewSp(new Unique<VkImageView>( 947 makeImageView(vk, device, *wd.colorImage, VK_IMAGE_VIEW_TYPE_2D, params.colorFormat, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, layerNdx, 1u))))); 948 } 949 950 // Create a render pass and a framebuffer 951 { 952 std::vector<VkSubpassDescription> subpasses; 953 std::vector<VkImage> images; 954 std::vector<VkImageView> attachments; 955 std::vector<VkAttachmentDescription> attachmentDescriptions; 956 std::vector<VkAttachmentReference> attachmentReferences; 957 958 // Reserve capacity to avoid invalidating pointers to elements 959 attachmentReferences.reserve(params.numLayers); 960 961 // Create MS draw subpasses 962 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx) 963 { 964 images.push_back(*wd.colorImage); 965 attachments.push_back(**imageViews[layerNdx]); 966 967 attachmentDescriptions.push_back(makeAttachmentDescription( 968 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags; 969 params.colorFormat, // VkFormat format; 970 params.numColorSamples, // VkSampleCountFlagBits samples; 971 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 972 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 973 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 974 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 975 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 976 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout; 977 )); 978 979 attachmentReferences.push_back(makeAttachmentReference(static_cast<deUint32>(attachmentReferences.size()), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); 980 const VkAttachmentReference* colorRef = &attachmentReferences.back(); 981 982 const VkSubpassDescription subpassDescription = 983 { 984 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags; 985 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 986 0u, // uint32_t inputAttachmentCount; 987 DE_NULL, // const VkAttachmentReference* pInputAttachments; 988 1u, // uint32_t colorAttachmentCount; 989 colorRef, // const VkAttachmentReference* pColorAttachments; 990 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 991 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 992 0u, // uint32_t preserveAttachmentCount; 993 DE_NULL, // const uint32_t* pPreserveAttachments; 994 }; 995 996 subpasses.push_back(subpassDescription); 997 } 998 999 // All MS image drawing subpasses are independent 1000 VkRenderPassCreateInfo renderPassInfo = 1001 { 1002 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 1003 DE_NULL, // const void* pNext; 1004 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags; 1005 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount; 1006 dataOrNullPtr(attachmentDescriptions), // const VkAttachmentDescription* pAttachments; 1007 static_cast<deUint32>(subpasses.size()), // deUint32 subpassCount; 1008 dataOrNullPtr(subpasses), // const VkSubpassDescription* pSubpasses; 1009 0u, // deUint32 dependencyCount; 1010 DE_NULL, // const VkSubpassDependency* pDependencies; 1011 }; 1012 1013 renderPass = RenderPassWrapper(params.pipelineConstructionType, vk, device, &renderPassInfo); 1014 renderPass.createFramebuffer(vk, device, static_cast<deUint32>(attachments.size()), dataOrNullPtr(images), dataOrNullPtr(attachments), params.renderSize.x(), params.renderSize.y()); 1015 } 1016 1017 const PipelineLayoutWrapper pipelineLayout (params.pipelineConstructionType, vk, device); 1018 const ShaderWrapper vertexModuleDraw (ShaderWrapper(vk, device, context.getBinaryCollection().get("vert"), 0u)); 1019 const ShaderWrapper fragmentModuleDraw (ShaderWrapper(vk, device, context.getBinaryCollection().get("frag"), 0u)); 1020 1021 // Vertex attributes: position and color 1022 VkVertexInputBindingDescription vertexInputBindingDescriptions = makeVertexInputBindingDescription(0u, sizeof(PositionColor), VK_VERTEX_INPUT_RATE_VERTEX); 1023 std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescriptions 1024 { 1025 makeVertexInputAttributeDescription(0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u), 1026 makeVertexInputAttributeDescription(1u, 0u, getVertexInputColorFormat(params.colorFormat), sizeof(Vec4)) 1027 }; 1028 1029 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo 1030 { 1031 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 1032 DE_NULL, // const void* pNext; 1033 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags; 1034 1u, // uint32_t vertexBindingDescriptionCount; 1035 &vertexInputBindingDescriptions, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 1036 static_cast<deUint32>(vertexInputAttributeDescriptions.size()), // uint32_t vertexAttributeDescriptionCount; 1037 vertexInputAttributeDescriptions.data(), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 1038 }; 1039 1040 const std::vector<VkViewport> viewports { makeViewport(params.renderSize) }; 1041 const std::vector<VkRect2D> scissors { makeRect2D(params.renderSize) }; 1042 1043 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo 1044 { 1045 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 1046 DE_NULL, // const void* pNext; 1047 (VkPipelineMultisampleStateCreateFlags)0, // VkPipelineMultisampleStateCreateFlags flags; 1048 params.numColorSamples, // VkSampleCountFlagBits rasterizationSamples; 1049 VK_FALSE, // VkBool32 sampleShadingEnable; 1050 1.0f, // float minSampleShading; 1051 DE_NULL, // const VkSampleMask* pSampleMask; 1052 VK_FALSE, // VkBool32 alphaToCoverageEnable; 1053 VK_FALSE // VkBool32 alphaToOneEnable; 1054 }; 1055 1056 const VkPipelineColorBlendAttachmentState defaultBlendAttachmentState 1057 { 1058 VK_FALSE, // VkBool32 blendEnable; 1059 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 1060 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 1061 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 1062 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 1063 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 1064 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 1065 0xf, // VkColorComponentFlags colorWriteMask; 1066 }; 1067 1068 VkPipelineColorBlendStateCreateInfo colorBlendStateInfo 1069 { 1070 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 1071 DE_NULL, // const void* pNext; 1072 (VkPipelineColorBlendStateCreateFlags)0, // VkPipelineColorBlendStateCreateFlags flags; 1073 VK_FALSE, // VkBool32 logicOpEnable; 1074 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 1075 1u, // deUint32 attachmentCount; 1076 &defaultBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 1077 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4]; 1078 }; 1079 1080 // Create pipelines for MS draw 1081 std::vector<GraphicsPipelineWrapper> pipelines; 1082 pipelines.reserve(params.numLayers); 1083 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx) 1084 { 1085 pipelines.emplace_back(vki, vk, physicalDevice, device, context.getDeviceExtensions(), params.pipelineConstructionType); 1086 pipelines.back().setDefaultRasterizationState() 1087 .setDefaultColorBlendState() 1088 .setDefaultDepthStencilState() 1089 .setupVertexInputState(&vertexInputStateInfo) 1090 .setupPreRasterizationShaderState(viewports, 1091 scissors, 1092 pipelineLayout, 1093 *renderPass, 1094 layerNdx, 1095 vertexModuleDraw) 1096 .setupFragmentShaderState(pipelineLayout, *renderPass, layerNdx, fragmentModuleDraw, DE_NULL, &multisampleStateInfo) 1097 .setupFragmentOutputState(*renderPass, layerNdx, &colorBlendStateInfo, &multisampleStateInfo) 1098 .setMonolithicPipelineLayout(pipelineLayout) 1099 .buildPipeline(); 1100 } 1101 1102 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex())); 1103 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1104 1105 beginCommandBuffer(vk, *cmdBuffer); 1106 1107 { 1108 // Generate clear values 1109 std::vector<VkClearValue> clearValues = genClearValues(params.colorFormat, params.numLayers); 1110 1111 const VkRect2D renderArea = 1112 { 1113 { 0u, 0u }, 1114 { params.renderSize.x(), params.renderSize.y() } 1115 }; 1116 1117 renderPass.begin(vk, *cmdBuffer, renderArea, static_cast<deUint32>(clearValues.size()), dataOrNullPtr(clearValues)); 1118 } 1119 1120 { 1121 const VkDeviceSize vertexBufferOffset = 0ull; 1122 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &wd.vertexBuffer.get(), &vertexBufferOffset); 1123 } 1124 1125 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx) 1126 { 1127 if (layerNdx != 0u) 1128 renderPass.nextSubpass(vk, *cmdBuffer, VK_SUBPASS_CONTENTS_INLINE); 1129 1130 pipelines[layerNdx].bind(*cmdBuffer); 1131 vk.cmdDraw(*cmdBuffer, wd.numVertices, 1u, 0u, layerNdx); // pass instance index to slightly change geometry per layer 1132 } 1133 1134 renderPass.end(vk, *cmdBuffer); 1135 1136 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 1137 submitCommandsAndWait(vk, device, SingletonDevice::getUniversalQueue(context), *cmdBuffer); 1138} 1139 1140//! Sample from an image in a compute shader, storing the result in a color buffer 1141void dispatchSampleImage (Context& context, const TestParams& params, WorkingData& wd, const std::string& shaderName) 1142{ 1143 const DeviceInterface& vk = SingletonDevice::getDeviceInterface(context); 1144 const VkDevice device = SingletonDevice::getDevice(context); 1145 1146 // Create descriptor set 1147 1148 const Unique<VkDescriptorSetLayout> descriptorSetLayout( 1149 DescriptorSetLayoutBuilder() 1150 .addSingleSamplerBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT, &wd.defaultSampler.get()) 1151 .addSingleBinding (VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT) 1152 .build(vk, device)); 1153 1154 const Unique<VkDescriptorPool> descriptorPool( 1155 DescriptorPoolBuilder() 1156 .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 1157 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) 1158 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); 1159 1160 const Unique<VkDescriptorSet> descriptorSet(makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); 1161 1162 { 1163 const VkDescriptorImageInfo colorImageInfo = makeDescriptorImageInfo(DE_NULL, *wd.colorImageView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 1164 const VkDescriptorBufferInfo resultBufferInfo = makeDescriptorBufferInfo(*wd.colorBuffer, 0ull, wd.colorBufferSize); 1165 1166 DescriptorSetUpdateBuilder builder; 1167 1168 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &colorImageInfo); 1169 builder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferInfo); 1170 1171 builder.update(vk, device); 1172 } 1173 1174 // Pipeline 1175 1176 const Unique<VkShaderModule> shaderModule (createShaderModule(vk, device, context.getBinaryCollection().get(shaderName), 0u)); 1177 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout)); 1178 const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule)); 1179 1180 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex())); 1181 const Unique<VkCommandBuffer> cmdBuffer (makeCommandBuffer(vk, device, *cmdPool)); 1182 1183 beginCommandBuffer(vk, *cmdBuffer); 1184 1185 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); 1186 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); 1187 1188 vk.cmdDispatch(*cmdBuffer, params.renderSize.x(), params.renderSize.y(), params.numLayers); 1189 1190 { 1191 const VkBufferMemoryBarrier barrier = 1192 { 1193 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType; 1194 DE_NULL, // const void* pNext; 1195 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask; 1196 VK_ACCESS_HOST_READ_BIT, // VkAccessFlags dstAccessMask; 1197 VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex; 1198 VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex; 1199 *wd.colorBuffer, // VkBuffer buffer; 1200 0ull, // VkDeviceSize offset; 1201 VK_WHOLE_SIZE, // VkDeviceSize size; 1202 }; 1203 1204 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, 1205 (const VkMemoryBarrier*)DE_NULL, 1u, &barrier, 0u, (const VkImageMemoryBarrier*)DE_NULL); 1206 } 1207 1208 VK_CHECK(vk.endCommandBuffer(*cmdBuffer)); 1209 submitCommandsAndWait(vk, device, SingletonDevice::getUniversalQueue(context), *cmdBuffer); 1210 1211 invalidateMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE); 1212} 1213 1214//! Get a single-sampled image access from a multisampled color buffer with samples packed per pixel 1215tcu::ConstPixelBufferAccess getSingleSampledAccess (const void* const imageData, const TestParams& params, const deUint32 sampleNdx, const deUint32 layerNdx) 1216{ 1217 const deUint32 numSamples = static_cast<deUint32>(params.numColorSamples); 1218 const deUint32 pixelSize = tcu::getPixelSize(mapVkFormat(params.colorFormat)); 1219 const deUint32 rowSize = pixelSize * params.renderSize.x(); 1220 const deUint32 layerSize = rowSize * params.renderSize.y(); 1221 const deUint8* src = static_cast<const deUint8*>(imageData) 1222 + (layerNdx * numSamples * layerSize) 1223 + (sampleNdx * pixelSize); 1224 const tcu::IVec3 size (params.renderSize.x(), params.renderSize.y(), 1); 1225 const tcu::IVec3 pitch (numSamples * pixelSize, 1226 numSamples * rowSize, 1227 numSamples * layerSize); 1228 return tcu::ConstPixelBufferAccess(mapVkFormat(params.colorFormat), size, pitch, src); 1229} 1230 1231tcu::TestStatus test (Context& context, const TestParams params) 1232{ 1233 WorkingData wd; 1234 const DeviceInterface& vk = SingletonDevice::getDeviceInterface(context); 1235 const VkDevice device = SingletonDevice::getDevice(context); 1236 1237 MovePtr<Allocator> allocator = MovePtr<Allocator>(new SimpleAllocator(vk, device, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()))); 1238 1239 // Initialize resources 1240 { 1241 const VkImageUsageFlags msImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT 1242 | VK_IMAGE_USAGE_SAMPLED_BIT 1243 | (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT ? VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0); 1244 wd.colorImage = makeImage(vk, device, params.colorFormat, params.renderSize, params.numLayers, params.numColorSamples, msImageUsage); 1245 wd.colorImageAlloc = bindImage(vk, device, *allocator, *wd.colorImage, MemoryRequirement::Any); 1246 wd.colorImageView = makeImageView(vk, device, *wd.colorImage, (params.numLayers == 1u ? VK_IMAGE_VIEW_TYPE_2D : VK_IMAGE_VIEW_TYPE_2D_ARRAY), params.colorFormat, 1247 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, params.numLayers)); 1248 1249 wd.defaultSampler = makeSampler(vk, device); 1250 1251 // Color buffer is meant to hold data for all layers and all samples of the image. 1252 // Data is tightly packed layer by layer, for each pixel all samples are laid out together starting with sample 0. 1253 // E.g.: pixel(0,0)sample(0)sample(1), pixel(1,0)sample(0)sample(1), ... 1254 wd.colorBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(mapVkFormat(params.colorFormat)) 1255 * params.renderSize.x() * params.renderSize.y() * params.numLayers * static_cast<deUint32>(params.numColorSamples)); 1256 wd.colorBuffer = makeBuffer(vk, device, wd.colorBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT); 1257 wd.colorBufferAlloc = bindBuffer(vk, device, *allocator, *wd.colorBuffer, MemoryRequirement::HostVisible); 1258 1259 deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize)); 1260 flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE); 1261 1262 const std::vector<PositionColor> vertices = genShapes(params.colorFormat); 1263 const VkDeviceSize vertexBufferSize = static_cast<VkDeviceSize>(sizeof(vertices[0]) * vertices.size()); 1264 1265 wd.numVertices = static_cast<deUint32>(vertices.size()); 1266 wd.vertexBuffer = makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); 1267 wd.vertexBufferAlloc = bindBuffer(vk, device, *allocator, *wd.vertexBuffer, MemoryRequirement::HostVisible); 1268 1269 deMemcpy(wd.vertexBufferAlloc->getHostPtr(), dataOrNullPtr(vertices), static_cast<std::size_t>(vertexBufferSize)); 1270 flushMappedMemoryRange(vk, device, wd.vertexBufferAlloc->getMemory(), wd.vertexBufferAlloc->getOffset(), VK_WHOLE_SIZE); 1271 } 1272 1273 if (params.sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT) 1274 { 1275 // Create a multisample image and sample from it 1276 drawAndSampleInputAttachment (context, params, wd); 1277 } 1278 else 1279 { 1280 // Draw the image, then sample from it in a CS 1281 draw (context, params, wd); 1282 dispatchSampleImage (context, params, wd, "comp_fmask_fetch"); 1283 } 1284 1285 // Copy the result 1286 std::vector<deUint8> fmaskFetchColorBuffer (static_cast<deUint32>(wd.colorBufferSize)); 1287 deMemcpy(&fmaskFetchColorBuffer[0], wd.colorBufferAlloc->getHostPtr(), static_cast<std::size_t>(wd.colorBufferSize)); 1288 1289 // Clear the color buffer, just to be sure we're getting the new data 1290 deMemset(wd.colorBufferAlloc->getHostPtr(), 0, static_cast<std::size_t>(wd.colorBufferSize)); 1291 flushMappedMemoryRange(vk, device, wd.colorBufferAlloc->getMemory(), wd.colorBufferAlloc->getOffset(), VK_WHOLE_SIZE); 1292 1293 // Sample image using the standard texel fetch 1294 dispatchSampleImage (context, params, wd, "comp_fetch"); 1295 1296 // Verify the images 1297 { 1298 const void* const fmaskResult = dataOrNullPtr(fmaskFetchColorBuffer); 1299 const void* const expectedResult = wd.colorBufferAlloc->getHostPtr(); 1300 1301 DE_ASSERT(!isFloatFormat(params.colorFormat)); // we're using int compare 1302 1303 // Mismatch, do image compare to pinpoint the failure 1304 for (deUint32 layerNdx = 0u; layerNdx < params.numLayers; ++layerNdx) 1305 for (deUint32 sampleNdx = 0u; sampleNdx < static_cast<deUint32>(params.numColorSamples); ++sampleNdx) 1306 { 1307 const std::string imageName = "layer_" + de::toString(layerNdx) + "_sample_" + de::toString(sampleNdx); 1308 const std::string imageDesc = "Layer " + de::toString(layerNdx) + " Sample " + de::toString(sampleNdx); 1309 const tcu::ConstPixelBufferAccess expected = getSingleSampledAccess(expectedResult, params, sampleNdx, layerNdx); 1310 const tcu::ConstPixelBufferAccess actual = getSingleSampledAccess(fmaskResult, params, sampleNdx, layerNdx); 1311 const UVec4 threshold (0); // should match exactly 1312 1313 const bool ok = tcu::intThresholdCompare(context.getTestContext().getLog(), imageName.c_str(), imageDesc.c_str(), 1314 expected, actual, threshold, tcu::COMPARE_LOG_RESULT); 1315 1316 if (!ok) 1317 return tcu::TestStatus::fail("Some texels were incorrect"); 1318 } 1319 } 1320 1321 return tcu::TestStatus::pass("Pass"); 1322} 1323 1324std::string getFormatShortString (const VkFormat format) 1325{ 1326 std::string s(de::toLower(getFormatName(format))); 1327 return s.substr(10); 1328} 1329 1330void createShaderFragmentMaskTestsInGroup (tcu::TestCaseGroup* rootGroup, PipelineConstructionType pipelineConstructionType) 1331{ 1332 // Per spec, the following formats must support color attachment and sampled image 1333 const VkFormat colorFormats[] = 1334 { 1335 VK_FORMAT_R8G8B8A8_UNORM, 1336 VK_FORMAT_R32_UINT, 1337 VK_FORMAT_R32_SINT, 1338 }; 1339 1340 const VkSampleCountFlagBits sampleCounts[] = 1341 { 1342 VK_SAMPLE_COUNT_2_BIT, 1343 VK_SAMPLE_COUNT_4_BIT, 1344 VK_SAMPLE_COUNT_8_BIT, 1345 VK_SAMPLE_COUNT_16_BIT, 1346 }; 1347 1348 const struct SourceCase 1349 { 1350 const char* name; 1351 deUint32 numLayers; 1352 SampleSource sampleSource; 1353 } sourceCases[] = 1354 { 1355 { "image_2d", 1u, SAMPLE_SOURCE_IMAGE }, 1356 { "image_2d_array", 3u, SAMPLE_SOURCE_IMAGE }, 1357 { "subpass_input", 1u, SAMPLE_SOURCE_SUBPASS_INPUT }, 1358 }; 1359 1360 // Test 1: Compare fragments fetched via FMASK and an ordinary texel fetch 1361 { 1362 for (const VkSampleCountFlagBits* pSampleCount = sampleCounts; pSampleCount != DE_ARRAY_END(sampleCounts); ++pSampleCount) 1363 { 1364 MovePtr<tcu::TestCaseGroup> sampleCountGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), ("samples_" + de::toString(*pSampleCount)).c_str())); 1365 for (const SourceCase* pSourceCase = sourceCases; pSourceCase != DE_ARRAY_END(sourceCases); ++pSourceCase) 1366 { 1367 // Input attachments cannot be used with dynamic rendering. 1368 if (pSourceCase->sampleSource == SAMPLE_SOURCE_SUBPASS_INPUT && isConstructionTypeShaderObject(pipelineConstructionType)) 1369 continue; 1370 1371 MovePtr<tcu::TestCaseGroup> sourceGroup (new tcu::TestCaseGroup(rootGroup->getTestContext(), pSourceCase->name)); 1372 for (const VkFormat* pColorFormat = colorFormats; pColorFormat != DE_ARRAY_END(colorFormats); ++pColorFormat) 1373 { 1374 TestParams params; 1375 params.pipelineConstructionType = pipelineConstructionType; 1376 params.renderSize = UVec2(32, 32); 1377 params.colorFormat = *pColorFormat; 1378 params.numColorSamples = *pSampleCount; 1379 params.numLayers = pSourceCase->numLayers; 1380 params.sampleSource = pSourceCase->sampleSource; 1381 1382 addFunctionCaseWithPrograms(sourceGroup.get(), getFormatShortString(*pColorFormat), checkRequirements, initPrograms, test, params); 1383 } 1384 sampleCountGroup->addChild(sourceGroup.release()); 1385 } 1386 rootGroup->addChild(sampleCountGroup.release()); 1387 } 1388 } 1389} 1390 1391} // anonymous ns 1392 1393tcu::TestCaseGroup* createMultisampleShaderFragmentMaskTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType) 1394{ 1395 const auto cleanGroup = [](tcu::TestCaseGroup*, PipelineConstructionType) { SingletonDevice::destroy(); }; 1396 const char* groupName = "shader_fragment_mask"; 1397 1398 // Access raw texel values in a compressed MSAA surface 1399 return createTestGroup(testCtx, groupName, createShaderFragmentMaskTestsInGroup, pipelineConstructionType, cleanGroup); 1400} 1401 1402} // pipeline 1403} // vkt 1404