1 /*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2017 Google Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Tests for render passses with multisample attachments 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktRenderPassMultisampleTests.hpp" 25 26 #include "vktTestCaseUtil.hpp" 27 #include "vktTestGroupUtil.hpp" 28 29 #include "vkDefs.hpp" 30 #include "vkDeviceUtil.hpp" 31 #include "vkImageUtil.hpp" 32 #include "vkMemUtil.hpp" 33 #include "vkPlatform.hpp" 34 #include "vkPrograms.hpp" 35 #include "vkQueryUtil.hpp" 36 #include "vkRef.hpp" 37 #include "vkRefUtil.hpp" 38 #include "vkTypeUtil.hpp" 39 40 #include "tcuFloat.hpp" 41 #include "tcuImageCompare.hpp" 42 #include "tcuFormatUtil.hpp" 43 #include "tcuMaybe.hpp" 44 #include "tcuResultCollector.hpp" 45 #include "tcuTestLog.hpp" 46 #include "tcuTextureUtil.hpp" 47 #include "tcuVectorUtil.hpp" 48 49 #include "deUniquePtr.hpp" 50 #include "deSharedPtr.hpp" 51 52 using namespace vk; 53 54 using tcu::BVec4; 55 using tcu::IVec2; 56 using tcu::IVec4; 57 using tcu::UVec2; 58 using tcu::UVec4; 59 using tcu::Vec2; 60 using tcu::Vec4; 61 62 using tcu::Maybe; 63 using tcu::just; 64 using tcu::nothing; 65 66 using tcu::ConstPixelBufferAccess; 67 using tcu::PixelBufferAccess; 68 69 using tcu::TestLog; 70 71 using std::pair; 72 using std::string; 73 using std::vector; 74 75 typedef de::SharedPtr<vk::Unique<VkImage> > VkImageSp; 76 typedef de::SharedPtr<vk::Unique<VkImageView> > VkImageViewSp; 77 typedef de::SharedPtr<vk::Unique<VkBuffer> > VkBufferSp; 78 typedef de::SharedPtr<vk::Unique<VkPipeline> > VkPipelineSp; 79 80 namespace vkt 81 { 82 namespace 83 { 84 enum 85 { 86 MAX_COLOR_ATTACHMENT_COUNT = 4u 87 }; 88 89 template<typename T> 90 de::SharedPtr<T> safeSharedPtr (T* ptr) 91 { 92 try 93 { 94 return de::SharedPtr<T>(ptr); 95 } 96 catch (...) 97 { 98 delete ptr; 99 throw; 100 } 101 } 102 103 VkImageAspectFlags getImageAspectFlags (VkFormat vkFormat) 104 { 105 const tcu::TextureFormat format (mapVkFormat(vkFormat)); 106 const bool hasDepth (tcu::hasDepthComponent(format.order)); 107 const bool hasStencil (tcu::hasStencilComponent(format.order)); 108 109 if (hasDepth || hasStencil) 110 { 111 return (hasDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : (VkImageAspectFlagBits)0u) 112 | (hasStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : (VkImageAspectFlagBits)0u); 113 } 114 else 115 return VK_IMAGE_ASPECT_COLOR_BIT; 116 } 117 118 void bindBufferMemory (const DeviceInterface& vk, VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memOffset) 119 { 120 VK_CHECK(vk.bindBufferMemory(device, buffer, mem, memOffset)); 121 } 122 123 void bindImageMemory (const DeviceInterface& vk, VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memOffset) 124 { 125 VK_CHECK(vk.bindImageMemory(device, image, mem, memOffset)); 126 } 127 128 de::MovePtr<Allocation> createBufferMemory (const DeviceInterface& vk, 129 VkDevice device, 130 Allocator& allocator, 131 VkBuffer buffer) 132 { 133 de::MovePtr<Allocation> allocation (allocator.allocate(getBufferMemoryRequirements(vk, device, buffer), MemoryRequirement::HostVisible)); 134 bindBufferMemory(vk, device, buffer, allocation->getMemory(), allocation->getOffset()); 135 return allocation; 136 } 137 138 de::MovePtr<Allocation> createImageMemory (const DeviceInterface& vk, 139 VkDevice device, 140 Allocator& allocator, 141 VkImage image) 142 { 143 de::MovePtr<Allocation> allocation (allocator.allocate(getImageMemoryRequirements(vk, device, image), MemoryRequirement::Any)); 144 bindImageMemory(vk, device, image, allocation->getMemory(), allocation->getOffset()); 145 return allocation; 146 } 147 148 Move<VkImage> createImage (const DeviceInterface& vk, 149 VkDevice device, 150 VkImageCreateFlags flags, 151 VkImageType imageType, 152 VkFormat format, 153 VkExtent3D extent, 154 deUint32 mipLevels, 155 deUint32 arrayLayers, 156 VkSampleCountFlagBits samples, 157 VkImageTiling tiling, 158 VkImageUsageFlags usage, 159 VkSharingMode sharingMode, 160 deUint32 queueFamilyCount, 161 const deUint32* pQueueFamilyIndices, 162 VkImageLayout initialLayout) 163 { 164 const VkImageCreateInfo pCreateInfo = 165 { 166 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 167 DE_NULL, 168 flags, 169 imageType, 170 format, 171 extent, 172 mipLevels, 173 arrayLayers, 174 samples, 175 tiling, 176 usage, 177 sharingMode, 178 queueFamilyCount, 179 pQueueFamilyIndices, 180 initialLayout 181 }; 182 return createImage(vk, device, &pCreateInfo); 183 } 184 185 Move<VkImageView> createImageView (const DeviceInterface& vk, 186 VkDevice device, 187 VkImageViewCreateFlags flags, 188 VkImage image, 189 VkImageViewType viewType, 190 VkFormat format, 191 VkComponentMapping components, 192 VkImageSubresourceRange subresourceRange) 193 { 194 const VkImageViewCreateInfo pCreateInfo = 195 { 196 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 197 DE_NULL, 198 flags, 199 image, 200 viewType, 201 format, 202 components, 203 subresourceRange, 204 }; 205 return createImageView(vk, device, &pCreateInfo); 206 } 207 208 Move<VkImage> createImage (const InstanceInterface& vki, 209 VkPhysicalDevice physicalDevice, 210 const DeviceInterface& vkd, 211 VkDevice device, 212 VkFormat vkFormat, 213 VkSampleCountFlagBits sampleCountBit, 214 VkImageUsageFlags usage, 215 deUint32 width, 216 deUint32 height) 217 { 218 try 219 { 220 const tcu::TextureFormat format (mapVkFormat(vkFormat)); 221 const VkImageType imageType (VK_IMAGE_TYPE_2D); 222 const VkImageTiling imageTiling (VK_IMAGE_TILING_OPTIMAL); 223 const VkFormatProperties formatProperties (getPhysicalDeviceFormatProperties(vki, physicalDevice, vkFormat)); 224 const VkImageFormatProperties imageFormatProperties (getPhysicalDeviceImageFormatProperties(vki, physicalDevice, vkFormat, imageType, imageTiling, usage, 0u)); 225 const VkExtent3D imageExtent = 226 { 227 width, 228 height, 229 1u 230 }; 231 232 if ((tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order)) 233 && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0) 234 TCU_THROW(NotSupportedError, "Format can't be used as depth stencil attachment"); 235 236 if (!(tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order)) 237 && (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0) 238 TCU_THROW(NotSupportedError, "Format can't be used as color attachment"); 239 240 if (imageFormatProperties.maxExtent.width < imageExtent.width 241 || imageFormatProperties.maxExtent.height < imageExtent.height 242 || ((imageFormatProperties.sampleCounts & sampleCountBit) == 0)) 243 { 244 TCU_THROW(NotSupportedError, "Image type not supported"); 245 } 246 247 return createImage(vkd, device, 0u, imageType, vkFormat, imageExtent, 1u, 1u, sampleCountBit, imageTiling, usage, VK_SHARING_MODE_EXCLUSIVE, 0u, DE_NULL, VK_IMAGE_LAYOUT_UNDEFINED); 248 } 249 catch (const vk::Error& error) 250 { 251 if (error.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED) 252 TCU_THROW(NotSupportedError, "Image format not supported"); 253 254 throw; 255 } 256 } 257 258 Move<VkImageView> createImageAttachmentView (const DeviceInterface& vkd, 259 VkDevice device, 260 VkImage image, 261 VkFormat format, 262 VkImageAspectFlags aspect) 263 { 264 const VkImageSubresourceRange range = 265 { 266 aspect, 267 0u, 268 1u, 269 0u, 270 1u 271 }; 272 273 return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range); 274 } 275 276 Move<VkImageView> createSrcPrimaryInputImageView (const DeviceInterface& vkd, 277 VkDevice device, 278 VkImage image, 279 VkFormat format, 280 VkImageAspectFlags aspect) 281 { 282 const VkImageSubresourceRange range = 283 { 284 aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT) 285 ? (VkImageAspectFlags)VK_IMAGE_ASPECT_DEPTH_BIT 286 : aspect, 287 0u, 288 1u, 289 0u, 290 1u 291 }; 292 293 return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range); 294 } 295 296 Move<VkImageView> createSrcSecondaryInputImageView (const DeviceInterface& vkd, 297 VkDevice device, 298 VkImage image, 299 VkFormat format, 300 VkImageAspectFlags aspect) 301 { 302 if (aspect == (VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT)) 303 { 304 const VkImageSubresourceRange range = 305 { 306 VK_IMAGE_ASPECT_STENCIL_BIT, 307 0u, 308 1u, 309 0u, 310 1u 311 }; 312 313 return createImageView(vkd, device, 0u, image, VK_IMAGE_VIEW_TYPE_2D, format, makeComponentMappingRGBA(), range); 314 } 315 else 316 return Move<VkImageView>(); 317 } 318 319 VkDeviceSize getPixelSize (VkFormat vkFormat) 320 { 321 const tcu::TextureFormat format (mapVkFormat(vkFormat)); 322 323 return format.getPixelSize(); 324 } 325 326 Move<VkBuffer> createBuffer (const DeviceInterface& vkd, 327 VkDevice device, 328 VkFormat format, 329 deUint32 width, 330 deUint32 height) 331 { 332 const VkBufferUsageFlags bufferUsage (VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); 333 const VkDeviceSize pixelSize (getPixelSize(format)); 334 const VkBufferCreateInfo createInfo = 335 { 336 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, 337 DE_NULL, 338 0u, 339 340 width * height * pixelSize, 341 bufferUsage, 342 343 VK_SHARING_MODE_EXCLUSIVE, 344 0u, 345 DE_NULL 346 }; 347 return createBuffer(vkd, device, &createInfo); 348 } 349 350 VkSampleCountFlagBits sampleCountBitFromomSampleCount (deUint32 count) 351 { 352 switch (count) 353 { 354 case 1: return VK_SAMPLE_COUNT_1_BIT; 355 case 2: return VK_SAMPLE_COUNT_2_BIT; 356 case 4: return VK_SAMPLE_COUNT_4_BIT; 357 case 8: return VK_SAMPLE_COUNT_8_BIT; 358 case 16: return VK_SAMPLE_COUNT_16_BIT; 359 case 32: return VK_SAMPLE_COUNT_32_BIT; 360 case 64: return VK_SAMPLE_COUNT_64_BIT; 361 362 default: 363 DE_FATAL("Invalid sample count"); 364 return (VkSampleCountFlagBits)(0x1u << count); 365 } 366 } 367 368 std::vector<VkImageSp> createMultisampleImages (const InstanceInterface& vki, 369 VkPhysicalDevice physicalDevice, 370 const DeviceInterface& vkd, 371 VkDevice device, 372 VkFormat format, 373 deUint32 sampleCount, 374 deUint32 width, 375 deUint32 height) 376 { 377 std::vector<VkImageSp> images (sampleCount); 378 379 for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++) 380 images[imageNdx] = safeSharedPtr(new vk::Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, sampleCountBitFromomSampleCount(sampleCount), VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, width, height))); 381 382 return images; 383 } 384 385 std::vector<VkImageSp> createSingleSampleImages (const InstanceInterface& vki, 386 VkPhysicalDevice physicalDevice, 387 const DeviceInterface& vkd, 388 VkDevice device, 389 VkFormat format, 390 deUint32 sampleCount, 391 deUint32 width, 392 deUint32 height) 393 { 394 std::vector<VkImageSp> images (sampleCount); 395 396 for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++) 397 images[imageNdx] = safeSharedPtr(new vk::Unique<VkImage>(createImage(vki, physicalDevice, vkd, device, format, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, width, height))); 398 399 return images; 400 } 401 402 std::vector<de::SharedPtr<Allocation> > createImageMemory (const DeviceInterface& vkd, 403 VkDevice device, 404 Allocator& allocator, 405 const std::vector<VkImageSp> images) 406 { 407 std::vector<de::SharedPtr<Allocation> > memory (images.size()); 408 409 for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++) 410 memory[memoryNdx] = safeSharedPtr(createImageMemory(vkd, device, allocator, **images[memoryNdx]).release()); 411 412 return memory; 413 } 414 415 std::vector<VkImageViewSp> createImageAttachmentViews (const DeviceInterface& vkd, 416 VkDevice device, 417 const std::vector<VkImageSp>& images, 418 VkFormat format, 419 VkImageAspectFlagBits aspect) 420 { 421 std::vector<VkImageViewSp> views (images.size()); 422 423 for (size_t imageNdx = 0; imageNdx < images.size(); imageNdx++) 424 views[imageNdx] = safeSharedPtr(new vk::Unique<VkImageView>(createImageAttachmentView(vkd, device, **images[imageNdx], format, aspect))); 425 426 return views; 427 } 428 429 std::vector<VkBufferSp> createBuffers (const DeviceInterface& vkd, 430 VkDevice device, 431 VkFormat format, 432 deUint32 sampleCount, 433 deUint32 width, 434 deUint32 height) 435 { 436 std::vector<VkBufferSp> buffers (sampleCount); 437 438 for (size_t bufferNdx = 0; bufferNdx < buffers.size(); bufferNdx++) 439 buffers[bufferNdx] = safeSharedPtr(new vk::Unique<VkBuffer>(createBuffer(vkd, device, format, width, height))); 440 441 return buffers; 442 } 443 444 std::vector<de::SharedPtr<Allocation> > createBufferMemory (const DeviceInterface& vkd, 445 VkDevice device, 446 Allocator& allocator, 447 const std::vector<VkBufferSp> buffers) 448 { 449 std::vector<de::SharedPtr<Allocation> > memory (buffers.size()); 450 451 for (size_t memoryNdx = 0; memoryNdx < memory.size(); memoryNdx++) 452 memory[memoryNdx] = safeSharedPtr(createBufferMemory(vkd, device, allocator, **buffers[memoryNdx]).release()); 453 454 return memory; 455 } 456 457 Move<VkRenderPass> createRenderPass (const DeviceInterface& vkd, 458 VkDevice device, 459 VkFormat srcFormat, 460 VkFormat dstFormat, 461 deUint32 sampleCount) 462 { 463 const VkSampleCountFlagBits samples (sampleCountBitFromomSampleCount(sampleCount)); 464 const deUint32 splitSubpassCount (deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT)); 465 const tcu::TextureFormat format (mapVkFormat(srcFormat)); 466 const bool isDepthStencilFormat (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order)); 467 vector<VkSubpassDescription> subpasses; 468 vector<vector<VkAttachmentReference> > dstAttachmentRefs (splitSubpassCount); 469 vector<vector<VkAttachmentReference> > dstResolveAttachmentRefs (splitSubpassCount); 470 vector<VkAttachmentDescription> attachments; 471 vector<VkSubpassDependency> dependencies; 472 const VkAttachmentReference srcAttachmentRef = 473 { 474 0u, 475 isDepthStencilFormat 476 ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL 477 : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 478 }; 479 const VkAttachmentReference srcAttachmentInputRef = 480 { 481 0u, 482 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL 483 }; 484 485 { 486 const VkAttachmentDescription srcAttachment = 487 { 488 0u, 489 490 srcFormat, 491 samples, 492 493 VK_ATTACHMENT_LOAD_OP_DONT_CARE, 494 VK_ATTACHMENT_STORE_OP_DONT_CARE, 495 496 VK_ATTACHMENT_LOAD_OP_DONT_CARE, 497 VK_ATTACHMENT_STORE_OP_DONT_CARE, 498 499 VK_IMAGE_LAYOUT_UNDEFINED, 500 VK_IMAGE_LAYOUT_GENERAL 501 }; 502 503 attachments.push_back(srcAttachment); 504 } 505 506 for (deUint32 splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++) 507 { 508 for (deUint32 sampleNdx = 0; sampleNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount - splitSubpassIndex * MAX_COLOR_ATTACHMENT_COUNT); sampleNdx++) 509 { 510 // Multisample color attachment 511 { 512 const VkAttachmentDescription dstAttachment = 513 { 514 0u, 515 516 dstFormat, 517 samples, 518 519 VK_ATTACHMENT_LOAD_OP_DONT_CARE, 520 VK_ATTACHMENT_STORE_OP_DONT_CARE, 521 522 VK_ATTACHMENT_LOAD_OP_DONT_CARE, 523 VK_ATTACHMENT_STORE_OP_DONT_CARE, 524 525 VK_IMAGE_LAYOUT_UNDEFINED, 526 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 527 }; 528 const VkAttachmentReference dstAttachmentRef = 529 { 530 (deUint32)attachments.size(), 531 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 532 }; 533 534 attachments.push_back(dstAttachment); 535 dstAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef); 536 } 537 // Resolve attachment 538 { 539 const VkAttachmentDescription dstAttachment = 540 { 541 0u, 542 543 dstFormat, 544 VK_SAMPLE_COUNT_1_BIT, 545 546 VK_ATTACHMENT_LOAD_OP_DONT_CARE, 547 VK_ATTACHMENT_STORE_OP_STORE, 548 549 VK_ATTACHMENT_LOAD_OP_DONT_CARE, 550 VK_ATTACHMENT_STORE_OP_STORE, 551 552 VK_IMAGE_LAYOUT_UNDEFINED, 553 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL 554 }; 555 const VkAttachmentReference dstAttachmentRef = 556 { 557 (deUint32)attachments.size(), 558 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL 559 }; 560 561 attachments.push_back(dstAttachment); 562 dstResolveAttachmentRefs[splitSubpassIndex].push_back(dstAttachmentRef); 563 } 564 } 565 } 566 567 { 568 { 569 const VkSubpassDescription subpass = 570 { 571 (VkSubpassDescriptionFlags)0, 572 VK_PIPELINE_BIND_POINT_GRAPHICS, 573 574 0u, 575 DE_NULL, 576 577 isDepthStencilFormat ? 0u : 1u, 578 isDepthStencilFormat ? DE_NULL : &srcAttachmentRef, 579 DE_NULL, 580 581 isDepthStencilFormat ? &srcAttachmentRef : DE_NULL, 582 0u, 583 DE_NULL 584 }; 585 586 subpasses.push_back(subpass); 587 } 588 589 for (deUint32 splitSubpassIndex = 0; splitSubpassIndex < splitSubpassCount; splitSubpassIndex++) 590 { 591 { 592 const VkSubpassDescription subpass = 593 { 594 (VkSubpassDescriptionFlags)0, 595 VK_PIPELINE_BIND_POINT_GRAPHICS, 596 597 1u, 598 &srcAttachmentInputRef, 599 600 (deUint32)dstAttachmentRefs[splitSubpassIndex].size(), 601 &dstAttachmentRefs[splitSubpassIndex][0], 602 &dstResolveAttachmentRefs[splitSubpassIndex][0], 603 604 DE_NULL, 605 0u, 606 DE_NULL 607 }; 608 subpasses.push_back(subpass); 609 } 610 { 611 const VkSubpassDependency dependency = 612 { 613 0u, splitSubpassIndex + 1, 614 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 615 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 616 617 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, 618 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, 619 620 VK_DEPENDENCY_BY_REGION_BIT 621 }; 622 623 dependencies.push_back(dependency); 624 } 625 }; 626 const VkRenderPassCreateInfo createInfo = 627 { 628 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 629 DE_NULL, 630 (VkRenderPassCreateFlags)0u, 631 632 (deUint32)attachments.size(), 633 &attachments[0], 634 635 (deUint32)subpasses.size(), 636 &subpasses[0], 637 638 (deUint32)dependencies.size(), 639 &dependencies[0] 640 }; 641 642 return createRenderPass(vkd, device, &createInfo); 643 } 644 } 645 646 Move<VkFramebuffer> createFramebuffer (const DeviceInterface& vkd, 647 VkDevice device, 648 VkRenderPass renderPass, 649 VkImageView srcImageView, 650 const std::vector<VkImageViewSp>& dstMultisampleImageViews, 651 const std::vector<VkImageViewSp>& dstSinglesampleImageViews, 652 deUint32 width, 653 deUint32 height) 654 { 655 std::vector<VkImageView> attachments; 656 657 attachments.reserve(dstMultisampleImageViews.size() + dstSinglesampleImageViews.size() + 1u); 658 659 attachments.push_back(srcImageView); 660 661 DE_ASSERT(dstMultisampleImageViews.size() == dstSinglesampleImageViews.size()); 662 663 for (size_t ndx = 0; ndx < dstMultisampleImageViews.size(); ndx++) 664 { 665 attachments.push_back(**dstMultisampleImageViews[ndx]); 666 attachments.push_back(**dstSinglesampleImageViews[ndx]); 667 } 668 669 const VkFramebufferCreateInfo createInfo = 670 { 671 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 672 DE_NULL, 673 0u, 674 675 renderPass, 676 (deUint32)attachments.size(), 677 &attachments[0], 678 679 width, 680 height, 681 1u 682 }; 683 684 return createFramebuffer(vkd, device, &createInfo); 685 } 686 687 Move<VkPipelineLayout> createRenderPipelineLayout (const DeviceInterface& vkd, 688 VkDevice device) 689 { 690 const VkPushConstantRange pushConstant = 691 { 692 VK_SHADER_STAGE_FRAGMENT_BIT, 693 0u, 694 4u 695 }; 696 const VkPipelineLayoutCreateInfo createInfo = 697 { 698 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 699 DE_NULL, 700 (vk::VkPipelineLayoutCreateFlags)0, 701 702 0u, 703 DE_NULL, 704 705 1u, 706 &pushConstant 707 }; 708 709 return createPipelineLayout(vkd, device, &createInfo); 710 } 711 712 Move<VkPipeline> createRenderPipeline (const DeviceInterface& vkd, 713 VkDevice device, 714 VkRenderPass renderPass, 715 VkPipelineLayout pipelineLayout, 716 const vk::ProgramCollection<vk::ProgramBinary>& binaryCollection, 717 deUint32 width, 718 deUint32 height, 719 deUint32 sampleCount) 720 { 721 const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u)); 722 const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u)); 723 const VkSpecializationInfo emptyShaderSpecializations = 724 { 725 0u, 726 DE_NULL, 727 728 0u, 729 DE_NULL 730 }; 731 // Disable blending 732 const VkPipelineColorBlendAttachmentState attachmentBlendState = 733 { 734 VK_FALSE, 735 VK_BLEND_FACTOR_SRC_ALPHA, 736 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, 737 VK_BLEND_OP_ADD, 738 VK_BLEND_FACTOR_ONE, 739 VK_BLEND_FACTOR_ONE, 740 VK_BLEND_OP_ADD, 741 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT 742 }; 743 const VkPipelineShaderStageCreateInfo shaderStages[2] = 744 { 745 { 746 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 747 DE_NULL, 748 (VkPipelineShaderStageCreateFlags)0u, 749 VK_SHADER_STAGE_VERTEX_BIT, 750 *vertexShaderModule, 751 "main", 752 &emptyShaderSpecializations 753 }, 754 { 755 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 756 DE_NULL, 757 (VkPipelineShaderStageCreateFlags)0u, 758 VK_SHADER_STAGE_FRAGMENT_BIT, 759 *fragmentShaderModule, 760 "main", 761 &emptyShaderSpecializations 762 } 763 }; 764 const VkPipelineVertexInputStateCreateInfo vertexInputState = 765 { 766 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 767 DE_NULL, 768 (VkPipelineVertexInputStateCreateFlags)0u, 769 770 0u, 771 DE_NULL, 772 773 0u, 774 DE_NULL 775 }; 776 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = 777 { 778 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 779 DE_NULL, 780 781 (VkPipelineInputAssemblyStateCreateFlags)0u, 782 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 783 VK_FALSE 784 }; 785 const VkViewport viewport = 786 { 787 0.0f, 0.0f, 788 (float)width, (float)height, 789 790 0.0f, 1.0f 791 }; 792 const VkRect2D scissor = 793 { 794 { 0u, 0u }, 795 { width, height } 796 }; 797 const VkPipelineViewportStateCreateInfo viewportState = 798 { 799 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 800 DE_NULL, 801 (VkPipelineViewportStateCreateFlags)0u, 802 803 1u, 804 &viewport, 805 806 1u, 807 &scissor 808 }; 809 const VkPipelineRasterizationStateCreateInfo rasterState = 810 { 811 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 812 DE_NULL, 813 (VkPipelineRasterizationStateCreateFlags)0u, 814 VK_TRUE, 815 VK_FALSE, 816 VK_POLYGON_MODE_FILL, 817 VK_CULL_MODE_NONE, 818 VK_FRONT_FACE_COUNTER_CLOCKWISE, 819 VK_FALSE, 820 0.0f, 821 0.0f, 822 0.0f, 823 1.0f 824 }; 825 const VkPipelineMultisampleStateCreateInfo multisampleState = 826 { 827 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 828 DE_NULL, 829 (VkPipelineMultisampleStateCreateFlags)0u, 830 831 sampleCountBitFromomSampleCount(sampleCount), 832 VK_FALSE, 833 0.0f, 834 DE_NULL, 835 VK_FALSE, 836 VK_FALSE, 837 }; 838 const VkPipelineDepthStencilStateCreateInfo depthStencilState = 839 { 840 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 841 DE_NULL, 842 (VkPipelineDepthStencilStateCreateFlags)0u, 843 844 VK_TRUE, 845 VK_TRUE, 846 VK_COMPARE_OP_ALWAYS, 847 VK_FALSE, 848 VK_TRUE, 849 { 850 VK_STENCIL_OP_KEEP, 851 VK_STENCIL_OP_INCREMENT_AND_WRAP, 852 VK_STENCIL_OP_KEEP, 853 VK_COMPARE_OP_ALWAYS, 854 ~0u, 855 ~0u, 856 0xFFu / (sampleCount + 1) 857 }, 858 { 859 VK_STENCIL_OP_KEEP, 860 VK_STENCIL_OP_INCREMENT_AND_WRAP, 861 VK_STENCIL_OP_KEEP, 862 VK_COMPARE_OP_ALWAYS, 863 ~0u, 864 ~0u, 865 0xFFu / (sampleCount + 1) 866 }, 867 868 0.0f, 869 1.0f 870 }; 871 const VkPipelineColorBlendStateCreateInfo blendState = 872 { 873 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 874 DE_NULL, 875 (VkPipelineColorBlendStateCreateFlags)0u, 876 877 VK_FALSE, 878 VK_LOGIC_OP_COPY, 879 1u, 880 &attachmentBlendState, 881 { 0.0f, 0.0f, 0.0f, 0.0f } 882 }; 883 const VkGraphicsPipelineCreateInfo createInfo = 884 { 885 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 886 DE_NULL, 887 (VkPipelineCreateFlags)0u, 888 889 2, 890 shaderStages, 891 892 &vertexInputState, 893 &inputAssemblyState, 894 DE_NULL, 895 &viewportState, 896 &rasterState, 897 &multisampleState, 898 &depthStencilState, 899 &blendState, 900 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, 901 pipelineLayout, 902 903 renderPass, 904 0u, 905 DE_NULL, 906 0u 907 }; 908 909 return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo); 910 } 911 912 Move<VkDescriptorSetLayout> createSplitDescriptorSetLayout (const DeviceInterface& vkd, 913 VkDevice device, 914 VkFormat vkFormat) 915 { 916 const tcu::TextureFormat format (mapVkFormat(vkFormat)); 917 const bool hasDepth (tcu::hasDepthComponent(format.order)); 918 const bool hasStencil (tcu::hasStencilComponent(format.order)); 919 const VkDescriptorSetLayoutBinding bindings[] = 920 { 921 { 922 0u, 923 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 924 1u, 925 VK_SHADER_STAGE_FRAGMENT_BIT, 926 DE_NULL 927 }, 928 { 929 1u, 930 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 931 1u, 932 VK_SHADER_STAGE_FRAGMENT_BIT, 933 DE_NULL 934 } 935 }; 936 const VkDescriptorSetLayoutCreateInfo createInfo = 937 { 938 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 939 DE_NULL, 940 0u, 941 942 hasDepth && hasStencil ? 2u : 1u, 943 bindings 944 }; 945 946 return createDescriptorSetLayout(vkd, device, &createInfo); 947 } 948 949 Move<VkPipelineLayout> createSplitPipelineLayout (const DeviceInterface& vkd, 950 VkDevice device, 951 VkDescriptorSetLayout descriptorSetLayout) 952 { 953 const VkPushConstantRange pushConstant = 954 { 955 VK_SHADER_STAGE_FRAGMENT_BIT, 956 0u, 957 4u 958 }; 959 const VkPipelineLayoutCreateInfo createInfo = 960 { 961 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 962 DE_NULL, 963 (vk::VkPipelineLayoutCreateFlags)0, 964 965 1u, 966 &descriptorSetLayout, 967 968 1u, 969 &pushConstant 970 }; 971 972 return createPipelineLayout(vkd, device, &createInfo); 973 } 974 975 Move<VkPipeline> createSplitPipeline (const DeviceInterface& vkd, 976 VkDevice device, 977 VkRenderPass renderPass, 978 deUint32 subpassIndex, 979 VkPipelineLayout pipelineLayout, 980 const vk::ProgramCollection<vk::ProgramBinary>& binaryCollection, 981 deUint32 width, 982 deUint32 height, 983 deUint32 sampleCount) 984 { 985 const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u)); 986 const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-split-frag"), 0u)); 987 const VkSpecializationInfo emptyShaderSpecializations = 988 { 989 0u, 990 DE_NULL, 991 992 0u, 993 DE_NULL 994 }; 995 // Disable blending 996 const VkPipelineColorBlendAttachmentState attachmentBlendState = 997 { 998 VK_FALSE, 999 VK_BLEND_FACTOR_SRC_ALPHA, 1000 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, 1001 VK_BLEND_OP_ADD, 1002 VK_BLEND_FACTOR_ONE, 1003 VK_BLEND_FACTOR_ONE, 1004 VK_BLEND_OP_ADD, 1005 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT 1006 }; 1007 const std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates (de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount), attachmentBlendState); 1008 const VkPipelineShaderStageCreateInfo shaderStages[2] = 1009 { 1010 { 1011 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 1012 DE_NULL, 1013 (VkPipelineShaderStageCreateFlags)0u, 1014 VK_SHADER_STAGE_VERTEX_BIT, 1015 *vertexShaderModule, 1016 "main", 1017 &emptyShaderSpecializations 1018 }, 1019 { 1020 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 1021 DE_NULL, 1022 (VkPipelineShaderStageCreateFlags)0u, 1023 VK_SHADER_STAGE_FRAGMENT_BIT, 1024 *fragmentShaderModule, 1025 "main", 1026 &emptyShaderSpecializations 1027 } 1028 }; 1029 const VkPipelineVertexInputStateCreateInfo vertexInputState = 1030 { 1031 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 1032 DE_NULL, 1033 (VkPipelineVertexInputStateCreateFlags)0u, 1034 1035 0u, 1036 DE_NULL, 1037 1038 0u, 1039 DE_NULL 1040 }; 1041 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = 1042 { 1043 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 1044 DE_NULL, 1045 1046 (VkPipelineInputAssemblyStateCreateFlags)0u, 1047 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1048 VK_FALSE 1049 }; 1050 const VkViewport viewport = 1051 { 1052 0.0f, 0.0f, 1053 (float)width, (float)height, 1054 1055 0.0f, 1.0f 1056 }; 1057 const VkRect2D scissor = 1058 { 1059 { 0u, 0u }, 1060 { width, height } 1061 }; 1062 const VkPipelineViewportStateCreateInfo viewportState = 1063 { 1064 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 1065 DE_NULL, 1066 (VkPipelineViewportStateCreateFlags)0u, 1067 1068 1u, 1069 &viewport, 1070 1071 1u, 1072 &scissor 1073 }; 1074 const VkPipelineRasterizationStateCreateInfo rasterState = 1075 { 1076 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 1077 DE_NULL, 1078 (VkPipelineRasterizationStateCreateFlags)0u, 1079 VK_TRUE, 1080 VK_FALSE, 1081 VK_POLYGON_MODE_FILL, 1082 VK_CULL_MODE_NONE, 1083 VK_FRONT_FACE_COUNTER_CLOCKWISE, 1084 VK_FALSE, 1085 0.0f, 1086 0.0f, 1087 0.0f, 1088 1.0f 1089 }; 1090 const VkPipelineMultisampleStateCreateInfo multisampleState = 1091 { 1092 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 1093 DE_NULL, 1094 (VkPipelineMultisampleStateCreateFlags)0u, 1095 1096 sampleCountBitFromomSampleCount(sampleCount), 1097 VK_FALSE, 1098 0.0f, 1099 DE_NULL, 1100 VK_FALSE, 1101 VK_FALSE, 1102 }; 1103 const VkPipelineDepthStencilStateCreateInfo depthStencilState = 1104 { 1105 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 1106 DE_NULL, 1107 (VkPipelineDepthStencilStateCreateFlags)0u, 1108 1109 VK_FALSE, 1110 VK_FALSE, 1111 VK_COMPARE_OP_ALWAYS, 1112 VK_FALSE, 1113 VK_FALSE, 1114 { 1115 VK_STENCIL_OP_REPLACE, 1116 VK_STENCIL_OP_REPLACE, 1117 VK_STENCIL_OP_REPLACE, 1118 VK_COMPARE_OP_ALWAYS, 1119 ~0u, 1120 ~0u, 1121 0x0u 1122 }, 1123 { 1124 VK_STENCIL_OP_REPLACE, 1125 VK_STENCIL_OP_REPLACE, 1126 VK_STENCIL_OP_REPLACE, 1127 VK_COMPARE_OP_ALWAYS, 1128 ~0u, 1129 ~0u, 1130 0x0u 1131 }, 1132 1133 0.0f, 1134 1.0f 1135 }; 1136 const VkPipelineColorBlendStateCreateInfo blendState = 1137 { 1138 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 1139 DE_NULL, 1140 (VkPipelineColorBlendStateCreateFlags)0u, 1141 1142 VK_FALSE, 1143 VK_LOGIC_OP_COPY, 1144 1145 (deUint32)attachmentBlendStates.size(), 1146 &attachmentBlendStates[0], 1147 1148 { 0.0f, 0.0f, 0.0f, 0.0f } 1149 }; 1150 const VkGraphicsPipelineCreateInfo createInfo = 1151 { 1152 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 1153 DE_NULL, 1154 (VkPipelineCreateFlags)0u, 1155 1156 2, 1157 shaderStages, 1158 1159 &vertexInputState, 1160 &inputAssemblyState, 1161 DE_NULL, 1162 &viewportState, 1163 &rasterState, 1164 &multisampleState, 1165 &depthStencilState, 1166 &blendState, 1167 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, 1168 pipelineLayout, 1169 1170 renderPass, 1171 subpassIndex, 1172 DE_NULL, 1173 0u 1174 }; 1175 1176 return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo); 1177 } 1178 1179 vector<VkPipeline> createSplitPipelines (const DeviceInterface& vkd, 1180 VkDevice device, 1181 VkRenderPass renderPass, 1182 VkPipelineLayout pipelineLayout, 1183 const vk::ProgramCollection<vk::ProgramBinary>& binaryCollection, 1184 deUint32 width, 1185 deUint32 height, 1186 deUint32 sampleCount) 1187 { 1188 vector<VkPipeline> pipelines (deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT), (VkPipeline)0u); 1189 1190 try 1191 { 1192 for (size_t ndx = 0; ndx < pipelines.size(); ndx++) 1193 pipelines[ndx] = createSplitPipeline(vkd, device, renderPass, (deUint32)(ndx + 1), pipelineLayout, binaryCollection, width, height, sampleCount).disown(); 1194 } 1195 catch (...) 1196 { 1197 for (size_t ndx = 0; ndx < pipelines.size(); ndx++) 1198 vkd.destroyPipeline(device, pipelines[ndx], DE_NULL); 1199 1200 throw; 1201 } 1202 1203 return pipelines; 1204 } 1205 1206 Move<VkDescriptorPool> createSplitDescriptorPool (const DeviceInterface& vkd, 1207 VkDevice device) 1208 { 1209 const VkDescriptorPoolSize size = 1210 { 1211 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2u 1212 }; 1213 const VkDescriptorPoolCreateInfo createInfo = 1214 { 1215 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 1216 DE_NULL, 1217 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1218 1219 1220 2u, 1221 1u, 1222 &size 1223 }; 1224 1225 return createDescriptorPool(vkd, device, &createInfo); 1226 } 1227 1228 Move<VkDescriptorSet> createSplitDescriptorSet (const DeviceInterface& vkd, 1229 VkDevice device, 1230 VkDescriptorPool pool, 1231 VkDescriptorSetLayout layout, 1232 VkImageView primaryImageView, 1233 VkImageView secondaryImageView) 1234 { 1235 const VkDescriptorSetAllocateInfo allocateInfo = 1236 { 1237 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 1238 DE_NULL, 1239 1240 pool, 1241 1u, 1242 &layout 1243 }; 1244 Move<VkDescriptorSet> set (allocateDescriptorSet(vkd, device, &allocateInfo)); 1245 1246 { 1247 const VkDescriptorImageInfo imageInfos[] = 1248 { 1249 { 1250 (VkSampler)0u, 1251 primaryImageView, 1252 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL 1253 }, 1254 { 1255 (VkSampler)0u, 1256 secondaryImageView, 1257 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL 1258 } 1259 }; 1260 const VkWriteDescriptorSet writes[] = 1261 { 1262 { 1263 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 1264 DE_NULL, 1265 1266 *set, 1267 0u, 1268 0u, 1269 1u, 1270 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1271 &imageInfos[0], 1272 DE_NULL, 1273 DE_NULL 1274 }, 1275 { 1276 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 1277 DE_NULL, 1278 1279 *set, 1280 1u, 1281 0u, 1282 1u, 1283 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1284 &imageInfos[1], 1285 DE_NULL, 1286 DE_NULL 1287 } 1288 }; 1289 const deUint32 count = secondaryImageView != (VkImageView)0 1290 ? 2u 1291 : 1u; 1292 1293 vkd.updateDescriptorSets(device, count, writes, 0u, DE_NULL); 1294 } 1295 return set; 1296 } 1297 1298 struct TestConfig 1299 { 1300 TestConfig (VkFormat format_, 1301 deUint32 sampleCount_) 1302 : format (format_) 1303 , sampleCount (sampleCount_) 1304 { 1305 } 1306 1307 VkFormat format; 1308 deUint32 sampleCount; 1309 }; 1310 1311 VkImageUsageFlags getSrcImageUsage (VkFormat vkFormat) 1312 { 1313 const tcu::TextureFormat format (mapVkFormat(vkFormat)); 1314 const bool hasDepth (tcu::hasDepthComponent(format.order)); 1315 const bool hasStencil (tcu::hasStencilComponent(format.order)); 1316 1317 if (hasDepth || hasStencil) 1318 return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 1319 else 1320 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 1321 } 1322 1323 VkFormat getDstFormat (VkFormat vkFormat) 1324 { 1325 const tcu::TextureFormat format (mapVkFormat(vkFormat)); 1326 const bool hasDepth (tcu::hasDepthComponent(format.order)); 1327 const bool hasStencil (tcu::hasStencilComponent(format.order)); 1328 1329 if (hasDepth && hasStencil) 1330 return VK_FORMAT_R32G32_SFLOAT; 1331 else if (hasDepth || hasStencil) 1332 return VK_FORMAT_R32_SFLOAT; 1333 else 1334 return vkFormat; 1335 } 1336 1337 1338 class MultisampleRenderPassTestInstance : public TestInstance 1339 { 1340 public: 1341 MultisampleRenderPassTestInstance (Context& context, TestConfig config); 1342 ~MultisampleRenderPassTestInstance (void); 1343 1344 tcu::TestStatus iterate (void); 1345 1346 private: 1347 const VkFormat m_srcFormat; 1348 const VkFormat m_dstFormat; 1349 const deUint32 m_sampleCount; 1350 const deUint32 m_width; 1351 const deUint32 m_height; 1352 1353 const VkImageAspectFlags m_srcImageAspect; 1354 const VkImageUsageFlags m_srcImageUsage; 1355 const Unique<VkImage> m_srcImage; 1356 const de::UniquePtr<Allocation> m_srcImageMemory; 1357 const Unique<VkImageView> m_srcImageView; 1358 const Unique<VkImageView> m_srcPrimaryInputImageView; 1359 const Unique<VkImageView> m_srcSecondaryInputImageView; 1360 1361 const std::vector<VkImageSp> m_dstMultisampleImages; 1362 const std::vector<de::SharedPtr<Allocation> > m_dstMultisampleImageMemory; 1363 const std::vector<VkImageViewSp> m_dstMultisampleImageViews; 1364 1365 const std::vector<VkImageSp> m_dstSinglesampleImages; 1366 const std::vector<de::SharedPtr<Allocation> > m_dstSinglesampleImageMemory; 1367 const std::vector<VkImageViewSp> m_dstSinglesampleImageViews; 1368 1369 const std::vector<VkBufferSp> m_dstBuffers; 1370 const std::vector<de::SharedPtr<Allocation> > m_dstBufferMemory; 1371 1372 const Unique<VkRenderPass> m_renderPass; 1373 const Unique<VkFramebuffer> m_framebuffer; 1374 1375 const Unique<VkPipelineLayout> m_renderPipelineLayout; 1376 const Unique<VkPipeline> m_renderPipeline; 1377 1378 const Unique<VkDescriptorSetLayout> m_splitDescriptorSetLayout; 1379 const Unique<VkPipelineLayout> m_splitPipelineLayout; 1380 const vector<VkPipeline> m_splitPipelines; 1381 const Unique<VkDescriptorPool> m_splitDescriptorPool; 1382 const Unique<VkDescriptorSet> m_splitDescriptorSet; 1383 1384 const Unique<VkCommandPool> m_commandPool; 1385 tcu::ResultCollector m_resultCollector; 1386 }; 1387 1388 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config) 1389 : TestInstance (context) 1390 , m_srcFormat (config.format) 1391 , m_dstFormat (getDstFormat(config.format)) 1392 , m_sampleCount (config.sampleCount) 1393 , m_width (32u) 1394 , m_height (32u) 1395 1396 , m_srcImageAspect (getImageAspectFlags(m_srcFormat)) 1397 , m_srcImageUsage (getSrcImageUsage(m_srcFormat)) 1398 , m_srcImage (createImage(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_srcFormat, sampleCountBitFromomSampleCount(m_sampleCount), m_srcImageUsage, m_width, m_height)) 1399 , m_srcImageMemory (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), *m_srcImage)) 1400 , m_srcImageView (createImageAttachmentView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect)) 1401 , m_srcPrimaryInputImageView (createSrcPrimaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect)) 1402 , m_srcSecondaryInputImageView (createSrcSecondaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect)) 1403 1404 , m_dstMultisampleImages (createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height)) 1405 , m_dstMultisampleImageMemory (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstMultisampleImages)) 1406 , m_dstMultisampleImageViews (createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstMultisampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT)) 1407 1408 , m_dstSinglesampleImages (createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height)) 1409 , m_dstSinglesampleImageMemory (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstSinglesampleImages)) 1410 , m_dstSinglesampleImageViews (createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstSinglesampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT)) 1411 1412 , m_dstBuffers (createBuffers(context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height)) 1413 , m_dstBufferMemory (createBufferMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstBuffers)) 1414 1415 , m_renderPass (createRenderPass(context.getDeviceInterface(), context.getDevice(), m_srcFormat, m_dstFormat, m_sampleCount)) 1416 , m_framebuffer (createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_srcImageView, m_dstMultisampleImageViews, m_dstSinglesampleImageViews, m_width, m_height)) 1417 1418 , m_renderPipelineLayout (createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice())) 1419 , m_renderPipeline (createRenderPipeline(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount)) 1420 1421 , m_splitDescriptorSetLayout (createSplitDescriptorSetLayout(context.getDeviceInterface(), context.getDevice(), m_srcFormat)) 1422 , m_splitPipelineLayout (createSplitPipelineLayout(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorSetLayout)) 1423 , m_splitPipelines (createSplitPipelines(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_splitPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount)) 1424 , m_splitDescriptorPool (createSplitDescriptorPool(context.getDeviceInterface(), context.getDevice())) 1425 , m_splitDescriptorSet (createSplitDescriptorSet(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorPool, *m_splitDescriptorSetLayout, *m_srcPrimaryInputImageView, *m_srcSecondaryInputImageView)) 1426 , m_commandPool (createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex())) 1427 { 1428 } 1429 1430 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void) 1431 { 1432 } 1433 1434 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void) 1435 { 1436 const DeviceInterface& vkd (m_context.getDeviceInterface()); 1437 const VkDevice device (m_context.getDevice()); 1438 const Unique<VkCommandBuffer> commandBuffer (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 1439 1440 { 1441 const VkCommandBufferBeginInfo beginInfo = 1442 { 1443 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 1444 DE_NULL, 1445 1446 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 1447 DE_NULL 1448 }; 1449 1450 VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo)); 1451 } 1452 1453 { 1454 const VkRenderPassBeginInfo beginInfo = 1455 { 1456 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 1457 DE_NULL, 1458 1459 *m_renderPass, 1460 *m_framebuffer, 1461 1462 { 1463 { 0u, 0u }, 1464 { m_width, m_height } 1465 }, 1466 1467 0u, 1468 DE_NULL 1469 }; 1470 vkd.cmdBeginRenderPass(*commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE); 1471 } 1472 1473 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline); 1474 1475 for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++) 1476 { 1477 vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(sampleNdx), &sampleNdx); 1478 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u); 1479 } 1480 1481 for (deUint32 splitPipelineNdx = 0; splitPipelineNdx < m_splitPipelines.size(); splitPipelineNdx++) 1482 { 1483 vkd.cmdNextSubpass(*commandBuffer, VK_SUBPASS_CONTENTS_INLINE); 1484 1485 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, m_splitPipelines[splitPipelineNdx]); 1486 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_splitPipelineLayout, 0u, 1u, &*m_splitDescriptorSet, 0u, DE_NULL); 1487 vkd.cmdPushConstants(*commandBuffer, *m_splitPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(splitPipelineNdx), &splitPipelineNdx); 1488 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u); 1489 } 1490 1491 vkd.cmdEndRenderPass(*commandBuffer); 1492 1493 // Memory barriers between rendering and copies 1494 { 1495 std::vector<VkImageMemoryBarrier> barriers; 1496 1497 for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++) 1498 { 1499 const VkImageMemoryBarrier barrier = 1500 { 1501 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 1502 DE_NULL, 1503 1504 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 1505 VK_ACCESS_TRANSFER_READ_BIT, 1506 1507 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1508 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1509 1510 VK_QUEUE_FAMILY_IGNORED, 1511 VK_QUEUE_FAMILY_IGNORED, 1512 1513 **m_dstSinglesampleImages[dstNdx], 1514 { 1515 VK_IMAGE_ASPECT_COLOR_BIT, 1516 0u, 1517 1u, 1518 0u, 1519 1u 1520 } 1521 }; 1522 1523 barriers.push_back(barrier); 1524 } 1525 1526 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0]); 1527 } 1528 1529 // Copy image memory to buffers 1530 for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++) 1531 { 1532 const VkBufferImageCopy region = 1533 { 1534 0u, 1535 0u, 1536 0u, 1537 { 1538 VK_IMAGE_ASPECT_COLOR_BIT, 1539 0u, 1540 0u, 1541 1u, 1542 }, 1543 { 0u, 0u, 0u }, 1544 { m_width, m_height, 1u } 1545 }; 1546 1547 vkd.cmdCopyImageToBuffer(*commandBuffer, **m_dstSinglesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_dstBuffers[dstNdx], 1u, ®ion); 1548 } 1549 1550 // Memory barriers between copies and host access 1551 { 1552 std::vector<VkBufferMemoryBarrier> barriers; 1553 1554 for (size_t dstNdx = 0; dstNdx < m_dstBuffers.size(); dstNdx++) 1555 { 1556 const VkBufferMemoryBarrier barrier = 1557 { 1558 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 1559 DE_NULL, 1560 1561 VK_ACCESS_TRANSFER_WRITE_BIT, 1562 VK_ACCESS_HOST_READ_BIT, 1563 1564 VK_QUEUE_FAMILY_IGNORED, 1565 VK_QUEUE_FAMILY_IGNORED, 1566 1567 **m_dstBuffers[dstNdx], 1568 0u, 1569 VK_WHOLE_SIZE 1570 }; 1571 1572 barriers.push_back(barrier); 1573 } 1574 1575 vkd.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, (deUint32)barriers.size(), &barriers[0], 0u, DE_NULL); 1576 } 1577 1578 VK_CHECK(vkd.endCommandBuffer(*commandBuffer)); 1579 1580 { 1581 const VkSubmitInfo submitInfo = 1582 { 1583 VK_STRUCTURE_TYPE_SUBMIT_INFO, 1584 DE_NULL, 1585 1586 0u, 1587 DE_NULL, 1588 DE_NULL, 1589 1590 1u, 1591 &*commandBuffer, 1592 1593 0u, 1594 DE_NULL 1595 }; 1596 1597 VK_CHECK(vkd.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, (VkFence)0u)); 1598 1599 VK_CHECK(vkd.queueWaitIdle(m_context.getUniversalQueue())); 1600 } 1601 1602 { 1603 const tcu::TextureFormat format (mapVkFormat(m_dstFormat)); 1604 const tcu::TextureFormat srcFormat (mapVkFormat(m_srcFormat)); 1605 const bool hasDepth (tcu::hasDepthComponent(srcFormat.order)); 1606 const bool hasStencil (tcu::hasStencilComponent(srcFormat.order)); 1607 1608 for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++) 1609 { 1610 const std::string name ("Sample" + de::toString(sampleNdx)); 1611 const void* const ptr (m_dstBufferMemory[sampleNdx]->getHostPtr()); 1612 const tcu::ConstPixelBufferAccess access (format, m_width, m_height, 1, ptr); 1613 tcu::TextureLevel reference (format, m_width, m_height); 1614 1615 if (hasDepth || hasStencil) 1616 { 1617 if (hasDepth) 1618 { 1619 for (deUint32 y = 0; y < m_height; y++) 1620 for (deUint32 x = 0; x < m_width; x++) 1621 { 1622 const deUint32 x1 = x ^ sampleNdx; 1623 const deUint32 y1 = y ^ sampleNdx; 1624 const float range = 1.0f; 1625 float depth = 0.0f; 1626 deUint32 divider = 2; 1627 1628 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1629 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++) 1630 { 1631 depth += (range / (float)divider) 1632 * (((bitNdx % 2 == 0 ? x1 : y1) & (0x1u << (bitNdx / 2u))) == 0u ? 0u : 1u); 1633 divider *= 2; 1634 } 1635 1636 reference.getAccess().setPixel(Vec4(depth, 0.0f, 0.0f, 0.0f), x, y); 1637 } 1638 } 1639 if (hasStencil) 1640 { 1641 for (deUint32 y = 0; y < m_height; y++) 1642 for (deUint32 x = 0; x < m_width; x++) 1643 { 1644 const deUint32 stencil = sampleNdx + 1u; 1645 1646 if (hasDepth) 1647 { 1648 const Vec4 src (reference.getAccess().getPixel(x, y)); 1649 1650 reference.getAccess().setPixel(Vec4(src.x(), (float)stencil, 0.0f, 0.0f), x, y); 1651 } 1652 else 1653 reference.getAccess().setPixel(Vec4((float)stencil, 0.0f, 0.0f, 0.0f), x, y); 1654 } 1655 } 1656 { 1657 const Vec4 threshold (hasDepth ? (1.0f / 1024.0f) : 0.0f, 0.0f, 0.0f, 0.0f); 1658 1659 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR)) 1660 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx)); 1661 } 1662 } 1663 else 1664 { 1665 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type)); 1666 1667 switch (channelClass) 1668 { 1669 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 1670 { 1671 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>()); 1672 const UVec4 minValue (0); 1673 const UVec4 range (UVec4(1u) << tcu::min(bits, UVec4(31))); 1674 const int componentCount (tcu::getNumUsedChannels(format.order)); 1675 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 1676 1677 for (deUint32 y = 0; y < m_height; y++) 1678 for (deUint32 x = 0; x < m_width; x++) 1679 { 1680 const deUint32 x1 = x ^ sampleNdx; 1681 const deUint32 y1 = y ^ sampleNdx; 1682 UVec4 color (minValue); 1683 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 1684 deUint32 nextSrcBit = 0; 1685 deUint32 divider = 2; 1686 1687 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1688 while (nextSrcBit < de::min(bitSize, 10u)) 1689 { 1690 for (int compNdx = 0; compNdx < componentCount; compNdx++) 1691 { 1692 if (dstBitsUsed[compNdx] > bits[compNdx]) 1693 continue; 1694 1695 color[compNdx] += (range[compNdx] / divider) 1696 * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u); 1697 1698 nextSrcBit++; 1699 dstBitsUsed[compNdx]++; 1700 } 1701 1702 divider *= 2; 1703 } 1704 1705 reference.getAccess().setPixel(color, x, y); 1706 } 1707 1708 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR)) 1709 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx)); 1710 1711 break; 1712 } 1713 1714 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 1715 { 1716 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>()); 1717 const IVec4 minValue (0); 1718 const IVec4 range ((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>()); 1719 const int componentCount (tcu::getNumUsedChannels(format.order)); 1720 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 1721 1722 for (deUint32 y = 0; y < m_height; y++) 1723 for (deUint32 x = 0; x < m_width; x++) 1724 { 1725 const deUint32 x1 = x ^ sampleNdx; 1726 const deUint32 y1 = y ^ sampleNdx; 1727 IVec4 color (minValue); 1728 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 1729 deUint32 nextSrcBit = 0; 1730 deUint32 divider = 2; 1731 1732 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1733 while (nextSrcBit < de::min(bitSize, 10u)) 1734 { 1735 for (int compNdx = 0; compNdx < componentCount; compNdx++) 1736 { 1737 if (dstBitsUsed[compNdx] > bits[compNdx]) 1738 continue; 1739 1740 color[compNdx] += (range[compNdx] / divider) 1741 * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u); 1742 1743 nextSrcBit++; 1744 dstBitsUsed[compNdx]++; 1745 } 1746 1747 divider *= 2; 1748 } 1749 1750 reference.getAccess().setPixel(color, x, y); 1751 } 1752 1753 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR)) 1754 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx)); 1755 1756 break; 1757 } 1758 1759 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 1760 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 1761 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 1762 { 1763 const tcu::TextureFormatInfo info (tcu::getTextureFormatInfo(format)); 1764 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>()); 1765 const Vec4 minLimit (-65536.0); 1766 const Vec4 maxLimit (65536.0); 1767 const Vec4 minValue (tcu::max(info.valueMin, minLimit)); 1768 const Vec4 range (tcu::min(info.valueMax, maxLimit) - minValue); 1769 const int componentCount (tcu::getNumUsedChannels(format.order)); 1770 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 1771 1772 for (deUint32 y = 0; y < m_height; y++) 1773 for (deUint32 x = 0; x < m_width; x++) 1774 { 1775 const deUint32 x1 = x ^ sampleNdx; 1776 const deUint32 y1 = y ^ sampleNdx; 1777 Vec4 color (minValue); 1778 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 1779 deUint32 nextSrcBit = 0; 1780 deUint32 divider = 2; 1781 1782 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1783 while (nextSrcBit < de::min(bitSize, 10u)) 1784 { 1785 for (int compNdx = 0; compNdx < componentCount; compNdx++) 1786 { 1787 if (dstBitsUsed[compNdx] > bits[compNdx]) 1788 continue; 1789 1790 color[compNdx] += (range[compNdx] / (float)divider) 1791 * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u); 1792 1793 nextSrcBit++; 1794 dstBitsUsed[compNdx]++; 1795 } 1796 1797 divider *= 2; 1798 } 1799 1800 if (tcu::isSRGB(format)) 1801 reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y); 1802 else 1803 reference.getAccess().setPixel(color, x, y); 1804 } 1805 1806 if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT) 1807 { 1808 // Convert target format ulps to float ulps and allow 64ulp differences 1809 const UVec4 threshold (64u * (UVec4(1u) << (UVec4(23) - tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()))); 1810 1811 if (!tcu::floatUlpThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR)) 1812 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx)); 1813 } 1814 else 1815 { 1816 // Allow error of 4 times the minimum presentable difference 1817 const Vec4 threshold (4.0f * 1.0f / ((UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()) - 1u).cast<float>()); 1818 1819 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR)) 1820 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx)); 1821 } 1822 1823 break; 1824 } 1825 1826 default: 1827 DE_FATAL("Unknown channel class"); 1828 } 1829 } 1830 } 1831 } 1832 1833 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage()); 1834 } 1835 1836 struct Programs 1837 { 1838 void init (vk::SourceCollections& dst, TestConfig config) const 1839 { 1840 const tcu::TextureFormat format (mapVkFormat(config.format)); 1841 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type)); 1842 1843 dst.glslSources.add("quad-vert") << glu::VertexSource( 1844 "#version 450\n" 1845 "out gl_PerVertex {\n" 1846 "\tvec4 gl_Position;\n" 1847 "};\n" 1848 "highp float;\n" 1849 "void main (void) {\n" 1850 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n" 1851 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n" 1852 "}\n"); 1853 1854 if (tcu::hasDepthComponent(format.order)) 1855 { 1856 const Vec4 minValue (0.0f); 1857 const Vec4 range (1.0f); 1858 std::ostringstream fragmentShader; 1859 1860 fragmentShader << 1861 "#version 450\n" 1862 "layout(push_constant) uniform PushConstant {\n" 1863 "\thighp uint sampleIndex;\n" 1864 "} pushConstants;\n" 1865 "void main (void)\n" 1866 "{\n" 1867 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n" 1868 "\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n" 1869 "\thighp float depth;\n" 1870 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n" 1871 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n"; 1872 1873 fragmentShader << "\tdepth = " << minValue[0] << ";\n"; 1874 1875 { 1876 deUint32 divider = 2; 1877 1878 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1879 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++) 1880 { 1881 fragmentShader << 1882 "\tdepth += " << (range[0] / (float)divider) 1883 << " * float(bitfieldExtract(" << (bitNdx % 2 == 0 ? "x" : "y") << ", " << (bitNdx / 2) << ", 1));\n"; 1884 1885 divider *= 2; 1886 } 1887 } 1888 1889 fragmentShader << 1890 "\tgl_FragDepth = depth;\n" 1891 "}\n"; 1892 1893 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str()); 1894 } 1895 else if (tcu::hasStencilComponent(format.order)) 1896 { 1897 dst.glslSources.add("quad-frag") << glu::FragmentSource( 1898 "#version 450\n" 1899 "layout(push_constant) uniform PushConstant {\n" 1900 "\thighp uint sampleIndex;\n" 1901 "} pushConstants;\n" 1902 "void main (void)\n" 1903 "{\n" 1904 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n" 1905 "\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n" 1906 "}\n"); 1907 } 1908 else 1909 { 1910 switch (channelClass) 1911 { 1912 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 1913 { 1914 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>()); 1915 const UVec4 minValue (0); 1916 const UVec4 range (UVec4(1u) << tcu::min(bits, UVec4(31))); 1917 std::ostringstream fragmentShader; 1918 1919 fragmentShader << 1920 "#version 450\n" 1921 "layout(location = 0) out highp uvec4 o_color;\n" 1922 "layout(push_constant) uniform PushConstant {\n" 1923 "\thighp uint sampleIndex;\n" 1924 "} pushConstants;\n" 1925 "void main (void)\n" 1926 "{\n" 1927 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n" 1928 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n" 1929 "\thighp uint color[4];\n" 1930 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n" 1931 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n"; 1932 1933 for (int ndx = 0; ndx < 4; ndx++) 1934 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n"; 1935 1936 { 1937 const int componentCount = tcu::getNumUsedChannels(format.order); 1938 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 1939 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 1940 deUint32 nextSrcBit = 0; 1941 deUint32 divider = 2; 1942 1943 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1944 while (nextSrcBit < de::min(bitSize, 10u)) 1945 { 1946 for (int compNdx = 0; compNdx < componentCount; compNdx++) 1947 { 1948 if (dstBitsUsed[compNdx] > bits[compNdx]) 1949 continue; 1950 1951 fragmentShader << 1952 "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider) 1953 << " * bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1);\n"; 1954 1955 nextSrcBit++; 1956 dstBitsUsed[compNdx]++; 1957 } 1958 1959 divider *= 2; 1960 } 1961 } 1962 1963 fragmentShader << 1964 "\to_color = uvec4(color[0], color[1], color[2], color[3]);\n" 1965 "}\n"; 1966 1967 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str()); 1968 break; 1969 } 1970 1971 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 1972 { 1973 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>()); 1974 const IVec4 minValue (0); 1975 const IVec4 range ((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>()); 1976 std::ostringstream fragmentShader; 1977 1978 fragmentShader << 1979 "#version 450\n" 1980 "layout(location = 0) out highp ivec4 o_color;\n" 1981 "layout(push_constant) uniform PushConstant {\n" 1982 "\thighp uint sampleIndex;\n" 1983 "} pushConstants;\n" 1984 "void main (void)\n" 1985 "{\n" 1986 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n" 1987 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n" 1988 "\thighp int color[4];\n" 1989 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n" 1990 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n"; 1991 1992 for (int ndx = 0; ndx < 4; ndx++) 1993 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n"; 1994 1995 { 1996 const int componentCount = tcu::getNumUsedChannels(format.order); 1997 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 1998 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 1999 deUint32 nextSrcBit = 0; 2000 deUint32 divider = 2; 2001 2002 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 2003 while (nextSrcBit < de::min(bitSize, 10u)) 2004 { 2005 for (int compNdx = 0; compNdx < componentCount; compNdx++) 2006 { 2007 if (dstBitsUsed[compNdx] > bits[compNdx]) 2008 continue; 2009 2010 fragmentShader << 2011 "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider) 2012 << " * int(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n"; 2013 2014 nextSrcBit++; 2015 dstBitsUsed[compNdx]++; 2016 } 2017 2018 divider *= 2; 2019 } 2020 } 2021 2022 fragmentShader << 2023 "\to_color = ivec4(color[0], color[1], color[2], color[3]);\n" 2024 "}\n"; 2025 2026 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str()); 2027 break; 2028 } 2029 2030 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 2031 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 2032 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 2033 { 2034 const tcu::TextureFormatInfo info (tcu::getTextureFormatInfo(format)); 2035 const UVec4 bits (tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()); 2036 const Vec4 minLimit (-65536.0); 2037 const Vec4 maxLimit (65536.0); 2038 const Vec4 minValue (tcu::max(info.valueMin, minLimit)); 2039 const Vec4 range (tcu::min(info.valueMax, maxLimit) - minValue); 2040 std::ostringstream fragmentShader; 2041 2042 fragmentShader << 2043 "#version 450\n" 2044 "layout(location = 0) out highp vec4 o_color;\n" 2045 "layout(push_constant) uniform PushConstant {\n" 2046 "\thighp uint sampleIndex;\n" 2047 "} pushConstants;\n" 2048 "void main (void)\n" 2049 "{\n" 2050 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n" 2051 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n" 2052 "\thighp float color[4];\n" 2053 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n" 2054 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n"; 2055 2056 for (int ndx = 0; ndx < 4; ndx++) 2057 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n"; 2058 2059 { 2060 const int componentCount = tcu::getNumUsedChannels(format.order); 2061 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 2062 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 2063 deUint32 nextSrcBit = 0; 2064 deUint32 divider = 2; 2065 2066 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 2067 while (nextSrcBit < de::min(bitSize, 10u)) 2068 { 2069 for (int compNdx = 0; compNdx < componentCount; compNdx++) 2070 { 2071 if (dstBitsUsed[compNdx] > bits[compNdx]) 2072 continue; 2073 2074 fragmentShader << 2075 "\tcolor[" << compNdx << "] += " << (range[compNdx] / (float)divider) 2076 << " * float(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n"; 2077 2078 nextSrcBit++; 2079 dstBitsUsed[compNdx]++; 2080 } 2081 2082 divider *= 2; 2083 } 2084 } 2085 2086 fragmentShader << 2087 "\to_color = vec4(color[0], color[1], color[2], color[3]);\n" 2088 "}\n"; 2089 2090 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str()); 2091 break; 2092 } 2093 2094 default: 2095 DE_FATAL("Unknown channel class"); 2096 } 2097 } 2098 2099 if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order)) 2100 { 2101 std::ostringstream splitShader; 2102 2103 splitShader << 2104 "#version 450\n"; 2105 2106 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order)) 2107 { 2108 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n" 2109 << "layout(input_attachment_index = 0, set = 0, binding = 1) uniform highp usubpassInputMS i_stencil;\n"; 2110 } 2111 else if (tcu::hasDepthComponent(format.order)) 2112 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n"; 2113 else if (tcu::hasStencilComponent(format.order)) 2114 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp usubpassInputMS i_stencil;\n"; 2115 2116 splitShader << 2117 "layout(push_constant) uniform PushConstant {\n" 2118 "\thighp uint splitSubpassIndex;\n" 2119 "} pushConstants;\n"; 2120 2121 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++) 2122 { 2123 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order)) 2124 splitShader << "layout(location = " << attachmentNdx << ") out highp vec2 o_color" << attachmentNdx << ";\n"; 2125 else 2126 splitShader << "layout(location = " << attachmentNdx << ") out highp float o_color" << attachmentNdx << ";\n"; 2127 } 2128 2129 splitShader << 2130 "void main (void)\n" 2131 "{\n"; 2132 2133 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++) 2134 { 2135 if (tcu::hasDepthComponent(format.order)) 2136 splitShader << "\thighp float depth" << attachmentNdx << " = subpassLoad(i_depth, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n"; 2137 2138 if (tcu::hasStencilComponent(format.order)) 2139 splitShader << "\thighp uint stencil" << attachmentNdx << " = subpassLoad(i_stencil, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n"; 2140 2141 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order)) 2142 splitShader << "\to_color" << attachmentNdx << " = vec2(depth" << attachmentNdx << ", float(stencil" << attachmentNdx << "));\n"; 2143 else if (tcu::hasDepthComponent(format.order)) 2144 splitShader << "\to_color" << attachmentNdx << " = float(depth" << attachmentNdx << ");\n"; 2145 else if (tcu::hasStencilComponent(format.order)) 2146 splitShader << "\to_color" << attachmentNdx << " = float(stencil" << attachmentNdx << ");\n"; 2147 } 2148 2149 splitShader << 2150 "}\n"; 2151 2152 dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str()); 2153 } 2154 else 2155 { 2156 std::string subpassType; 2157 std::string outputType; 2158 2159 switch (channelClass) 2160 { 2161 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 2162 subpassType = "usubpassInputMS"; 2163 outputType = "uvec4"; 2164 break; 2165 2166 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 2167 subpassType = "isubpassInputMS"; 2168 outputType = "ivec4"; 2169 break; 2170 2171 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 2172 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 2173 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 2174 subpassType = "subpassInputMS"; 2175 outputType = "vec4"; 2176 break; 2177 2178 default: 2179 DE_FATAL("Unknown channel class"); 2180 } 2181 2182 std::ostringstream splitShader; 2183 splitShader << 2184 "#version 450\n" 2185 "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp " << subpassType << " i_color;\n" 2186 "layout(push_constant) uniform PushConstant {\n" 2187 "\thighp uint splitSubpassIndex;\n" 2188 "} pushConstants;\n"; 2189 2190 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++) 2191 splitShader << "layout(location = " << attachmentNdx << ") out highp " << outputType << " o_color" << attachmentNdx << ";\n"; 2192 2193 splitShader << 2194 "void main (void)\n" 2195 "{\n"; 2196 2197 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++) 2198 splitShader << "\to_color" << attachmentNdx << " = subpassLoad(i_color, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u));\n"; 2199 2200 splitShader << 2201 "}\n"; 2202 2203 dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str()); 2204 } 2205 } 2206 }; 2207 2208 std::string formatToName (VkFormat format) 2209 { 2210 const std::string formatStr = de::toString(format); 2211 const std::string prefix = "VK_FORMAT_"; 2212 2213 DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix); 2214 2215 return de::toLower(formatStr.substr(prefix.length())); 2216 } 2217 2218 void initTests (tcu::TestCaseGroup* group) 2219 { 2220 static const VkFormat formats[] = 2221 { 2222 VK_FORMAT_R5G6B5_UNORM_PACK16, 2223 VK_FORMAT_R8_UNORM, 2224 VK_FORMAT_R8_SNORM, 2225 VK_FORMAT_R8_UINT, 2226 VK_FORMAT_R8_SINT, 2227 VK_FORMAT_R8G8_UNORM, 2228 VK_FORMAT_R8G8_SNORM, 2229 VK_FORMAT_R8G8_UINT, 2230 VK_FORMAT_R8G8_SINT, 2231 VK_FORMAT_R8G8B8A8_UNORM, 2232 VK_FORMAT_R8G8B8A8_SNORM, 2233 VK_FORMAT_R8G8B8A8_UINT, 2234 VK_FORMAT_R8G8B8A8_SINT, 2235 VK_FORMAT_R8G8B8A8_SRGB, 2236 VK_FORMAT_A8B8G8R8_UNORM_PACK32, 2237 VK_FORMAT_A8B8G8R8_SNORM_PACK32, 2238 VK_FORMAT_A8B8G8R8_UINT_PACK32, 2239 VK_FORMAT_A8B8G8R8_SINT_PACK32, 2240 VK_FORMAT_A8B8G8R8_SRGB_PACK32, 2241 VK_FORMAT_B8G8R8A8_UNORM, 2242 VK_FORMAT_B8G8R8A8_SRGB, 2243 VK_FORMAT_A2R10G10B10_UNORM_PACK32, 2244 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 2245 VK_FORMAT_A2B10G10R10_UINT_PACK32, 2246 VK_FORMAT_R16_UNORM, 2247 VK_FORMAT_R16_SNORM, 2248 VK_FORMAT_R16_UINT, 2249 VK_FORMAT_R16_SINT, 2250 VK_FORMAT_R16_SFLOAT, 2251 VK_FORMAT_R16G16_UNORM, 2252 VK_FORMAT_R16G16_SNORM, 2253 VK_FORMAT_R16G16_UINT, 2254 VK_FORMAT_R16G16_SINT, 2255 VK_FORMAT_R16G16_SFLOAT, 2256 VK_FORMAT_R16G16B16A16_UNORM, 2257 VK_FORMAT_R16G16B16A16_SNORM, 2258 VK_FORMAT_R16G16B16A16_UINT, 2259 VK_FORMAT_R16G16B16A16_SINT, 2260 VK_FORMAT_R16G16B16A16_SFLOAT, 2261 VK_FORMAT_R32_UINT, 2262 VK_FORMAT_R32_SINT, 2263 VK_FORMAT_R32_SFLOAT, 2264 VK_FORMAT_R32G32_UINT, 2265 VK_FORMAT_R32G32_SINT, 2266 VK_FORMAT_R32G32_SFLOAT, 2267 VK_FORMAT_R32G32B32A32_UINT, 2268 VK_FORMAT_R32G32B32A32_SINT, 2269 VK_FORMAT_R32G32B32A32_SFLOAT, 2270 2271 VK_FORMAT_D16_UNORM, 2272 VK_FORMAT_X8_D24_UNORM_PACK32, 2273 VK_FORMAT_D32_SFLOAT, 2274 VK_FORMAT_S8_UINT, 2275 VK_FORMAT_D16_UNORM_S8_UINT, 2276 VK_FORMAT_D24_UNORM_S8_UINT, 2277 VK_FORMAT_D32_SFLOAT_S8_UINT 2278 }; 2279 const deUint32 sampleCounts[] = 2280 { 2281 2u, 4u, 8u, 16u, 32u 2282 }; 2283 tcu::TestContext& testCtx (group->getTestContext()); 2284 2285 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++) 2286 { 2287 const VkFormat format (formats[formatNdx]); 2288 const std::string formatName (formatToName(format)); 2289 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str())); 2290 2291 for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++) 2292 { 2293 const deUint32 sampleCount (sampleCounts[sampleCountNdx]); 2294 const std::string testName ("samples_" + de::toString(sampleCount)); 2295 2296 formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), TestConfig(format, sampleCount))); 2297 } 2298 2299 group->addChild(formatGroup.release()); 2300 } 2301 } 2302 2303 } // anonymous 2304 2305 tcu::TestCaseGroup* createRenderPassMultisampleTests (tcu::TestContext& testCtx) 2306 { 2307 return createTestGroup(testCtx, "multisample", "Multisample render pass tests", initTests); 2308 } 2309 2310 } // vkt 2311