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 VkFormat srcFormat, 715 VkRenderPass renderPass, 716 VkPipelineLayout pipelineLayout, 717 const vk::BinaryCollection& binaryCollection, 718 deUint32 width, 719 deUint32 height, 720 deUint32 sampleCount) 721 { 722 const tcu::TextureFormat format (mapVkFormat(srcFormat)); 723 const bool isDepthStencilFormat (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order)); 724 725 const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u)); 726 const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-frag"), 0u)); 727 const VkSpecializationInfo emptyShaderSpecializations = 728 { 729 0u, 730 DE_NULL, 731 732 0u, 733 DE_NULL 734 }; 735 // Disable blending 736 const VkPipelineColorBlendAttachmentState attachmentBlendState = 737 { 738 VK_FALSE, 739 VK_BLEND_FACTOR_SRC_ALPHA, 740 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, 741 VK_BLEND_OP_ADD, 742 VK_BLEND_FACTOR_ONE, 743 VK_BLEND_FACTOR_ONE, 744 VK_BLEND_OP_ADD, 745 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT 746 }; 747 const VkPipelineShaderStageCreateInfo shaderStages[2] = 748 { 749 { 750 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 751 DE_NULL, 752 (VkPipelineShaderStageCreateFlags)0u, 753 VK_SHADER_STAGE_VERTEX_BIT, 754 *vertexShaderModule, 755 "main", 756 &emptyShaderSpecializations 757 }, 758 { 759 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 760 DE_NULL, 761 (VkPipelineShaderStageCreateFlags)0u, 762 VK_SHADER_STAGE_FRAGMENT_BIT, 763 *fragmentShaderModule, 764 "main", 765 &emptyShaderSpecializations 766 } 767 }; 768 const VkPipelineVertexInputStateCreateInfo vertexInputState = 769 { 770 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 771 DE_NULL, 772 (VkPipelineVertexInputStateCreateFlags)0u, 773 774 0u, 775 DE_NULL, 776 777 0u, 778 DE_NULL 779 }; 780 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = 781 { 782 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 783 DE_NULL, 784 785 (VkPipelineInputAssemblyStateCreateFlags)0u, 786 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 787 VK_FALSE 788 }; 789 const VkViewport viewport = 790 { 791 0.0f, 0.0f, 792 (float)width, (float)height, 793 794 0.0f, 1.0f 795 }; 796 const VkRect2D scissor = 797 { 798 { 0u, 0u }, 799 { width, height } 800 }; 801 const VkPipelineViewportStateCreateInfo viewportState = 802 { 803 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 804 DE_NULL, 805 (VkPipelineViewportStateCreateFlags)0u, 806 807 1u, 808 &viewport, 809 810 1u, 811 &scissor 812 }; 813 const VkPipelineRasterizationStateCreateInfo rasterState = 814 { 815 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 816 DE_NULL, 817 (VkPipelineRasterizationStateCreateFlags)0u, 818 VK_TRUE, 819 VK_FALSE, 820 VK_POLYGON_MODE_FILL, 821 VK_CULL_MODE_NONE, 822 VK_FRONT_FACE_COUNTER_CLOCKWISE, 823 VK_FALSE, 824 0.0f, 825 0.0f, 826 0.0f, 827 1.0f 828 }; 829 const VkPipelineMultisampleStateCreateInfo multisampleState = 830 { 831 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 832 DE_NULL, 833 (VkPipelineMultisampleStateCreateFlags)0u, 834 835 sampleCountBitFromomSampleCount(sampleCount), 836 VK_FALSE, 837 0.0f, 838 DE_NULL, 839 VK_FALSE, 840 VK_FALSE, 841 }; 842 const VkPipelineDepthStencilStateCreateInfo depthStencilState = 843 { 844 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 845 DE_NULL, 846 (VkPipelineDepthStencilStateCreateFlags)0u, 847 848 VK_TRUE, 849 VK_TRUE, 850 VK_COMPARE_OP_ALWAYS, 851 VK_FALSE, 852 VK_TRUE, 853 { 854 VK_STENCIL_OP_KEEP, 855 VK_STENCIL_OP_INCREMENT_AND_WRAP, 856 VK_STENCIL_OP_KEEP, 857 VK_COMPARE_OP_ALWAYS, 858 ~0u, 859 ~0u, 860 0xFFu / (sampleCount + 1) 861 }, 862 { 863 VK_STENCIL_OP_KEEP, 864 VK_STENCIL_OP_INCREMENT_AND_WRAP, 865 VK_STENCIL_OP_KEEP, 866 VK_COMPARE_OP_ALWAYS, 867 ~0u, 868 ~0u, 869 0xFFu / (sampleCount + 1) 870 }, 871 872 0.0f, 873 1.0f 874 }; 875 const VkPipelineColorBlendStateCreateInfo blendState = 876 { 877 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 878 DE_NULL, 879 (VkPipelineColorBlendStateCreateFlags)0u, 880 881 VK_FALSE, 882 VK_LOGIC_OP_COPY, 883 (isDepthStencilFormat ? 0u : 1u), 884 (isDepthStencilFormat ? DE_NULL : &attachmentBlendState), 885 { 0.0f, 0.0f, 0.0f, 0.0f } 886 }; 887 const VkGraphicsPipelineCreateInfo createInfo = 888 { 889 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 890 DE_NULL, 891 (VkPipelineCreateFlags)0u, 892 893 2, 894 shaderStages, 895 896 &vertexInputState, 897 &inputAssemblyState, 898 DE_NULL, 899 &viewportState, 900 &rasterState, 901 &multisampleState, 902 &depthStencilState, 903 &blendState, 904 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, 905 pipelineLayout, 906 907 renderPass, 908 0u, 909 DE_NULL, 910 0u 911 }; 912 913 return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo); 914 } 915 916 Move<VkDescriptorSetLayout> createSplitDescriptorSetLayout (const DeviceInterface& vkd, 917 VkDevice device, 918 VkFormat vkFormat) 919 { 920 const tcu::TextureFormat format (mapVkFormat(vkFormat)); 921 const bool hasDepth (tcu::hasDepthComponent(format.order)); 922 const bool hasStencil (tcu::hasStencilComponent(format.order)); 923 const VkDescriptorSetLayoutBinding bindings[] = 924 { 925 { 926 0u, 927 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 928 1u, 929 VK_SHADER_STAGE_FRAGMENT_BIT, 930 DE_NULL 931 }, 932 { 933 1u, 934 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 935 1u, 936 VK_SHADER_STAGE_FRAGMENT_BIT, 937 DE_NULL 938 } 939 }; 940 const VkDescriptorSetLayoutCreateInfo createInfo = 941 { 942 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 943 DE_NULL, 944 0u, 945 946 hasDepth && hasStencil ? 2u : 1u, 947 bindings 948 }; 949 950 return createDescriptorSetLayout(vkd, device, &createInfo); 951 } 952 953 Move<VkPipelineLayout> createSplitPipelineLayout (const DeviceInterface& vkd, 954 VkDevice device, 955 VkDescriptorSetLayout descriptorSetLayout) 956 { 957 const VkPushConstantRange pushConstant = 958 { 959 VK_SHADER_STAGE_FRAGMENT_BIT, 960 0u, 961 4u 962 }; 963 const VkPipelineLayoutCreateInfo createInfo = 964 { 965 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 966 DE_NULL, 967 (vk::VkPipelineLayoutCreateFlags)0, 968 969 1u, 970 &descriptorSetLayout, 971 972 1u, 973 &pushConstant 974 }; 975 976 return createPipelineLayout(vkd, device, &createInfo); 977 } 978 979 Move<VkPipeline> createSplitPipeline (const DeviceInterface& vkd, 980 VkDevice device, 981 VkRenderPass renderPass, 982 deUint32 subpassIndex, 983 VkPipelineLayout pipelineLayout, 984 const vk::BinaryCollection& binaryCollection, 985 deUint32 width, 986 deUint32 height, 987 deUint32 sampleCount) 988 { 989 const Unique<VkShaderModule> vertexShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-vert"), 0u)); 990 const Unique<VkShaderModule> fragmentShaderModule (createShaderModule(vkd, device, binaryCollection.get("quad-split-frag"), 0u)); 991 const VkSpecializationInfo emptyShaderSpecializations = 992 { 993 0u, 994 DE_NULL, 995 996 0u, 997 DE_NULL 998 }; 999 // Disable blending 1000 const VkPipelineColorBlendAttachmentState attachmentBlendState = 1001 { 1002 VK_FALSE, 1003 VK_BLEND_FACTOR_SRC_ALPHA, 1004 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, 1005 VK_BLEND_OP_ADD, 1006 VK_BLEND_FACTOR_ONE, 1007 VK_BLEND_FACTOR_ONE, 1008 VK_BLEND_OP_ADD, 1009 VK_COLOR_COMPONENT_R_BIT|VK_COLOR_COMPONENT_G_BIT|VK_COLOR_COMPONENT_B_BIT|VK_COLOR_COMPONENT_A_BIT 1010 }; 1011 const std::vector<VkPipelineColorBlendAttachmentState> attachmentBlendStates (de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, sampleCount), attachmentBlendState); 1012 const VkPipelineShaderStageCreateInfo shaderStages[2] = 1013 { 1014 { 1015 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 1016 DE_NULL, 1017 (VkPipelineShaderStageCreateFlags)0u, 1018 VK_SHADER_STAGE_VERTEX_BIT, 1019 *vertexShaderModule, 1020 "main", 1021 &emptyShaderSpecializations 1022 }, 1023 { 1024 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, 1025 DE_NULL, 1026 (VkPipelineShaderStageCreateFlags)0u, 1027 VK_SHADER_STAGE_FRAGMENT_BIT, 1028 *fragmentShaderModule, 1029 "main", 1030 &emptyShaderSpecializations 1031 } 1032 }; 1033 const VkPipelineVertexInputStateCreateInfo vertexInputState = 1034 { 1035 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 1036 DE_NULL, 1037 (VkPipelineVertexInputStateCreateFlags)0u, 1038 1039 0u, 1040 DE_NULL, 1041 1042 0u, 1043 DE_NULL 1044 }; 1045 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = 1046 { 1047 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 1048 DE_NULL, 1049 1050 (VkPipelineInputAssemblyStateCreateFlags)0u, 1051 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 1052 VK_FALSE 1053 }; 1054 const VkViewport viewport = 1055 { 1056 0.0f, 0.0f, 1057 (float)width, (float)height, 1058 1059 0.0f, 1.0f 1060 }; 1061 const VkRect2D scissor = 1062 { 1063 { 0u, 0u }, 1064 { width, height } 1065 }; 1066 const VkPipelineViewportStateCreateInfo viewportState = 1067 { 1068 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 1069 DE_NULL, 1070 (VkPipelineViewportStateCreateFlags)0u, 1071 1072 1u, 1073 &viewport, 1074 1075 1u, 1076 &scissor 1077 }; 1078 const VkPipelineRasterizationStateCreateInfo rasterState = 1079 { 1080 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 1081 DE_NULL, 1082 (VkPipelineRasterizationStateCreateFlags)0u, 1083 VK_TRUE, 1084 VK_FALSE, 1085 VK_POLYGON_MODE_FILL, 1086 VK_CULL_MODE_NONE, 1087 VK_FRONT_FACE_COUNTER_CLOCKWISE, 1088 VK_FALSE, 1089 0.0f, 1090 0.0f, 1091 0.0f, 1092 1.0f 1093 }; 1094 const VkPipelineMultisampleStateCreateInfo multisampleState = 1095 { 1096 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 1097 DE_NULL, 1098 (VkPipelineMultisampleStateCreateFlags)0u, 1099 1100 sampleCountBitFromomSampleCount(sampleCount), 1101 VK_FALSE, 1102 0.0f, 1103 DE_NULL, 1104 VK_FALSE, 1105 VK_FALSE, 1106 }; 1107 const VkPipelineDepthStencilStateCreateInfo depthStencilState = 1108 { 1109 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 1110 DE_NULL, 1111 (VkPipelineDepthStencilStateCreateFlags)0u, 1112 1113 VK_FALSE, 1114 VK_FALSE, 1115 VK_COMPARE_OP_ALWAYS, 1116 VK_FALSE, 1117 VK_FALSE, 1118 { 1119 VK_STENCIL_OP_REPLACE, 1120 VK_STENCIL_OP_REPLACE, 1121 VK_STENCIL_OP_REPLACE, 1122 VK_COMPARE_OP_ALWAYS, 1123 ~0u, 1124 ~0u, 1125 0x0u 1126 }, 1127 { 1128 VK_STENCIL_OP_REPLACE, 1129 VK_STENCIL_OP_REPLACE, 1130 VK_STENCIL_OP_REPLACE, 1131 VK_COMPARE_OP_ALWAYS, 1132 ~0u, 1133 ~0u, 1134 0x0u 1135 }, 1136 1137 0.0f, 1138 1.0f 1139 }; 1140 const VkPipelineColorBlendStateCreateInfo blendState = 1141 { 1142 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 1143 DE_NULL, 1144 (VkPipelineColorBlendStateCreateFlags)0u, 1145 1146 VK_FALSE, 1147 VK_LOGIC_OP_COPY, 1148 1149 (deUint32)attachmentBlendStates.size(), 1150 &attachmentBlendStates[0], 1151 1152 { 0.0f, 0.0f, 0.0f, 0.0f } 1153 }; 1154 const VkGraphicsPipelineCreateInfo createInfo = 1155 { 1156 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 1157 DE_NULL, 1158 (VkPipelineCreateFlags)0u, 1159 1160 2, 1161 shaderStages, 1162 1163 &vertexInputState, 1164 &inputAssemblyState, 1165 DE_NULL, 1166 &viewportState, 1167 &rasterState, 1168 &multisampleState, 1169 &depthStencilState, 1170 &blendState, 1171 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, 1172 pipelineLayout, 1173 1174 renderPass, 1175 subpassIndex, 1176 DE_NULL, 1177 0u 1178 }; 1179 1180 return createGraphicsPipeline(vkd, device, DE_NULL, &createInfo); 1181 } 1182 1183 vector<VkPipelineSp> createSplitPipelines (const DeviceInterface& vkd, 1184 VkDevice device, 1185 VkRenderPass renderPass, 1186 VkPipelineLayout pipelineLayout, 1187 const vk::BinaryCollection& binaryCollection, 1188 deUint32 width, 1189 deUint32 height, 1190 deUint32 sampleCount) 1191 { 1192 std::vector<VkPipelineSp> pipelines (deDivRoundUp32(sampleCount, MAX_COLOR_ATTACHMENT_COUNT), (VkPipelineSp)0u); 1193 1194 for (size_t ndx = 0; ndx < pipelines.size(); ndx++) 1195 pipelines[ndx] = safeSharedPtr(new Unique<VkPipeline>(createSplitPipeline(vkd, device, renderPass, (deUint32)(ndx + 1), pipelineLayout, binaryCollection, width, height, sampleCount))); 1196 1197 return pipelines; 1198 } 1199 1200 Move<VkDescriptorPool> createSplitDescriptorPool (const DeviceInterface& vkd, 1201 VkDevice device) 1202 { 1203 const VkDescriptorPoolSize size = 1204 { 1205 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 2u 1206 }; 1207 const VkDescriptorPoolCreateInfo createInfo = 1208 { 1209 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 1210 DE_NULL, 1211 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1212 1213 1214 2u, 1215 1u, 1216 &size 1217 }; 1218 1219 return createDescriptorPool(vkd, device, &createInfo); 1220 } 1221 1222 Move<VkDescriptorSet> createSplitDescriptorSet (const DeviceInterface& vkd, 1223 VkDevice device, 1224 VkDescriptorPool pool, 1225 VkDescriptorSetLayout layout, 1226 VkImageView primaryImageView, 1227 VkImageView secondaryImageView) 1228 { 1229 const VkDescriptorSetAllocateInfo allocateInfo = 1230 { 1231 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 1232 DE_NULL, 1233 1234 pool, 1235 1u, 1236 &layout 1237 }; 1238 Move<VkDescriptorSet> set (allocateDescriptorSet(vkd, device, &allocateInfo)); 1239 1240 { 1241 const VkDescriptorImageInfo imageInfos[] = 1242 { 1243 { 1244 (VkSampler)0u, 1245 primaryImageView, 1246 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL 1247 }, 1248 { 1249 (VkSampler)0u, 1250 secondaryImageView, 1251 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL 1252 } 1253 }; 1254 const VkWriteDescriptorSet writes[] = 1255 { 1256 { 1257 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 1258 DE_NULL, 1259 1260 *set, 1261 0u, 1262 0u, 1263 1u, 1264 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1265 &imageInfos[0], 1266 DE_NULL, 1267 DE_NULL 1268 }, 1269 { 1270 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 1271 DE_NULL, 1272 1273 *set, 1274 1u, 1275 0u, 1276 1u, 1277 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1278 &imageInfos[1], 1279 DE_NULL, 1280 DE_NULL 1281 } 1282 }; 1283 const deUint32 count = secondaryImageView != (VkImageView)0 1284 ? 2u 1285 : 1u; 1286 1287 vkd.updateDescriptorSets(device, count, writes, 0u, DE_NULL); 1288 } 1289 return set; 1290 } 1291 1292 struct TestConfig 1293 { 1294 TestConfig (VkFormat format_, 1295 deUint32 sampleCount_) 1296 : format (format_) 1297 , sampleCount (sampleCount_) 1298 { 1299 } 1300 1301 VkFormat format; 1302 deUint32 sampleCount; 1303 }; 1304 1305 VkImageUsageFlags getSrcImageUsage (VkFormat vkFormat) 1306 { 1307 const tcu::TextureFormat format (mapVkFormat(vkFormat)); 1308 const bool hasDepth (tcu::hasDepthComponent(format.order)); 1309 const bool hasStencil (tcu::hasStencilComponent(format.order)); 1310 1311 if (hasDepth || hasStencil) 1312 return VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 1313 else 1314 return VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 1315 } 1316 1317 VkFormat getDstFormat (VkFormat vkFormat) 1318 { 1319 const tcu::TextureFormat format (mapVkFormat(vkFormat)); 1320 const bool hasDepth (tcu::hasDepthComponent(format.order)); 1321 const bool hasStencil (tcu::hasStencilComponent(format.order)); 1322 1323 if (hasDepth && hasStencil) 1324 return VK_FORMAT_R32G32_SFLOAT; 1325 else if (hasDepth || hasStencil) 1326 return VK_FORMAT_R32_SFLOAT; 1327 else 1328 return vkFormat; 1329 } 1330 1331 1332 class MultisampleRenderPassTestInstance : public TestInstance 1333 { 1334 public: 1335 MultisampleRenderPassTestInstance (Context& context, TestConfig config); 1336 ~MultisampleRenderPassTestInstance (void); 1337 1338 tcu::TestStatus iterate (void); 1339 1340 private: 1341 const VkFormat m_srcFormat; 1342 const VkFormat m_dstFormat; 1343 const deUint32 m_sampleCount; 1344 const deUint32 m_width; 1345 const deUint32 m_height; 1346 1347 const VkImageAspectFlags m_srcImageAspect; 1348 const VkImageUsageFlags m_srcImageUsage; 1349 const Unique<VkImage> m_srcImage; 1350 const de::UniquePtr<Allocation> m_srcImageMemory; 1351 const Unique<VkImageView> m_srcImageView; 1352 const Unique<VkImageView> m_srcPrimaryInputImageView; 1353 const Unique<VkImageView> m_srcSecondaryInputImageView; 1354 1355 const std::vector<VkImageSp> m_dstMultisampleImages; 1356 const std::vector<de::SharedPtr<Allocation> > m_dstMultisampleImageMemory; 1357 const std::vector<VkImageViewSp> m_dstMultisampleImageViews; 1358 1359 const std::vector<VkImageSp> m_dstSinglesampleImages; 1360 const std::vector<de::SharedPtr<Allocation> > m_dstSinglesampleImageMemory; 1361 const std::vector<VkImageViewSp> m_dstSinglesampleImageViews; 1362 1363 const std::vector<VkBufferSp> m_dstBuffers; 1364 const std::vector<de::SharedPtr<Allocation> > m_dstBufferMemory; 1365 1366 const Unique<VkRenderPass> m_renderPass; 1367 const Unique<VkFramebuffer> m_framebuffer; 1368 1369 const Unique<VkPipelineLayout> m_renderPipelineLayout; 1370 const Unique<VkPipeline> m_renderPipeline; 1371 1372 const Unique<VkDescriptorSetLayout> m_splitDescriptorSetLayout; 1373 const Unique<VkPipelineLayout> m_splitPipelineLayout; 1374 const std::vector<VkPipelineSp> m_splitPipelines; 1375 const Unique<VkDescriptorPool> m_splitDescriptorPool; 1376 const Unique<VkDescriptorSet> m_splitDescriptorSet; 1377 1378 const Unique<VkCommandPool> m_commandPool; 1379 tcu::ResultCollector m_resultCollector; 1380 }; 1381 1382 MultisampleRenderPassTestInstance::MultisampleRenderPassTestInstance (Context& context, TestConfig config) 1383 : TestInstance (context) 1384 , m_srcFormat (config.format) 1385 , m_dstFormat (getDstFormat(config.format)) 1386 , m_sampleCount (config.sampleCount) 1387 , m_width (32u) 1388 , m_height (32u) 1389 1390 , m_srcImageAspect (getImageAspectFlags(m_srcFormat)) 1391 , m_srcImageUsage (getSrcImageUsage(m_srcFormat)) 1392 , m_srcImage (createImage(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_srcFormat, sampleCountBitFromomSampleCount(m_sampleCount), m_srcImageUsage, m_width, m_height)) 1393 , m_srcImageMemory (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), *m_srcImage)) 1394 , m_srcImageView (createImageAttachmentView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect)) 1395 , m_srcPrimaryInputImageView (createSrcPrimaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect)) 1396 , m_srcSecondaryInputImageView (createSrcSecondaryInputImageView(context.getDeviceInterface(), context.getDevice(), *m_srcImage, m_srcFormat, m_srcImageAspect)) 1397 1398 , m_dstMultisampleImages (createMultisampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height)) 1399 , m_dstMultisampleImageMemory (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstMultisampleImages)) 1400 , m_dstMultisampleImageViews (createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstMultisampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT)) 1401 1402 , m_dstSinglesampleImages (createSingleSampleImages(context.getInstanceInterface(), context.getPhysicalDevice(), context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height)) 1403 , m_dstSinglesampleImageMemory (createImageMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstSinglesampleImages)) 1404 , m_dstSinglesampleImageViews (createImageAttachmentViews(context.getDeviceInterface(), context.getDevice(), m_dstSinglesampleImages, m_dstFormat, VK_IMAGE_ASPECT_COLOR_BIT)) 1405 1406 , m_dstBuffers (createBuffers(context.getDeviceInterface(), context.getDevice(), m_dstFormat, m_sampleCount, m_width, m_height)) 1407 , m_dstBufferMemory (createBufferMemory(context.getDeviceInterface(), context.getDevice(), context.getDefaultAllocator(), m_dstBuffers)) 1408 1409 , m_renderPass (createRenderPass(context.getDeviceInterface(), context.getDevice(), m_srcFormat, m_dstFormat, m_sampleCount)) 1410 , m_framebuffer (createFramebuffer(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_srcImageView, m_dstMultisampleImageViews, m_dstSinglesampleImageViews, m_width, m_height)) 1411 1412 , m_renderPipelineLayout (createRenderPipelineLayout(context.getDeviceInterface(), context.getDevice())) 1413 , m_renderPipeline (createRenderPipeline(context.getDeviceInterface(), context.getDevice(), m_srcFormat, *m_renderPass, *m_renderPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount)) 1414 1415 , m_splitDescriptorSetLayout (createSplitDescriptorSetLayout(context.getDeviceInterface(), context.getDevice(), m_srcFormat)) 1416 , m_splitPipelineLayout (createSplitPipelineLayout(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorSetLayout)) 1417 , m_splitPipelines (createSplitPipelines(context.getDeviceInterface(), context.getDevice(), *m_renderPass, *m_splitPipelineLayout, context.getBinaryCollection(), m_width, m_height, m_sampleCount)) 1418 , m_splitDescriptorPool (createSplitDescriptorPool(context.getDeviceInterface(), context.getDevice())) 1419 , m_splitDescriptorSet (createSplitDescriptorSet(context.getDeviceInterface(), context.getDevice(), *m_splitDescriptorPool, *m_splitDescriptorSetLayout, *m_srcPrimaryInputImageView, *m_srcSecondaryInputImageView)) 1420 , m_commandPool (createCommandPool(context.getDeviceInterface(), context.getDevice(), VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, context.getUniversalQueueFamilyIndex())) 1421 { 1422 } 1423 1424 MultisampleRenderPassTestInstance::~MultisampleRenderPassTestInstance (void) 1425 { 1426 } 1427 1428 tcu::TestStatus MultisampleRenderPassTestInstance::iterate (void) 1429 { 1430 const DeviceInterface& vkd (m_context.getDeviceInterface()); 1431 const VkDevice device (m_context.getDevice()); 1432 const Unique<VkCommandBuffer> commandBuffer (allocateCommandBuffer(vkd, device, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 1433 1434 { 1435 const VkCommandBufferBeginInfo beginInfo = 1436 { 1437 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 1438 DE_NULL, 1439 1440 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 1441 DE_NULL 1442 }; 1443 1444 VK_CHECK(vkd.beginCommandBuffer(*commandBuffer, &beginInfo)); 1445 } 1446 1447 { 1448 const VkRenderPassBeginInfo beginInfo = 1449 { 1450 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 1451 DE_NULL, 1452 1453 *m_renderPass, 1454 *m_framebuffer, 1455 1456 { 1457 { 0u, 0u }, 1458 { m_width, m_height } 1459 }, 1460 1461 0u, 1462 DE_NULL 1463 }; 1464 vkd.cmdBeginRenderPass(*commandBuffer, &beginInfo, VK_SUBPASS_CONTENTS_INLINE); 1465 1466 // Stencil needs to be cleared if it exists. 1467 if (tcu::hasStencilComponent(mapVkFormat(m_srcFormat).order)) 1468 { 1469 const VkClearAttachment clearAttachment = 1470 { 1471 VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask; 1472 0, // deUint32 colorAttachment; 1473 makeClearValueDepthStencil(0, 0) // VkClearValue clearValue; 1474 }; 1475 1476 const VkClearRect clearRect = 1477 { 1478 { 1479 { 0u, 0u }, 1480 { m_width, m_height } 1481 }, 1482 0, // deUint32 baseArrayLayer; 1483 1 // deUint32 layerCount; 1484 }; 1485 1486 vkd.cmdClearAttachments(*commandBuffer, 1, &clearAttachment, 1, &clearRect); 1487 } 1488 } 1489 1490 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_renderPipeline); 1491 1492 for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++) 1493 { 1494 vkd.cmdPushConstants(*commandBuffer, *m_renderPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(sampleNdx), &sampleNdx); 1495 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u); 1496 } 1497 1498 for (deUint32 splitPipelineNdx = 0; splitPipelineNdx < m_splitPipelines.size(); splitPipelineNdx++) 1499 { 1500 vkd.cmdNextSubpass(*commandBuffer, VK_SUBPASS_CONTENTS_INLINE); 1501 1502 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **m_splitPipelines[splitPipelineNdx]); 1503 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_splitPipelineLayout, 0u, 1u, &*m_splitDescriptorSet, 0u, DE_NULL); 1504 vkd.cmdPushConstants(*commandBuffer, *m_splitPipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(splitPipelineNdx), &splitPipelineNdx); 1505 vkd.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u); 1506 } 1507 1508 vkd.cmdEndRenderPass(*commandBuffer); 1509 1510 // Memory barriers between rendering and copies 1511 { 1512 std::vector<VkImageMemoryBarrier> barriers; 1513 1514 for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++) 1515 { 1516 const VkImageMemoryBarrier barrier = 1517 { 1518 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 1519 DE_NULL, 1520 1521 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 1522 VK_ACCESS_TRANSFER_READ_BIT, 1523 1524 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1525 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1526 1527 VK_QUEUE_FAMILY_IGNORED, 1528 VK_QUEUE_FAMILY_IGNORED, 1529 1530 **m_dstSinglesampleImages[dstNdx], 1531 { 1532 VK_IMAGE_ASPECT_COLOR_BIT, 1533 0u, 1534 1u, 1535 0u, 1536 1u 1537 } 1538 }; 1539 1540 barriers.push_back(barrier); 1541 } 1542 1543 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]); 1544 } 1545 1546 // Copy image memory to buffers 1547 for (size_t dstNdx = 0; dstNdx < m_dstSinglesampleImages.size(); dstNdx++) 1548 { 1549 const VkBufferImageCopy region = 1550 { 1551 0u, 1552 0u, 1553 0u, 1554 { 1555 VK_IMAGE_ASPECT_COLOR_BIT, 1556 0u, 1557 0u, 1558 1u, 1559 }, 1560 { 0u, 0u, 0u }, 1561 { m_width, m_height, 1u } 1562 }; 1563 1564 vkd.cmdCopyImageToBuffer(*commandBuffer, **m_dstSinglesampleImages[dstNdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **m_dstBuffers[dstNdx], 1u, ®ion); 1565 } 1566 1567 // Memory barriers between copies and host access 1568 { 1569 std::vector<VkBufferMemoryBarrier> barriers; 1570 1571 for (size_t dstNdx = 0; dstNdx < m_dstBuffers.size(); dstNdx++) 1572 { 1573 const VkBufferMemoryBarrier barrier = 1574 { 1575 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 1576 DE_NULL, 1577 1578 VK_ACCESS_TRANSFER_WRITE_BIT, 1579 VK_ACCESS_HOST_READ_BIT, 1580 1581 VK_QUEUE_FAMILY_IGNORED, 1582 VK_QUEUE_FAMILY_IGNORED, 1583 1584 **m_dstBuffers[dstNdx], 1585 0u, 1586 VK_WHOLE_SIZE 1587 }; 1588 1589 barriers.push_back(barrier); 1590 } 1591 1592 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); 1593 } 1594 1595 VK_CHECK(vkd.endCommandBuffer(*commandBuffer)); 1596 1597 { 1598 const VkSubmitInfo submitInfo = 1599 { 1600 VK_STRUCTURE_TYPE_SUBMIT_INFO, 1601 DE_NULL, 1602 1603 0u, 1604 DE_NULL, 1605 DE_NULL, 1606 1607 1u, 1608 &*commandBuffer, 1609 1610 0u, 1611 DE_NULL 1612 }; 1613 1614 VK_CHECK(vkd.queueSubmit(m_context.getUniversalQueue(), 1u, &submitInfo, (VkFence)0u)); 1615 1616 VK_CHECK(vkd.queueWaitIdle(m_context.getUniversalQueue())); 1617 } 1618 1619 { 1620 const tcu::TextureFormat format (mapVkFormat(m_dstFormat)); 1621 const tcu::TextureFormat srcFormat (mapVkFormat(m_srcFormat)); 1622 const bool hasDepth (tcu::hasDepthComponent(srcFormat.order)); 1623 const bool hasStencil (tcu::hasStencilComponent(srcFormat.order)); 1624 1625 for (deUint32 sampleNdx = 0; sampleNdx < m_sampleCount; sampleNdx++) 1626 { 1627 const std::string name ("Sample" + de::toString(sampleNdx)); 1628 const void* const ptr (m_dstBufferMemory[sampleNdx]->getHostPtr()); 1629 const tcu::ConstPixelBufferAccess access (format, m_width, m_height, 1, ptr); 1630 tcu::TextureLevel reference (format, m_width, m_height); 1631 1632 if (hasDepth || hasStencil) 1633 { 1634 if (hasDepth) 1635 { 1636 for (deUint32 y = 0; y < m_height; y++) 1637 for (deUint32 x = 0; x < m_width; x++) 1638 { 1639 const deUint32 x1 = x ^ sampleNdx; 1640 const deUint32 y1 = y ^ sampleNdx; 1641 const float range = 1.0f; 1642 float depth = 0.0f; 1643 deUint32 divider = 2; 1644 1645 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1646 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++) 1647 { 1648 depth += (range / (float)divider) 1649 * (((bitNdx % 2 == 0 ? x1 : y1) & (0x1u << (bitNdx / 2u))) == 0u ? 0u : 1u); 1650 divider *= 2; 1651 } 1652 1653 reference.getAccess().setPixel(Vec4(depth, 0.0f, 0.0f, 0.0f), x, y); 1654 } 1655 } 1656 if (hasStencil) 1657 { 1658 for (deUint32 y = 0; y < m_height; y++) 1659 for (deUint32 x = 0; x < m_width; x++) 1660 { 1661 const deUint32 stencil = sampleNdx + 1u; 1662 1663 if (hasDepth) 1664 { 1665 const Vec4 src (reference.getAccess().getPixel(x, y)); 1666 1667 reference.getAccess().setPixel(Vec4(src.x(), (float)stencil, 0.0f, 0.0f), x, y); 1668 } 1669 else 1670 reference.getAccess().setPixel(Vec4((float)stencil, 0.0f, 0.0f, 0.0f), x, y); 1671 } 1672 } 1673 { 1674 const Vec4 threshold (hasDepth ? (1.0f / 1024.0f) : 0.0f, 0.0f, 0.0f, 0.0f); 1675 1676 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR)) 1677 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx)); 1678 } 1679 } 1680 else 1681 { 1682 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type)); 1683 1684 switch (channelClass) 1685 { 1686 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 1687 { 1688 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>()); 1689 const UVec4 minValue (0); 1690 const UVec4 range (UVec4(1u) << tcu::min(bits, UVec4(31))); 1691 const int componentCount (tcu::getNumUsedChannels(format.order)); 1692 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 1693 1694 for (deUint32 y = 0; y < m_height; y++) 1695 for (deUint32 x = 0; x < m_width; x++) 1696 { 1697 const deUint32 x1 = x ^ sampleNdx; 1698 const deUint32 y1 = y ^ sampleNdx; 1699 UVec4 color (minValue); 1700 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 1701 deUint32 nextSrcBit = 0; 1702 deUint32 divider = 2; 1703 1704 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1705 while (nextSrcBit < de::min(bitSize, 10u)) 1706 { 1707 for (int compNdx = 0; compNdx < componentCount; compNdx++) 1708 { 1709 if (dstBitsUsed[compNdx] > bits[compNdx]) 1710 continue; 1711 1712 color[compNdx] += (range[compNdx] / divider) 1713 * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u); 1714 1715 nextSrcBit++; 1716 dstBitsUsed[compNdx]++; 1717 } 1718 1719 divider *= 2; 1720 } 1721 1722 reference.getAccess().setPixel(color, x, y); 1723 } 1724 1725 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR)) 1726 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx)); 1727 1728 break; 1729 } 1730 1731 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 1732 { 1733 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>()); 1734 const IVec4 minValue (0); 1735 const IVec4 range ((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>()); 1736 const int componentCount (tcu::getNumUsedChannels(format.order)); 1737 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 1738 1739 for (deUint32 y = 0; y < m_height; y++) 1740 for (deUint32 x = 0; x < m_width; x++) 1741 { 1742 const deUint32 x1 = x ^ sampleNdx; 1743 const deUint32 y1 = y ^ sampleNdx; 1744 IVec4 color (minValue); 1745 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 1746 deUint32 nextSrcBit = 0; 1747 deUint32 divider = 2; 1748 1749 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1750 while (nextSrcBit < de::min(bitSize, 10u)) 1751 { 1752 for (int compNdx = 0; compNdx < componentCount; compNdx++) 1753 { 1754 if (dstBitsUsed[compNdx] > bits[compNdx]) 1755 continue; 1756 1757 color[compNdx] += (range[compNdx] / divider) 1758 * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u); 1759 1760 nextSrcBit++; 1761 dstBitsUsed[compNdx]++; 1762 } 1763 1764 divider *= 2; 1765 } 1766 1767 reference.getAccess().setPixel(color, x, y); 1768 } 1769 1770 if (!tcu::intThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, UVec4(0u), tcu::COMPARE_LOG_ON_ERROR)) 1771 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx)); 1772 1773 break; 1774 } 1775 1776 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 1777 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 1778 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 1779 { 1780 const tcu::TextureFormatInfo info (tcu::getTextureFormatInfo(format)); 1781 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>()); 1782 const Vec4 minLimit (-65536.0); 1783 const Vec4 maxLimit (65536.0); 1784 const Vec4 minValue (tcu::max(info.valueMin, minLimit)); 1785 const Vec4 range (tcu::min(info.valueMax, maxLimit) - minValue); 1786 const int componentCount (tcu::getNumUsedChannels(format.order)); 1787 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 1788 1789 for (deUint32 y = 0; y < m_height; y++) 1790 for (deUint32 x = 0; x < m_width; x++) 1791 { 1792 const deUint32 x1 = x ^ sampleNdx; 1793 const deUint32 y1 = y ^ sampleNdx; 1794 Vec4 color (minValue); 1795 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 1796 deUint32 nextSrcBit = 0; 1797 deUint32 divider = 2; 1798 1799 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1800 while (nextSrcBit < de::min(bitSize, 10u)) 1801 { 1802 for (int compNdx = 0; compNdx < componentCount; compNdx++) 1803 { 1804 if (dstBitsUsed[compNdx] > bits[compNdx]) 1805 continue; 1806 1807 color[compNdx] += (range[compNdx] / (float)divider) 1808 * (((nextSrcBit % 2 == 0 ? x1 : y1) & (0x1u << (nextSrcBit / 2u))) == 0u ? 0u : 1u); 1809 1810 nextSrcBit++; 1811 dstBitsUsed[compNdx]++; 1812 } 1813 1814 divider *= 2; 1815 } 1816 1817 if (tcu::isSRGB(format)) 1818 reference.getAccess().setPixel(tcu::linearToSRGB(color), x, y); 1819 else 1820 reference.getAccess().setPixel(color, x, y); 1821 } 1822 1823 if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT) 1824 { 1825 // Convert target format ulps to float ulps and allow 64ulp differences 1826 const UVec4 threshold (64u * (UVec4(1u) << (UVec4(23) - tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()))); 1827 1828 if (!tcu::floatUlpThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR)) 1829 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx)); 1830 } 1831 else 1832 { 1833 // Allow error of 4 times the minimum presentable difference 1834 const Vec4 threshold (4.0f * 1.0f / ((UVec4(1u) << tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()) - 1u).cast<float>()); 1835 1836 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), name.c_str(), name.c_str(), reference.getAccess(), access, threshold, tcu::COMPARE_LOG_ON_ERROR)) 1837 m_resultCollector.fail("Compare failed for sample " + de::toString(sampleNdx)); 1838 } 1839 1840 break; 1841 } 1842 1843 default: 1844 DE_FATAL("Unknown channel class"); 1845 } 1846 } 1847 } 1848 } 1849 1850 return tcu::TestStatus(m_resultCollector.getResult(), m_resultCollector.getMessage()); 1851 } 1852 1853 struct Programs 1854 { 1855 void init (vk::SourceCollections& dst, TestConfig config) const 1856 { 1857 const tcu::TextureFormat format (mapVkFormat(config.format)); 1858 const tcu::TextureChannelClass channelClass (tcu::getTextureChannelClass(format.type)); 1859 1860 dst.glslSources.add("quad-vert") << glu::VertexSource( 1861 "#version 450\n" 1862 "out gl_PerVertex {\n" 1863 "\tvec4 gl_Position;\n" 1864 "};\n" 1865 "highp float;\n" 1866 "void main (void) {\n" 1867 "\tgl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n" 1868 "\t ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n" 1869 "}\n"); 1870 1871 if (tcu::hasDepthComponent(format.order)) 1872 { 1873 const Vec4 minValue (0.0f); 1874 const Vec4 range (1.0f); 1875 std::ostringstream fragmentShader; 1876 1877 fragmentShader << 1878 "#version 450\n" 1879 "layout(push_constant) uniform PushConstant {\n" 1880 "\thighp uint sampleIndex;\n" 1881 "} pushConstants;\n" 1882 "void main (void)\n" 1883 "{\n" 1884 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n" 1885 "\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n" 1886 "\thighp float depth;\n" 1887 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n" 1888 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n"; 1889 1890 fragmentShader << "\tdepth = " << minValue[0] << ";\n"; 1891 1892 { 1893 deUint32 divider = 2; 1894 1895 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1896 for (size_t bitNdx = 0; bitNdx < 10; bitNdx++) 1897 { 1898 fragmentShader << 1899 "\tdepth += " << (range[0] / (float)divider) 1900 << " * float(bitfieldExtract(" << (bitNdx % 2 == 0 ? "x" : "y") << ", " << (bitNdx / 2) << ", 1));\n"; 1901 1902 divider *= 2; 1903 } 1904 } 1905 1906 fragmentShader << 1907 "\tgl_FragDepth = depth;\n" 1908 "}\n"; 1909 1910 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str()); 1911 } 1912 else if (tcu::hasStencilComponent(format.order)) 1913 { 1914 dst.glslSources.add("quad-frag") << glu::FragmentSource( 1915 "#version 450\n" 1916 "layout(push_constant) uniform PushConstant {\n" 1917 "\thighp uint sampleIndex;\n" 1918 "} pushConstants;\n" 1919 "void main (void)\n" 1920 "{\n" 1921 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n" 1922 "\tgl_SampleMask[0] = int((~0x0u) << sampleIndex);\n" 1923 "}\n"); 1924 } 1925 else 1926 { 1927 switch (channelClass) 1928 { 1929 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 1930 { 1931 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>()); 1932 const UVec4 minValue (0); 1933 const UVec4 range (UVec4(1u) << tcu::min(bits, UVec4(31))); 1934 std::ostringstream fragmentShader; 1935 1936 fragmentShader << 1937 "#version 450\n" 1938 "layout(location = 0) out highp uvec4 o_color;\n" 1939 "layout(push_constant) uniform PushConstant {\n" 1940 "\thighp uint sampleIndex;\n" 1941 "} pushConstants;\n" 1942 "void main (void)\n" 1943 "{\n" 1944 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n" 1945 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n" 1946 "\thighp uint color[4];\n" 1947 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n" 1948 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n"; 1949 1950 for (int ndx = 0; ndx < 4; ndx++) 1951 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n"; 1952 1953 { 1954 const int componentCount = tcu::getNumUsedChannels(format.order); 1955 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 1956 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 1957 deUint32 nextSrcBit = 0; 1958 deUint32 divider = 2; 1959 1960 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 1961 while (nextSrcBit < de::min(bitSize, 10u)) 1962 { 1963 for (int compNdx = 0; compNdx < componentCount; compNdx++) 1964 { 1965 if (dstBitsUsed[compNdx] > bits[compNdx]) 1966 continue; 1967 1968 fragmentShader << 1969 "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider) 1970 << " * bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1);\n"; 1971 1972 nextSrcBit++; 1973 dstBitsUsed[compNdx]++; 1974 } 1975 1976 divider *= 2; 1977 } 1978 } 1979 1980 fragmentShader << 1981 "\to_color = uvec4(color[0], color[1], color[2], color[3]);\n" 1982 "}\n"; 1983 1984 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str()); 1985 break; 1986 } 1987 1988 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 1989 { 1990 const UVec4 bits (tcu::getTextureFormatBitDepth(format).cast<deUint32>()); 1991 const IVec4 minValue (0); 1992 const IVec4 range ((UVec4(1u) << tcu::min(bits, UVec4(30))).cast<deInt32>()); 1993 const IVec4 maxV ((UVec4(1u) << (bits - UVec4(1u))).cast<deInt32>()); 1994 const IVec4 clampMax (maxV - 1); 1995 const IVec4 clampMin (-maxV); 1996 std::ostringstream fragmentShader; 1997 1998 fragmentShader << 1999 "#version 450\n" 2000 "layout(location = 0) out highp ivec4 o_color;\n" 2001 "layout(push_constant) uniform PushConstant {\n" 2002 "\thighp uint sampleIndex;\n" 2003 "} pushConstants;\n" 2004 "void main (void)\n" 2005 "{\n" 2006 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n" 2007 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n" 2008 "\thighp int color[4];\n" 2009 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n" 2010 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n"; 2011 2012 for (int ndx = 0; ndx < 4; ndx++) 2013 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n"; 2014 2015 { 2016 const int componentCount = tcu::getNumUsedChannels(format.order); 2017 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 2018 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 2019 deUint32 nextSrcBit = 0; 2020 deUint32 divider = 2; 2021 2022 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 2023 while (nextSrcBit < de::min(bitSize, 10u)) 2024 { 2025 for (int compNdx = 0; compNdx < componentCount; compNdx++) 2026 { 2027 if (dstBitsUsed[compNdx] > bits[compNdx]) 2028 continue; 2029 2030 fragmentShader << 2031 "\tcolor[" << compNdx << "] += " << (range[compNdx] / divider) 2032 << " * int(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n"; 2033 2034 nextSrcBit++; 2035 dstBitsUsed[compNdx]++; 2036 } 2037 2038 divider *= 2; 2039 } 2040 } 2041 2042 // The spec doesn't define whether signed-integers are clamped on output, 2043 // so we'll clamp them explicitly to have well-defined outputs. 2044 fragmentShader << 2045 "\to_color = clamp(ivec4(color[0], color[1], color[2], color[3]), " << 2046 "ivec4" << clampMin << ", ivec4" << clampMax << ");\n" << 2047 "}\n"; 2048 2049 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str()); 2050 break; 2051 } 2052 2053 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 2054 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 2055 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 2056 { 2057 const tcu::TextureFormatInfo info (tcu::getTextureFormatInfo(format)); 2058 const UVec4 bits (tcu::getTextureFormatMantissaBitDepth(format).cast<deUint32>()); 2059 const Vec4 minLimit (-65536.0); 2060 const Vec4 maxLimit (65536.0); 2061 const Vec4 minValue (tcu::max(info.valueMin, minLimit)); 2062 const Vec4 range (tcu::min(info.valueMax, maxLimit) - minValue); 2063 std::ostringstream fragmentShader; 2064 2065 fragmentShader << 2066 "#version 450\n" 2067 "layout(location = 0) out highp vec4 o_color;\n" 2068 "layout(push_constant) uniform PushConstant {\n" 2069 "\thighp uint sampleIndex;\n" 2070 "} pushConstants;\n" 2071 "void main (void)\n" 2072 "{\n" 2073 "\thighp uint sampleIndex = pushConstants.sampleIndex;\n" 2074 "\tgl_SampleMask[0] = int(0x1u << sampleIndex);\n" 2075 "\thighp float color[4];\n" 2076 "\thighp uint x = sampleIndex ^ uint(gl_FragCoord.x);\n" 2077 "\thighp uint y = sampleIndex ^ uint(gl_FragCoord.y);\n"; 2078 2079 for (int ndx = 0; ndx < 4; ndx++) 2080 fragmentShader << "\tcolor[" << ndx << "] = " << minValue[ndx] << ";\n"; 2081 2082 { 2083 const int componentCount = tcu::getNumUsedChannels(format.order); 2084 const deUint32 bitSize (bits[0] + bits[1] + bits[2] + bits[3]); 2085 deUint32 dstBitsUsed[4] = { 0u, 0u, 0u, 0u }; 2086 deUint32 nextSrcBit = 0; 2087 deUint32 divider = 2; 2088 2089 // \note Limited to ten bits since the target is 32x32, so there are 10 input bits 2090 while (nextSrcBit < de::min(bitSize, 10u)) 2091 { 2092 for (int compNdx = 0; compNdx < componentCount; compNdx++) 2093 { 2094 if (dstBitsUsed[compNdx] > bits[compNdx]) 2095 continue; 2096 2097 fragmentShader << 2098 "\tcolor[" << compNdx << "] += " << (range[compNdx] / (float)divider) 2099 << " * float(bitfieldExtract(" << (nextSrcBit % 2 == 0 ? "x" : "y") << ", " << (nextSrcBit / 2) << ", 1));\n"; 2100 2101 nextSrcBit++; 2102 dstBitsUsed[compNdx]++; 2103 } 2104 2105 divider *= 2; 2106 } 2107 } 2108 2109 fragmentShader << 2110 "\to_color = vec4(color[0], color[1], color[2], color[3]);\n" 2111 "}\n"; 2112 2113 dst.glslSources.add("quad-frag") << glu::FragmentSource(fragmentShader.str()); 2114 break; 2115 } 2116 2117 default: 2118 DE_FATAL("Unknown channel class"); 2119 } 2120 } 2121 2122 if (tcu::hasDepthComponent(format.order) || tcu::hasStencilComponent(format.order)) 2123 { 2124 std::ostringstream splitShader; 2125 2126 splitShader << 2127 "#version 450\n"; 2128 2129 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order)) 2130 { 2131 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n" 2132 << "layout(input_attachment_index = 0, set = 0, binding = 1) uniform highp usubpassInputMS i_stencil;\n"; 2133 } 2134 else if (tcu::hasDepthComponent(format.order)) 2135 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp subpassInputMS i_depth;\n"; 2136 else if (tcu::hasStencilComponent(format.order)) 2137 splitShader << "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp usubpassInputMS i_stencil;\n"; 2138 2139 splitShader << 2140 "layout(push_constant) uniform PushConstant {\n" 2141 "\thighp uint splitSubpassIndex;\n" 2142 "} pushConstants;\n"; 2143 2144 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++) 2145 { 2146 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order)) 2147 splitShader << "layout(location = " << attachmentNdx << ") out highp vec2 o_color" << attachmentNdx << ";\n"; 2148 else 2149 splitShader << "layout(location = " << attachmentNdx << ") out highp float o_color" << attachmentNdx << ";\n"; 2150 } 2151 2152 splitShader << 2153 "void main (void)\n" 2154 "{\n"; 2155 2156 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++) 2157 { 2158 if (tcu::hasDepthComponent(format.order)) 2159 splitShader << "\thighp float depth" << attachmentNdx << " = subpassLoad(i_depth, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n"; 2160 2161 if (tcu::hasStencilComponent(format.order)) 2162 splitShader << "\thighp uint stencil" << attachmentNdx << " = subpassLoad(i_stencil, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u)).x;\n"; 2163 2164 if (tcu::hasDepthComponent(format.order) && tcu::hasStencilComponent(format.order)) 2165 splitShader << "\to_color" << attachmentNdx << " = vec2(depth" << attachmentNdx << ", float(stencil" << attachmentNdx << "));\n"; 2166 else if (tcu::hasDepthComponent(format.order)) 2167 splitShader << "\to_color" << attachmentNdx << " = float(depth" << attachmentNdx << ");\n"; 2168 else if (tcu::hasStencilComponent(format.order)) 2169 splitShader << "\to_color" << attachmentNdx << " = float(stencil" << attachmentNdx << ");\n"; 2170 } 2171 2172 splitShader << 2173 "}\n"; 2174 2175 dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str()); 2176 } 2177 else 2178 { 2179 std::string subpassType; 2180 std::string outputType; 2181 2182 switch (channelClass) 2183 { 2184 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 2185 subpassType = "usubpassInputMS"; 2186 outputType = "uvec4"; 2187 break; 2188 2189 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 2190 subpassType = "isubpassInputMS"; 2191 outputType = "ivec4"; 2192 break; 2193 2194 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 2195 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 2196 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 2197 subpassType = "subpassInputMS"; 2198 outputType = "vec4"; 2199 break; 2200 2201 default: 2202 DE_FATAL("Unknown channel class"); 2203 } 2204 2205 std::ostringstream splitShader; 2206 splitShader << 2207 "#version 450\n" 2208 "layout(input_attachment_index = 0, set = 0, binding = 0) uniform highp " << subpassType << " i_color;\n" 2209 "layout(push_constant) uniform PushConstant {\n" 2210 "\thighp uint splitSubpassIndex;\n" 2211 "} pushConstants;\n"; 2212 2213 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++) 2214 splitShader << "layout(location = " << attachmentNdx << ") out highp " << outputType << " o_color" << attachmentNdx << ";\n"; 2215 2216 splitShader << 2217 "void main (void)\n" 2218 "{\n"; 2219 2220 for (deUint32 attachmentNdx = 0; attachmentNdx < de::min((deUint32)MAX_COLOR_ATTACHMENT_COUNT, config.sampleCount); attachmentNdx++) 2221 splitShader << "\to_color" << attachmentNdx << " = subpassLoad(i_color, int(" << MAX_COLOR_ATTACHMENT_COUNT << " * pushConstants.splitSubpassIndex + " << attachmentNdx << "u));\n"; 2222 2223 splitShader << 2224 "}\n"; 2225 2226 dst.glslSources.add("quad-split-frag") << glu::FragmentSource(splitShader.str()); 2227 } 2228 } 2229 }; 2230 2231 std::string formatToName (VkFormat format) 2232 { 2233 const std::string formatStr = de::toString(format); 2234 const std::string prefix = "VK_FORMAT_"; 2235 2236 DE_ASSERT(formatStr.substr(0, prefix.length()) == prefix); 2237 2238 return de::toLower(formatStr.substr(prefix.length())); 2239 } 2240 2241 void initTests (tcu::TestCaseGroup* group) 2242 { 2243 static const VkFormat formats[] = 2244 { 2245 VK_FORMAT_R5G6B5_UNORM_PACK16, 2246 VK_FORMAT_R8_UNORM, 2247 VK_FORMAT_R8_SNORM, 2248 VK_FORMAT_R8_UINT, 2249 VK_FORMAT_R8_SINT, 2250 VK_FORMAT_R8G8_UNORM, 2251 VK_FORMAT_R8G8_SNORM, 2252 VK_FORMAT_R8G8_UINT, 2253 VK_FORMAT_R8G8_SINT, 2254 VK_FORMAT_R8G8B8A8_UNORM, 2255 VK_FORMAT_R8G8B8A8_SNORM, 2256 VK_FORMAT_R8G8B8A8_UINT, 2257 VK_FORMAT_R8G8B8A8_SINT, 2258 VK_FORMAT_R8G8B8A8_SRGB, 2259 VK_FORMAT_A8B8G8R8_UNORM_PACK32, 2260 VK_FORMAT_A8B8G8R8_SNORM_PACK32, 2261 VK_FORMAT_A8B8G8R8_UINT_PACK32, 2262 VK_FORMAT_A8B8G8R8_SINT_PACK32, 2263 VK_FORMAT_A8B8G8R8_SRGB_PACK32, 2264 VK_FORMAT_B8G8R8A8_UNORM, 2265 VK_FORMAT_B8G8R8A8_SRGB, 2266 VK_FORMAT_A2R10G10B10_UNORM_PACK32, 2267 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 2268 VK_FORMAT_A2B10G10R10_UINT_PACK32, 2269 VK_FORMAT_R16_UNORM, 2270 VK_FORMAT_R16_SNORM, 2271 VK_FORMAT_R16_UINT, 2272 VK_FORMAT_R16_SINT, 2273 VK_FORMAT_R16_SFLOAT, 2274 VK_FORMAT_R16G16_UNORM, 2275 VK_FORMAT_R16G16_SNORM, 2276 VK_FORMAT_R16G16_UINT, 2277 VK_FORMAT_R16G16_SINT, 2278 VK_FORMAT_R16G16_SFLOAT, 2279 VK_FORMAT_R16G16B16A16_UNORM, 2280 VK_FORMAT_R16G16B16A16_SNORM, 2281 VK_FORMAT_R16G16B16A16_UINT, 2282 VK_FORMAT_R16G16B16A16_SINT, 2283 VK_FORMAT_R16G16B16A16_SFLOAT, 2284 VK_FORMAT_R32_UINT, 2285 VK_FORMAT_R32_SINT, 2286 VK_FORMAT_R32_SFLOAT, 2287 VK_FORMAT_R32G32_UINT, 2288 VK_FORMAT_R32G32_SINT, 2289 VK_FORMAT_R32G32_SFLOAT, 2290 VK_FORMAT_R32G32B32A32_UINT, 2291 VK_FORMAT_R32G32B32A32_SINT, 2292 VK_FORMAT_R32G32B32A32_SFLOAT, 2293 2294 VK_FORMAT_D16_UNORM, 2295 VK_FORMAT_X8_D24_UNORM_PACK32, 2296 VK_FORMAT_D32_SFLOAT, 2297 VK_FORMAT_S8_UINT, 2298 VK_FORMAT_D16_UNORM_S8_UINT, 2299 VK_FORMAT_D24_UNORM_S8_UINT, 2300 VK_FORMAT_D32_SFLOAT_S8_UINT 2301 }; 2302 const deUint32 sampleCounts[] = 2303 { 2304 2u, 4u, 8u, 16u, 32u 2305 }; 2306 tcu::TestContext& testCtx (group->getTestContext()); 2307 2308 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++) 2309 { 2310 const VkFormat format (formats[formatNdx]); 2311 const std::string formatName (formatToName(format)); 2312 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatName.c_str(), formatName.c_str())); 2313 2314 for (size_t sampleCountNdx = 0; sampleCountNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountNdx++) 2315 { 2316 const deUint32 sampleCount (sampleCounts[sampleCountNdx]); 2317 const std::string testName ("samples_" + de::toString(sampleCount)); 2318 2319 formatGroup->addChild(new InstanceFactory1<MultisampleRenderPassTestInstance, TestConfig, Programs>(testCtx, tcu::NODETYPE_SELF_VALIDATE, testName.c_str(), testName.c_str(), TestConfig(format, sampleCount))); 2320 } 2321 2322 group->addChild(formatGroup.release()); 2323 } 2324 } 2325 2326 } // anonymous 2327 2328 tcu::TestCaseGroup* createRenderPassMultisampleTests (tcu::TestContext& testCtx) 2329 { 2330 return createTestGroup(testCtx, "multisample", "Multisample render pass tests", initTests); 2331 } 2332 2333 } // vkt 2334