1/*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 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 Texture filtering tests with explicit LOD instructions 22 *//*--------------------------------------------------------------------*/ 23 24#include "vktTextureFilteringExplicitLodTests.hpp" 25 26#include "vkDefs.hpp" 27 28#include "vktSampleVerifier.hpp" 29#include "vktShaderExecutor.hpp" 30#include "vktTestCaseUtil.hpp" 31 32#include "vkDeviceUtil.hpp" 33#include "vkImageUtil.hpp" 34#include "vkPlatform.hpp" 35#include "vkRef.hpp" 36#include "vkRefUtil.hpp" 37#include "vkStrUtil.hpp" 38#include "vkTypeUtil.hpp" 39#include "vkQueryUtil.hpp" 40#include "vkMemUtil.hpp" 41 42#include "tcuTexLookupVerifier.hpp" 43#include "tcuTestLog.hpp" 44#include "tcuTexture.hpp" 45#include "tcuTextureUtil.hpp" 46#include "tcuVector.hpp" 47 48#include "deClock.h" 49#include "deMath.h" 50#include "deStringUtil.hpp" 51#include "deUniquePtr.hpp" 52 53#include <sstream> 54#include <string> 55#include <vector> 56 57namespace vkt 58{ 59namespace texture 60{ 61 62using namespace tcu; 63using namespace vk; 64using std::string; 65 66namespace 67{ 68 69tcu::FloatFormat getConversionPrecision (VkFormat format) 70{ 71 const tcu::FloatFormat reallyLow (0, 0, 8, false, tcu::YES); 72 const tcu::FloatFormat fp16 (-14, 15, 10, false); 73 const tcu::FloatFormat fp32 (-126, 127, 23, true); 74 75 switch (format) 76 { 77 case VK_FORMAT_B4G4R4A4_UNORM_PACK16: 78 case VK_FORMAT_R5G6B5_UNORM_PACK16: 79 case VK_FORMAT_A1R5G5B5_UNORM_PACK16: 80 return reallyLow; 81 82 case VK_FORMAT_R8_UNORM: 83 case VK_FORMAT_R8_SNORM: 84 case VK_FORMAT_R8G8_UNORM: 85 case VK_FORMAT_R8G8_SNORM: 86 case VK_FORMAT_R8G8B8A8_UNORM: 87 case VK_FORMAT_R8G8B8A8_SNORM: 88 case VK_FORMAT_B8G8R8A8_UNORM: 89 case VK_FORMAT_A8B8G8R8_UNORM_PACK32: 90 case VK_FORMAT_A8B8G8R8_SNORM_PACK32: 91 case VK_FORMAT_A2B10G10R10_UNORM_PACK32: 92 return fp16; 93 94 case VK_FORMAT_R16_SFLOAT: 95 case VK_FORMAT_R16G16_SFLOAT: 96 case VK_FORMAT_R16G16B16A16_SFLOAT: 97 return fp16; 98 99 case VK_FORMAT_R32_SFLOAT: 100 case VK_FORMAT_R32G32_SFLOAT: 101 case VK_FORMAT_R32G32B32A32_SFLOAT: 102 return fp32; 103 104 default: 105 DE_FATAL("Precision not defined for format"); 106 return fp32; 107 } 108} 109 110tcu::FloatFormat getFilteringPrecision (VkFormat format) 111{ 112 const tcu::FloatFormat reallyLow (0, 0, 6, false, tcu::YES); 113 const tcu::FloatFormat low (0, 0, 7, false, tcu::YES); 114 const tcu::FloatFormat fp16 (-14, 15, 10, false); 115 const tcu::FloatFormat fp32 (-126, 127, 23, true); 116 117 switch (format) 118 { 119 case VK_FORMAT_B4G4R4A4_UNORM_PACK16: 120 case VK_FORMAT_R5G6B5_UNORM_PACK16: 121 case VK_FORMAT_A1R5G5B5_UNORM_PACK16: 122 return reallyLow; 123 124 case VK_FORMAT_R8_UNORM: 125 case VK_FORMAT_R8_SNORM: 126 case VK_FORMAT_R8G8_UNORM: 127 case VK_FORMAT_R8G8_SNORM: 128 case VK_FORMAT_R8G8B8A8_UNORM: 129 case VK_FORMAT_R8G8B8A8_SNORM: 130 case VK_FORMAT_B8G8R8A8_UNORM: 131 case VK_FORMAT_A8B8G8R8_UNORM_PACK32: 132 case VK_FORMAT_A8B8G8R8_SNORM_PACK32: 133 case VK_FORMAT_A2B10G10R10_UNORM_PACK32: 134 return low; 135 136 case VK_FORMAT_R16_SFLOAT: 137 case VK_FORMAT_R16G16_SFLOAT: 138 case VK_FORMAT_R16G16B16A16_SFLOAT: 139 return fp16; 140 141 case VK_FORMAT_R32_SFLOAT: 142 case VK_FORMAT_R32G32_SFLOAT: 143 case VK_FORMAT_R32G32B32A32_SFLOAT: 144 return fp32; 145 146 default: 147 DE_FATAL("Precision not defined for format"); 148 return fp32; 149 } 150} 151 152using namespace shaderexecutor; 153 154string genSamplerDeclaration(const ImageViewParameters& imParams, 155 const SamplerParameters& samplerParams) 156{ 157 string result = "sampler"; 158 159 switch (imParams.dim) 160 { 161 case IMG_DIM_1D: 162 result += "1D"; 163 break; 164 165 case IMG_DIM_2D: 166 result += "2D"; 167 break; 168 169 case IMG_DIM_3D: 170 result += "3D"; 171 break; 172 173 case IMG_DIM_CUBE: 174 result += "Cube"; 175 break; 176 177 default: 178 break; 179 } 180 181 if (imParams.isArrayed) 182 { 183 result += "Array"; 184 } 185 186 if (samplerParams.isCompare) 187 { 188 result += "Shadow"; 189 } 190 191 return result; 192} 193 194string genLookupCode(const ImageViewParameters& imParams, 195 const SamplerParameters& samplerParams, 196 const SampleLookupSettings& lookupSettings) 197{ 198 int dim = -1; 199 200 switch (imParams.dim) 201 { 202 case IMG_DIM_1D: 203 dim = 1; 204 break; 205 206 case IMG_DIM_2D: 207 dim = 2; 208 break; 209 210 case IMG_DIM_3D: 211 dim = 3; 212 break; 213 214 case IMG_DIM_CUBE: 215 dim = 3; 216 break; 217 218 default: 219 dim = 0; 220 break; 221 } 222 223 DE_ASSERT(dim >= 1 && dim <= 3); 224 225 int numCoordComp = dim; 226 227 if (lookupSettings.isProjective) 228 { 229 ++numCoordComp; 230 } 231 232 int numArgComp = numCoordComp; 233 bool hasSeparateCompare = false; 234 235 if (imParams.isArrayed) 236 { 237 DE_ASSERT(!lookupSettings.isProjective && "Can't do a projective lookup on an arrayed image!"); 238 239 ++numArgComp; 240 } 241 242 if (samplerParams.isCompare && numCoordComp == 4) 243 { 244 hasSeparateCompare = true; 245 } 246 else if (samplerParams.isCompare) 247 { 248 ++numArgComp; 249 } 250 251 // Build coordinate input to texture*() function 252 253 string arg = "vec"; 254 arg += (char) (numArgComp + '0'); 255 arg += "(vec"; 256 arg += (char) (numCoordComp + '0'); 257 arg += "(coord)"; 258 259 int numZero = numArgComp - numCoordComp; 260 261 if (imParams.isArrayed) 262 { 263 arg += ", layer"; 264 --numZero; 265 } 266 267 if (samplerParams.isCompare && !hasSeparateCompare) 268 { 269 arg += ", dRef"; 270 --numZero; 271 } 272 273 for (int ndx = 0; ndx < numZero; ++ndx) 274 { 275 arg += ", 0.0"; 276 } 277 278 arg += ")"; 279 280 // Build call to texture*() function 281 282 string code; 283 284 code += "result = texture"; 285 286 if (lookupSettings.isProjective) 287 { 288 code += "Proj"; 289 } 290 291 if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES) 292 { 293 code += "Grad"; 294 } 295 else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD) 296 { 297 code += "Lod"; 298 } 299 300 code += "(testSampler, "; 301 code += arg; 302 303 if (samplerParams.isCompare && hasSeparateCompare) 304 { 305 code += ", dRef"; 306 } 307 308 if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES) 309 { 310 code += ", vec"; 311 code += (char) (numCoordComp + '0'); 312 code += "(dPdx), "; 313 code += "vec"; 314 code += (char) (numCoordComp + '0'); 315 code += "(dPdy)"; 316 } 317 else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD) 318 { 319 code += ", lod"; 320 } 321 322 code += ");"; 323 324 return code; 325} 326 327void initializeImage(Context& ctx, VkImage im, const ConstPixelBufferAccess* pba, ImageViewParameters imParams) 328{ 329 const DeviceInterface& vkd = ctx.getDeviceInterface(); 330 const VkDevice dev = ctx.getDevice(); 331 const deUint32 uqfi = ctx.getUniversalQueueFamilyIndex(); 332 333 const VkDeviceSize bufSize = 334 getPixelSize(mapVkFormat(imParams.format)) 335 * imParams.arrayLayers 336 * imParams.size[0] 337 * imParams.size[1] 338 * imParams.size[2] 339 * 2; 340 341 const VkBufferCreateInfo bufCreateInfo = 342 { 343 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType 344 DE_NULL, // pNext 345 0, // flags 346 bufSize, // size 347 VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage 348 VK_SHARING_MODE_EXCLUSIVE, // sharingMode 349 1, // queueFamilyIndexCount 350 &uqfi // pQueueFamilyIndices 351 }; 352 353 Unique<VkBuffer> buf(createBuffer(vkd, dev, &bufCreateInfo)); 354 355 VkMemoryRequirements bufMemReq; 356 vkd.getBufferMemoryRequirements(dev, buf.get(), &bufMemReq); 357 358 de::UniquePtr<Allocation> bufMem(ctx.getDefaultAllocator().allocate(bufMemReq, MemoryRequirement::HostVisible)); 359 VK_CHECK(vkd.bindBufferMemory(dev, buf.get(), bufMem->getMemory(), bufMem->getOffset())); 360 361 const VkCommandPoolCreateInfo copyPoolCreateInfo = 362 { 363 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, 364 DE_NULL, 365 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, 366 uqfi 367 }; 368 369 Unique<VkCommandPool> copyPool(createCommandPool(vkd, dev, ©PoolCreateInfo)); 370 371 const VkCommandBufferAllocateInfo copyBufferCreateInfo = 372 { 373 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, 374 DE_NULL, 375 copyPool.get(), 376 VK_COMMAND_BUFFER_LEVEL_PRIMARY, 377 1 378 }; 379 380 Unique<VkCommandBuffer> copyBuffer(allocateCommandBuffer(vkd, dev, ©BufferCreateInfo)); 381 382 std::vector<VkBufferImageCopy> copyRegions; 383 384 deUint8* const bufMapPtr = reinterpret_cast<deUint8*>(bufMem->getHostPtr()); 385 deUint8* bufCurPtr = bufMapPtr; 386 387 for (int level = 0; level < imParams.levels; ++level) 388 { 389 const IVec3 curLevelSize = pba[level].getSize(); 390 391 const std::size_t copySize = 392 getPixelSize(mapVkFormat(imParams.format)) 393 * curLevelSize[0] * curLevelSize[1] * curLevelSize[2] 394 * imParams.arrayLayers; 395 396 deMemcpy(bufCurPtr, pba[level].getDataPtr(), copySize); 397 398 flushMappedMemoryRange(vkd, dev, bufMem->getMemory(), bufMem->getOffset() + (bufCurPtr - bufMapPtr), copySize); 399 400 const VkImageSubresourceLayers curSubresource = 401 { 402 VK_IMAGE_ASPECT_COLOR_BIT, 403 (deUint32)level, 404 0, 405 (deUint32)imParams.arrayLayers 406 }; 407 408 const VkBufferImageCopy curRegion = 409 { 410 (VkDeviceSize) (bufCurPtr - bufMapPtr), 411 0, 412 0, 413 curSubresource, 414 {0U, 0U, 0U}, 415 {(deUint32)curLevelSize[0], (deUint32)curLevelSize[1], (deUint32)curLevelSize[2]} 416 }; 417 418 copyRegions.push_back(curRegion); 419 420 bufCurPtr += copySize; 421 } 422 423 const VkCommandBufferBeginInfo beginInfo = 424 { 425 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 426 DE_NULL, 427 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 428 DE_NULL 429 }; 430 431 VK_CHECK(vkd.beginCommandBuffer(copyBuffer.get(), &beginInfo)); 432 433 const VkImageSubresourceRange imMemBarSubRange = 434 { 435 VK_IMAGE_ASPECT_COLOR_BIT, 436 0, 437 (deUint32)imParams.levels, 438 0, 439 (deUint32)imParams.arrayLayers 440 }; 441 442 VkImageMemoryBarrier imMemBar = 443 { 444 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 445 DE_NULL, 446 0, 447 VK_ACCESS_TRANSFER_WRITE_BIT, 448 VK_IMAGE_LAYOUT_UNDEFINED, 449 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 450 VK_QUEUE_FAMILY_IGNORED, 451 VK_QUEUE_FAMILY_IGNORED, 452 im, 453 imMemBarSubRange 454 }; 455 456 VkBufferMemoryBarrier bufMemBar = 457 { 458 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, 459 DE_NULL, 460 VK_ACCESS_HOST_WRITE_BIT, 461 VK_ACCESS_TRANSFER_READ_BIT, 462 VK_QUEUE_FAMILY_IGNORED, 463 VK_QUEUE_FAMILY_IGNORED, 464 buf.get(), 465 0, 466 bufSize 467 }; 468 469 vkd.cmdPipelineBarrier(copyBuffer.get(), 470 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 471 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 472 0, 473 0, 474 DE_NULL, 475 1, 476 &bufMemBar, 477 1, 478 &imMemBar); 479 480 vkd.cmdCopyBufferToImage(copyBuffer.get(), 481 buf.get(), 482 im, 483 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 484 (deUint32)copyRegions.size(), 485 ©Regions[0]); 486 487 imMemBar.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; 488 imMemBar.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; 489 imMemBar.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; 490 imMemBar.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; 491 492 vkd.cmdPipelineBarrier(copyBuffer.get(), 493 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 494 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 495 0, 496 0, 497 DE_NULL, 498 0, 499 DE_NULL, 500 1, 501 &imMemBar); 502 503 VK_CHECK(vkd.endCommandBuffer(copyBuffer.get())); 504 505 const VkSubmitInfo copySubmitInfo = 506 { 507 VK_STRUCTURE_TYPE_SUBMIT_INFO, 508 DE_NULL, 509 0, 510 DE_NULL, 511 DE_NULL, 512 1, 513 &(copyBuffer.get()), 514 0, 515 DE_NULL 516 }; 517 518 VK_CHECK(vkd.queueSubmit(ctx.getUniversalQueue(), 1, ©SubmitInfo, 0)); 519 VK_CHECK(vkd.queueWaitIdle(ctx.getUniversalQueue())); 520} 521 522struct TestCaseData 523{ 524 std::vector<ConstPixelBufferAccess> pba; 525 ImageViewParameters imParams; 526 SamplerParameters samplerParams; 527 SampleLookupSettings sampleLookupSettings; 528 glu::ShaderType shaderType; 529}; 530 531VkSamplerCreateInfo mapSamplerCreateInfo (const SamplerParameters& samplerParams) 532{ 533 VkSamplerCreateInfo samplerCreateInfo = 534 { 535 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // sType 536 DE_NULL, // pNext 537 0U, // flags 538 samplerParams.magFilter, // magFilter 539 samplerParams.minFilter, // minFilter 540 samplerParams.mipmapFilter, // mipmapMode 541 samplerParams.wrappingModeU, // addressModeU 542 samplerParams.wrappingModeV, // addressModeV 543 samplerParams.wrappingModeW, // addressMoveW 544 samplerParams.lodBias, // mipLodBias 545 VK_FALSE, // anisotropyEnable 546 1.0f, // maxAnisotropy 547 VK_FALSE, // compareEnable 548 VK_COMPARE_OP_NEVER, // compareOp 549 samplerParams.minLod, // minLod 550 samplerParams.maxLod, // maxLod 551 samplerParams.borderColor, // borderColor 552 samplerParams.isUnnormalized ? VK_TRUE : VK_FALSE, // unnormalizedCoordinates 553 }; 554 555 if (samplerParams.isCompare) 556 { 557 samplerCreateInfo.compareEnable = VK_TRUE; 558 559 DE_FATAL("Not implemented"); 560 } 561 562 return samplerCreateInfo; 563} 564 565VkImageType mapImageType (ImgDim dim) 566{ 567 VkImageType imType; 568 569 switch (dim) 570 { 571 case IMG_DIM_1D: 572 imType = VK_IMAGE_TYPE_1D; 573 break; 574 575 case IMG_DIM_2D: 576 case IMG_DIM_CUBE: 577 imType = VK_IMAGE_TYPE_2D; 578 break; 579 580 case IMG_DIM_3D: 581 imType = VK_IMAGE_TYPE_3D; 582 break; 583 584 default: 585 imType = VK_IMAGE_TYPE_LAST; 586 break; 587 } 588 589 return imType; 590} 591 592VkImageViewType mapImageViewType (const ImageViewParameters& imParams) 593{ 594 VkImageViewType imViewType; 595 596 if (imParams.isArrayed) 597 { 598 switch (imParams.dim) 599 { 600 case IMG_DIM_1D: 601 imViewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY; 602 break; 603 604 case IMG_DIM_2D: 605 imViewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY; 606 break; 607 608 case IMG_DIM_CUBE: 609 imViewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY; 610 break; 611 612 default: 613 imViewType = VK_IMAGE_VIEW_TYPE_LAST; 614 break; 615 } 616 } 617 else 618 { 619 switch (imParams.dim) 620 { 621 case IMG_DIM_1D: 622 imViewType = VK_IMAGE_VIEW_TYPE_1D; 623 break; 624 625 case IMG_DIM_2D: 626 imViewType = VK_IMAGE_VIEW_TYPE_2D; 627 break; 628 629 case IMG_DIM_3D: 630 imViewType = VK_IMAGE_VIEW_TYPE_3D; 631 break; 632 633 case IMG_DIM_CUBE: 634 imViewType = VK_IMAGE_VIEW_TYPE_CUBE; 635 break; 636 637 default: 638 imViewType = VK_IMAGE_VIEW_TYPE_LAST; 639 break; 640 } 641 } 642 643 return imViewType; 644} 645 646class DataGenerator 647{ 648public: 649 virtual ~DataGenerator (void) {} 650 651 virtual bool generate (void) = 0; 652 653 virtual std::vector<ConstPixelBufferAccess> getPba (void) const = 0; 654 virtual std::vector<SampleArguments> getSampleArgs (void) const = 0; 655 656protected: 657 DataGenerator (void) {} 658}; 659 660class TextureFilteringTestInstance : public TestInstance 661{ 662public: 663 TextureFilteringTestInstance (Context& ctx, 664 const TestCaseData& testCaseData, 665 const ShaderSpec& shaderSpec, 666 de::MovePtr<DataGenerator> gen); 667 668 virtual TestStatus iterate (void) { return runTest(); } 669 670protected: 671 TestStatus runTest (void); 672 bool isSupported (void); 673 void createResources (void); 674 void execute (void); 675 bool verify (void); 676 677 tcu::Sampler mapTcuSampler (void) const; 678 679 const glu::ShaderType m_shaderType; 680 const ShaderSpec m_shaderSpec; 681 const ImageViewParameters m_imParams; 682 const SamplerParameters m_samplerParams; 683 const SampleLookupSettings m_sampleLookupSettings; 684 685 std::vector<SampleArguments> m_sampleArguments; 686 deUint32 m_numSamples; 687 688 de::MovePtr<Allocation> m_imAllocation; 689 Move<VkImage> m_im; 690 Move<VkImageView> m_imView; 691 Move<VkSampler> m_sampler; 692 693 Move<VkDescriptorSetLayout> m_extraResourcesLayout; 694 Move<VkDescriptorPool> m_extraResourcesPool; 695 Move<VkDescriptorSet> m_extraResourcesSet; 696 697 de::MovePtr<ShaderExecutor> m_executor; 698 699 std::vector<ConstPixelBufferAccess> m_levels; 700 de::MovePtr<DataGenerator> m_gen; 701 702 std::vector<Vec4> m_resultSamples; 703 std::vector<Vec4> m_resultCoords; 704}; 705 706TextureFilteringTestInstance::TextureFilteringTestInstance (Context& ctx, 707 const TestCaseData& testCaseData, 708 const ShaderSpec& shaderSpec, 709 de::MovePtr<DataGenerator> gen) 710 : TestInstance (ctx) 711 , m_shaderType (testCaseData.shaderType) 712 , m_shaderSpec (shaderSpec) 713 , m_imParams (testCaseData.imParams) 714 , m_samplerParams (testCaseData.samplerParams) 715 , m_sampleLookupSettings (testCaseData.sampleLookupSettings) 716 , m_levels (testCaseData.pba) 717 , m_gen (gen.release()) 718{ 719 for (deUint8 compNdx = 0; compNdx < 3; ++compNdx) 720 DE_ASSERT(m_imParams.size[compNdx] > 0); 721} 722 723TestStatus TextureFilteringTestInstance::runTest (void) 724{ 725 if (!isSupported()) 726 TCU_THROW(NotSupportedError, "Unsupported combination of filtering and image format"); 727 728 TCU_CHECK(m_gen->generate()); 729 m_levels = m_gen->getPba(); 730 731 m_sampleArguments = m_gen->getSampleArgs(); 732 m_numSamples = (deUint32)m_sampleArguments.size(); 733 734 createResources(); 735 initializeImage(m_context, m_im.get(), &m_levels[0], m_imParams); 736 737 deUint64 startTime, endTime; 738 739 startTime = deGetMicroseconds(); 740 execute(); 741 endTime = deGetMicroseconds(); 742 743 m_context.getTestContext().getLog() << TestLog::Message 744 << "Execution time: " 745 << endTime - startTime 746 << "us" 747 << TestLog::EndMessage; 748 749 startTime = deGetMicroseconds(); 750 bool result = verify(); 751 endTime = deGetMicroseconds(); 752 753 m_context.getTestContext().getLog() << TestLog::Message 754 << "Verification time: " 755 << endTime - startTime 756 << "us" 757 << TestLog::EndMessage; 758 759 if (result) 760 { 761 return TestStatus::pass("Success"); 762 } 763 else 764 { 765 // \todo [2016-06-24 collinbaker] Print report if verification fails 766 return TestStatus::fail("Verification failed"); 767 } 768} 769 770bool TextureFilteringTestInstance::verify (void) 771{ 772 // \todo [2016-06-24 collinbaker] Handle cubemaps 773 774 const int coordBits = (int)m_context.getDeviceProperties().limits.subTexelPrecisionBits; 775 const int mipmapBits = (int)m_context.getDeviceProperties().limits.mipmapPrecisionBits; 776 const int maxPrintedFailures = 5; 777 int failCount = 0; 778 779 const SampleVerifier verifier (m_imParams, 780 m_samplerParams, 781 m_sampleLookupSettings, 782 coordBits, 783 mipmapBits, 784 getConversionPrecision(m_imParams.format), 785 getFilteringPrecision(m_imParams.format), 786 m_levels); 787 788 789 for (deUint32 sampleNdx = 0; sampleNdx < m_numSamples; ++sampleNdx) 790 { 791 if (!verifier.verifySample(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx])) 792 { 793 if (failCount++ < maxPrintedFailures) 794 { 795 // Re-run with report logging 796 std::string report; 797 verifier.verifySampleReport(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx], report); 798 799 m_context.getTestContext().getLog() 800 << TestLog::Section("Failed sample", "Failed sample") 801 << TestLog::Message 802 << "Sample " << sampleNdx << ".\n" 803 << "\tCoordinate: " << m_sampleArguments[sampleNdx].coord << "\n" 804 << "\tLOD: " << m_sampleArguments[sampleNdx].lod << "\n" 805 << "\tGPU Result: " << m_resultSamples[sampleNdx] << "\n\n" 806 << "Failure report:\n" << report << "\n" 807 << TestLog::EndMessage 808 << TestLog::EndSection; 809 } 810 } 811 } 812 813 m_context.getTestContext().getLog() 814 << TestLog::Message 815 << "Passed " << m_numSamples - failCount << " out of " << m_numSamples << "." 816 << TestLog::EndMessage; 817 818 return failCount == 0; 819} 820 821void TextureFilteringTestInstance::execute (void) 822{ 823 std::vector<float> coords, layers, dRefs, dPdxs, dPdys, lods; 824 825 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx) 826 { 827 const SampleArguments& sampleArgs = m_sampleArguments[ndx]; 828 829 for (deUint8 compNdx = 0; compNdx < 4; ++compNdx) 830 { 831 coords.push_back(sampleArgs.coord[compNdx]); 832 dPdxs .push_back(sampleArgs.dPdx[compNdx]); 833 dPdys .push_back(sampleArgs.dPdy[compNdx]); 834 } 835 836 layers.push_back(sampleArgs.layer); 837 dRefs .push_back(sampleArgs.dRef); 838 lods .push_back(sampleArgs.lod); 839 } 840 841 const void* inputs[6] = 842 { 843 reinterpret_cast<const void*>(&coords[0]), 844 reinterpret_cast<const void*>(&layers[0]), 845 reinterpret_cast<const void*>(&dRefs[0]), 846 reinterpret_cast<const void*>(&dPdxs[0]), 847 reinterpret_cast<const void*>(&dPdys[0]), 848 reinterpret_cast<const void*>(&lods[0]) 849 }; 850 851 // Staging buffers; data will be copied into vectors of Vec4 852 // \todo [2016-06-24 collinbaker] Figure out if I actually need to 853 // use staging buffers 854 std::vector<float> resultSamplesTemp(m_numSamples * 4); 855 std::vector<float> resultCoordsTemp (m_numSamples * 4); 856 857 void* outputs[2] = 858 { 859 reinterpret_cast<void*>(&resultSamplesTemp[0]), 860 reinterpret_cast<void*>(&resultCoordsTemp[0]) 861 }; 862 863 m_executor->execute(m_numSamples, inputs, outputs, *m_extraResourcesSet); 864 865 m_resultSamples.resize(m_numSamples); 866 m_resultCoords .resize(m_numSamples); 867 868 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx) 869 { 870 m_resultSamples[ndx] = Vec4(resultSamplesTemp[4 * ndx + 0], 871 resultSamplesTemp[4 * ndx + 1], 872 resultSamplesTemp[4 * ndx + 2], 873 resultSamplesTemp[4 * ndx + 3]); 874 875 m_resultCoords [ndx] = Vec4(resultCoordsTemp [4 * ndx + 0], 876 resultCoordsTemp [4 * ndx + 1], 877 resultCoordsTemp [4 * ndx + 2], 878 resultCoordsTemp [4 * ndx + 3]); 879 } 880} 881 882void TextureFilteringTestInstance::createResources (void) 883{ 884 // Create VkImage 885 886 const DeviceInterface& vkd = m_context.getDeviceInterface(); 887 const VkDevice device = m_context.getDevice(); 888 889 const deUint32 queueFamily = m_context.getUniversalQueueFamilyIndex(); 890 const VkImageCreateFlags imCreateFlags =(m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0; 891 892 const VkImageCreateInfo imCreateInfo = 893 { 894 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 895 DE_NULL, 896 imCreateFlags, 897 mapImageType(m_imParams.dim), 898 m_imParams.format, 899 makeExtent3D(m_imParams.size[0], m_imParams.size[1], m_imParams.size[2]), 900 (deUint32)m_imParams.levels, 901 (deUint32)m_imParams.arrayLayers, 902 VK_SAMPLE_COUNT_1_BIT, 903 VK_IMAGE_TILING_OPTIMAL, 904 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 905 VK_SHARING_MODE_EXCLUSIVE, 906 1, 907 &queueFamily, 908 VK_IMAGE_LAYOUT_UNDEFINED 909 }; 910 911 m_im = createImage(vkd, device, &imCreateInfo); 912 913 // Allocate memory for image 914 915 VkMemoryRequirements imMemReq; 916 vkd.getImageMemoryRequirements(device, m_im.get(), &imMemReq); 917 918 m_imAllocation = m_context.getDefaultAllocator().allocate(imMemReq, MemoryRequirement::Any); 919 VK_CHECK(vkd.bindImageMemory(device, m_im.get(), m_imAllocation->getMemory(), m_imAllocation->getOffset())); 920 921 // Create VkImageView 922 923 // \todo [2016-06-23 collinbaker] Pick aspectMask based on image type (i.e. support depth and/or stencil images) 924 DE_ASSERT(m_imParams.dim != IMG_DIM_CUBE); // \todo Support cube maps 925 const VkImageSubresourceRange imViewSubresourceRange = 926 { 927 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask 928 0, // baseMipLevel 929 (deUint32)m_imParams.levels, // levelCount 930 0, // baseArrayLayer 931 (deUint32)m_imParams.arrayLayers // layerCount 932 }; 933 934 const VkComponentMapping imViewCompMap = 935 { 936 VK_COMPONENT_SWIZZLE_R, 937 VK_COMPONENT_SWIZZLE_G, 938 VK_COMPONENT_SWIZZLE_B, 939 VK_COMPONENT_SWIZZLE_A 940 }; 941 942 const VkImageViewCreateInfo imViewCreateInfo = 943 { 944 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType 945 DE_NULL, // pNext 946 0, // flags 947 m_im.get(), // image 948 mapImageViewType(m_imParams), // viewType 949 m_imParams.format, // format 950 imViewCompMap, // components 951 imViewSubresourceRange // subresourceRange 952 }; 953 954 m_imView = createImageView(vkd, device, &imViewCreateInfo); 955 956 // Create VkSampler 957 958 const VkSamplerCreateInfo samplerCreateInfo = mapSamplerCreateInfo(m_samplerParams); 959 m_sampler = createSampler(vkd, device, &samplerCreateInfo); 960 961 // Create additional descriptors 962 963 { 964 const VkDescriptorSetLayoutBinding bindings[] = 965 { 966 { 0u, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u, VK_SHADER_STAGE_ALL, DE_NULL }, 967 }; 968 const VkDescriptorSetLayoutCreateInfo layoutInfo = 969 { 970 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 971 DE_NULL, 972 (VkDescriptorSetLayoutCreateFlags)0u, 973 DE_LENGTH_OF_ARRAY(bindings), 974 bindings, 975 }; 976 977 m_extraResourcesLayout = createDescriptorSetLayout(vkd, device, &layoutInfo); 978 } 979 980 { 981 const VkDescriptorPoolSize poolSizes[] = 982 { 983 { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u }, 984 }; 985 const VkDescriptorPoolCreateInfo poolInfo = 986 { 987 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 988 DE_NULL, 989 (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 990 1u, // maxSets 991 DE_LENGTH_OF_ARRAY(poolSizes), 992 poolSizes, 993 }; 994 995 m_extraResourcesPool = createDescriptorPool(vkd, device, &poolInfo); 996 } 997 998 { 999 const VkDescriptorSetAllocateInfo allocInfo = 1000 { 1001 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 1002 DE_NULL, 1003 *m_extraResourcesPool, 1004 1u, 1005 &m_extraResourcesLayout.get(), 1006 }; 1007 1008 m_extraResourcesSet = allocateDescriptorSet(vkd, device, &allocInfo); 1009 } 1010 1011 { 1012 const VkDescriptorImageInfo imageInfo = 1013 { 1014 *m_sampler, 1015 *m_imView, 1016 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL 1017 }; 1018 const VkWriteDescriptorSet descriptorWrite = 1019 { 1020 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 1021 DE_NULL, 1022 *m_extraResourcesSet, 1023 0u, // dstBinding 1024 0u, // dstArrayElement 1025 1u, 1026 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1027 &imageInfo, 1028 (const VkDescriptorBufferInfo*)DE_NULL, 1029 (const VkBufferView*)DE_NULL, 1030 }; 1031 1032 vkd.updateDescriptorSets(device, 1u, &descriptorWrite, 0u, DE_NULL); 1033 } 1034 1035 m_executor = de::MovePtr<ShaderExecutor>(createExecutor(m_context, m_shaderType, m_shaderSpec, *m_extraResourcesLayout)); 1036} 1037 1038VkFormatFeatureFlags getRequiredFormatFeatures (const SamplerParameters& samplerParams) 1039{ 1040 VkFormatFeatureFlags features = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; 1041 1042 if (samplerParams.minFilter == VK_FILTER_LINEAR || 1043 samplerParams.magFilter == VK_FILTER_LINEAR || 1044 samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR) 1045 { 1046 features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT; 1047 } 1048 1049 return features; 1050} 1051 1052bool TextureFilteringTestInstance::isSupported (void) 1053{ 1054 const VkImageCreateFlags imCreateFlags = (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0; 1055 const VkFormatFeatureFlags reqImFeatures = getRequiredFormatFeatures(m_samplerParams); 1056 1057 const VkImageFormatProperties imFormatProperties = getPhysicalDeviceImageFormatProperties(m_context.getInstanceInterface(), 1058 m_context.getPhysicalDevice(), 1059 m_imParams.format, 1060 mapImageType(m_imParams.dim), 1061 VK_IMAGE_TILING_OPTIMAL, 1062 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, 1063 imCreateFlags); 1064 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(m_context.getInstanceInterface(), 1065 m_context.getPhysicalDevice(), 1066 m_imParams.format); 1067 1068 // \todo [2016-06-23 collinbaker] Check image parameters against imFormatProperties 1069 DE_UNREF(imFormatProperties); 1070 1071 return (formatProperties.optimalTilingFeatures & reqImFeatures) == reqImFeatures; 1072} 1073 1074class TextureFilteringTestCase : public TestCase 1075{ 1076public: 1077 TextureFilteringTestCase (tcu::TestContext& testCtx, 1078 const char* name, 1079 const char* description) 1080 : TestCase(testCtx, name, description) 1081 { 1082 } 1083 1084 void initSpec (void); 1085 1086 virtual void initPrograms (vk::SourceCollections& programCollection) const 1087 { 1088 generateSources(m_testCaseData.shaderType, m_shaderSpec, programCollection); 1089 } 1090 1091 virtual de::MovePtr<DataGenerator> createGenerator (void) const = 0; 1092 1093 virtual TestInstance* createInstance (Context& ctx) const 1094 { 1095 return new TextureFilteringTestInstance(ctx, m_testCaseData, m_shaderSpec, createGenerator()); 1096 } 1097 1098protected: 1099 de::MovePtr<ShaderExecutor> m_executor; 1100 TestCaseData m_testCaseData; 1101 ShaderSpec m_shaderSpec; 1102}; 1103 1104void TextureFilteringTestCase::initSpec (void) 1105{ 1106 m_shaderSpec.source = genLookupCode(m_testCaseData.imParams, 1107 m_testCaseData.samplerParams, 1108 m_testCaseData.sampleLookupSettings); 1109 m_shaderSpec.source += "\nsampledCoord = coord;"; 1110 1111 m_shaderSpec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP))); 1112 m_shaderSpec.outputs.push_back(Symbol("sampledCoord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP))); 1113 m_shaderSpec.inputs .push_back(Symbol("coord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP))); 1114 m_shaderSpec.inputs .push_back(Symbol("layer", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP))); 1115 m_shaderSpec.inputs .push_back(Symbol("dRef", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP))); 1116 m_shaderSpec.inputs .push_back(Symbol("dPdx", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP))); 1117 m_shaderSpec.inputs .push_back(Symbol("dPdy", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP))); 1118 m_shaderSpec.inputs .push_back(Symbol("lod", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP))); 1119 1120 m_shaderSpec.globalDeclarations = "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=0) uniform highp "; 1121 m_shaderSpec.globalDeclarations += genSamplerDeclaration(m_testCaseData.imParams, 1122 m_testCaseData.samplerParams); 1123 m_shaderSpec.globalDeclarations += " testSampler;"; 1124} 1125 1126class Texture2DGradientTestCase : public TextureFilteringTestCase 1127{ 1128public: 1129 Texture2DGradientTestCase (TestContext& testCtx, 1130 const char* name, 1131 const char* desc, 1132 TextureFormat format, 1133 IVec3 dimensions, 1134 VkFilter magFilter, 1135 VkFilter minFilter, 1136 VkSamplerMipmapMode mipmapFilter, 1137 VkSamplerAddressMode wrappingMode, 1138 bool useDerivatives) 1139 1140 : TextureFilteringTestCase (testCtx, name, desc) 1141 , m_format (format) 1142 , m_dimensions (dimensions) 1143 , m_magFilter (magFilter) 1144 , m_minFilter (minFilter) 1145 , m_mipmapFilter (mipmapFilter) 1146 , m_wrappingMode (wrappingMode) 1147 , m_useDerivatives (useDerivatives) 1148 { 1149 m_testCaseData = genTestCaseData(); 1150 initSpec(); 1151 } 1152 1153protected: 1154 class Generator; 1155 1156 virtual de::MovePtr<DataGenerator> createGenerator (void) const; 1157 1158 TestCaseData genTestCaseData() 1159 { 1160 // Generate grid 1161 1162 const SampleLookupSettings sampleLookupSettings = 1163 { 1164 m_useDerivatives ? LOOKUP_LOD_MODE_DERIVATIVES : LOOKUP_LOD_MODE_LOD, // lookupLodMode 1165 false, // hasLodBias 1166 false, // isProjective 1167 }; 1168 1169 const SamplerParameters samplerParameters = 1170 { 1171 m_magFilter, 1172 m_minFilter, 1173 m_mipmapFilter, 1174 m_wrappingMode, 1175 m_wrappingMode, 1176 m_wrappingMode, 1177 VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, 1178 0.0f, 1179 -1.0f, 1180 50.0f, 1181 false, 1182 false 1183 }; 1184 1185 const deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_dimensions[0], 1186 m_dimensions[1]))); 1187 1188 const ImageViewParameters imParameters = 1189 { 1190 IMG_DIM_2D, 1191 mapTextureFormat(m_format), 1192 m_dimensions, 1193 numLevels, 1194 false, 1195 1, 1196 }; 1197 1198 const TestCaseData data = 1199 { 1200 std::vector<ConstPixelBufferAccess>(), 1201 imParameters, 1202 samplerParameters, 1203 sampleLookupSettings, 1204 glu::SHADERTYPE_FRAGMENT 1205 }; 1206 1207 return data; 1208 } 1209 1210private: 1211 const TextureFormat m_format; 1212 const IVec3 m_dimensions; 1213 const VkFilter m_magFilter; 1214 const VkFilter m_minFilter; 1215 const VkSamplerMipmapMode m_mipmapFilter; 1216 const VkSamplerAddressMode m_wrappingMode; 1217 const bool m_useDerivatives; 1218}; 1219 1220class Texture2DGradientTestCase::Generator : public DataGenerator 1221{ 1222public: 1223 Generator (const Texture2DGradientTestCase* testCase) : m_testCase(testCase) {} 1224 1225 virtual ~Generator (void) 1226 { 1227 delete m_tex.release(); 1228 } 1229 1230 virtual bool generate (void) 1231 { 1232 m_tex = de::MovePtr<Texture2D>(new Texture2D(m_testCase->m_format, 1233 m_testCase->m_dimensions[0], 1234 m_testCase->m_dimensions[1])); 1235 1236 const deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_testCase->m_dimensions[0], 1237 m_testCase->m_dimensions[1]))); 1238 1239 const TextureFormatInfo fmtInfo = getTextureFormatInfo(m_testCase->m_format); 1240 1241 const Vec4 cBias = fmtInfo.valueMin; 1242 const Vec4 cScale = fmtInfo.valueMax - fmtInfo.valueMin; 1243 1244 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx) 1245 { 1246 const Vec4 gMin = Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias; 1247 const Vec4 gMax = Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias; 1248 1249 m_tex->allocLevel(levelNdx); 1250 fillWithComponentGradients(m_tex->getLevel(levelNdx), gMin, gMax); 1251 } 1252 1253 return true; 1254 } 1255 1256 virtual std::vector<ConstPixelBufferAccess> getPba (void) const 1257 { 1258 std::vector<ConstPixelBufferAccess> pba; 1259 1260 const deUint8 numLevels = (deUint8) m_tex->getNumLevels(); 1261 1262 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx) 1263 { 1264 pba.push_back(m_tex->getLevel(levelNdx)); 1265 } 1266 1267 return pba; 1268 } 1269 1270 virtual std::vector<SampleArguments> getSampleArgs (void) const 1271 { 1272 std::vector<SampleArguments> args; 1273 1274 if (m_testCase->m_useDerivatives) 1275 { 1276 struct 1277 { 1278 Vec4 dPdx; 1279 Vec4 dPdy; 1280 } 1281 derivativePairs[] = 1282 { 1283 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)}, 1284 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)}, 1285 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)}, 1286 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)}, 1287 {Vec4(2.0f, 2.0f, 2.0f, 0.0f), Vec4(2.0f, 2.0f, 2.0f, 0.0f)} 1288 }; 1289 1290 for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i) 1291 { 1292 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j) 1293 { 1294 for (deUint32 derivNdx = 0; derivNdx < DE_LENGTH_OF_ARRAY(derivativePairs); ++derivNdx) 1295 { 1296 SampleArguments cur; 1297 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]), 1298 (float)j / (float)(2 * m_testCase->m_dimensions[1]), 1299 0.0f, 0.0f); 1300 cur.dPdx = derivativePairs[derivNdx].dPdx; 1301 cur.dPdy = derivativePairs[derivNdx].dPdy; 1302 1303 args.push_back(cur); 1304 } 1305 } 1306 } 1307 } 1308 else 1309 { 1310 const float lodList[] = {-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0}; 1311 1312 for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i) 1313 { 1314 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j) 1315 { 1316 for (deUint32 lodNdx = 0; lodNdx < DE_LENGTH_OF_ARRAY(lodList); ++lodNdx) 1317 { 1318 SampleArguments cur; 1319 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]), 1320 (float)j / (float)(2 * m_testCase->m_dimensions[1]), 1321 0.0f, 0.0f); 1322 cur.lod = lodList[lodNdx]; 1323 1324 args.push_back(cur); 1325 } 1326 } 1327 } 1328 } 1329 1330 return args; 1331 } 1332 1333private: 1334 const Texture2DGradientTestCase* m_testCase; 1335 de::MovePtr<Texture2D> m_tex; 1336}; 1337 1338de::MovePtr<DataGenerator> Texture2DGradientTestCase::createGenerator (void) const 1339{ 1340 return de::MovePtr<DataGenerator>(new Generator(this)); 1341} 1342 1343TestCaseGroup* create2DFormatTests (TestContext& testCtx) 1344{ 1345 de::MovePtr<TestCaseGroup> tests( 1346 new TestCaseGroup(testCtx, "formats", "Various image formats")); 1347 1348 const VkFormat formats[] = 1349 { 1350 VK_FORMAT_B4G4R4A4_UNORM_PACK16, 1351 VK_FORMAT_R5G6B5_UNORM_PACK16, 1352 VK_FORMAT_A1R5G5B5_UNORM_PACK16, 1353 VK_FORMAT_R8_UNORM, 1354 VK_FORMAT_R8_SNORM, 1355 VK_FORMAT_R8G8_UNORM, 1356 VK_FORMAT_R8G8_SNORM, 1357 VK_FORMAT_R8G8B8A8_UNORM, 1358 VK_FORMAT_R8G8B8A8_SNORM, 1359// VK_FORMAT_R8G8B8A8_SRGB, 1360 VK_FORMAT_B8G8R8A8_UNORM, 1361// VK_FORMAT_B8G8R8A8_SRGB, 1362 VK_FORMAT_A8B8G8R8_UNORM_PACK32, 1363 VK_FORMAT_A8B8G8R8_SNORM_PACK32, 1364// VK_FORMAT_A8B8G8R8_SRGB_PACK32, 1365 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 1366 VK_FORMAT_R16_SFLOAT, 1367 VK_FORMAT_R16G16_SFLOAT, 1368 VK_FORMAT_R16G16B16A16_SFLOAT, 1369 VK_FORMAT_R32_SFLOAT, 1370 VK_FORMAT_R32G32_SFLOAT, 1371 VK_FORMAT_R32G32B32A32_SFLOAT, 1372// VK_FORMAT_B10G11R11_UFLOAT_PACK32, 1373// VK_FORMAT_E5B9G9R9_UFLOAT_PACK32 1374 }; 1375 1376 const IVec3 size(32, 32, 1); 1377 1378 for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) 1379 { 1380 const std::string prefix = de::toLower(std::string(getFormatName(formats[formatNdx])).substr(10)); 1381 1382 Texture2DGradientTestCase* testCaseNearest = 1383 new Texture2DGradientTestCase( 1384 testCtx, 1385 (prefix + "_nearest").c_str(), 1386 "...", 1387 mapVkFormat(formats[formatNdx]), 1388 size, 1389 VK_FILTER_NEAREST, 1390 VK_FILTER_NEAREST, 1391 VK_SAMPLER_MIPMAP_MODE_NEAREST, 1392 VK_SAMPLER_ADDRESS_MODE_REPEAT, 1393 false); 1394 1395 tests->addChild(testCaseNearest); 1396 1397 Texture2DGradientTestCase* testCaseLinear = 1398 new Texture2DGradientTestCase( 1399 testCtx, 1400 (prefix + "_linear").c_str(), 1401 "...", 1402 mapVkFormat(formats[formatNdx]), 1403 size, 1404 VK_FILTER_LINEAR, 1405 VK_FILTER_LINEAR, 1406 VK_SAMPLER_MIPMAP_MODE_LINEAR, 1407 VK_SAMPLER_ADDRESS_MODE_REPEAT, 1408 false); 1409 1410 tests->addChild(testCaseLinear); 1411 } 1412 1413 return tests.release(); 1414} 1415 1416TestCaseGroup* create2DDerivTests (TestContext& testCtx) 1417{ 1418 de::MovePtr<TestCaseGroup> tests( 1419 new TestCaseGroup(testCtx, "derivatives", "Explicit derivative tests")); 1420 1421 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM; 1422 const VkSamplerAddressMode wrappingMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; 1423 const IVec3 size = IVec3(16, 16, 1); 1424 1425 const VkFilter filters[2] = 1426 { 1427 VK_FILTER_NEAREST, 1428 VK_FILTER_LINEAR 1429 }; 1430 1431 const VkSamplerMipmapMode mipmapFilters[2] = 1432 { 1433 VK_SAMPLER_MIPMAP_MODE_NEAREST, 1434 VK_SAMPLER_MIPMAP_MODE_LINEAR, 1435 }; 1436 1437 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++magFilterNdx) 1438 { 1439 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++minFilterNdx) 1440 { 1441 for (int mipmapFilterNdx = 0; mipmapFilterNdx < DE_LENGTH_OF_ARRAY(mipmapFilters); ++mipmapFilterNdx) 1442 { 1443 std::ostringstream caseName; 1444 1445 switch (filters[magFilterNdx]) 1446 { 1447 case VK_FILTER_NEAREST: 1448 caseName << "nearest"; 1449 break; 1450 1451 case VK_FILTER_LINEAR: 1452 caseName << "linear"; 1453 break; 1454 1455 default: 1456 break; 1457 } 1458 1459 switch (filters[minFilterNdx]) 1460 { 1461 case VK_FILTER_NEAREST: 1462 caseName << "_nearest"; 1463 break; 1464 1465 case VK_FILTER_LINEAR: 1466 caseName << "_linear"; 1467 break; 1468 1469 default: 1470 break; 1471 } 1472 1473 caseName << "_mipmap"; 1474 1475 switch (mipmapFilters[mipmapFilterNdx]) 1476 { 1477 case VK_SAMPLER_MIPMAP_MODE_NEAREST: 1478 caseName << "_nearest"; 1479 break; 1480 1481 case VK_SAMPLER_MIPMAP_MODE_LINEAR: 1482 caseName << "_linear"; 1483 break; 1484 1485 default: 1486 break; 1487 } 1488 1489 Texture2DGradientTestCase* testCase = 1490 new Texture2DGradientTestCase( 1491 testCtx, 1492 caseName.str().c_str(), 1493 "...", 1494 mapVkFormat(format), 1495 size, 1496 filters[magFilterNdx], 1497 filters[minFilterNdx], 1498 mipmapFilters[mipmapFilterNdx], 1499 wrappingMode, 1500 true); 1501 1502 tests->addChild(testCase); 1503 } 1504 } 1505 } 1506 1507 return tests.release(); 1508} 1509 1510TestCaseGroup* create2DSizeTests (TestContext& testCtx) 1511{ 1512 de::MovePtr<TestCaseGroup> tests( 1513 new TestCaseGroup(testCtx, "sizes", "Various size and filtering combinations")); 1514 1515 const VkFilter filters[2] = 1516 { 1517 VK_FILTER_NEAREST, 1518 VK_FILTER_LINEAR 1519 }; 1520 1521 const VkSamplerMipmapMode mipmapFilters[2] = 1522 { 1523 VK_SAMPLER_MIPMAP_MODE_NEAREST, 1524 VK_SAMPLER_MIPMAP_MODE_LINEAR 1525 }; 1526 1527 const VkSamplerAddressMode wrappingModes[2] = 1528 { 1529 VK_SAMPLER_ADDRESS_MODE_REPEAT, 1530 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE 1531 }; 1532 1533 const IVec3 sizes[] = 1534 { 1535 IVec3(2, 2, 1), 1536 IVec3(2, 3, 1), 1537 IVec3(3, 7, 1), 1538 IVec3(4, 8, 1), 1539 IVec3(31, 55, 1), 1540 IVec3(32, 32, 1), 1541 IVec3(32, 64, 1), 1542 IVec3(57, 35, 1), 1543 IVec3(128, 128, 1) 1544 }; 1545 1546 1547 for (deUint32 sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx) 1548 { 1549 for (deUint32 magFilterNdx = 0; magFilterNdx < 2; ++magFilterNdx) 1550 { 1551 for (deUint32 minFilterNdx = 0; minFilterNdx < 2; ++minFilterNdx) 1552 { 1553 for (deUint32 mipmapFilterNdx = 0; mipmapFilterNdx < 2; ++mipmapFilterNdx) 1554 { 1555 for (deUint32 wrappingModeNdx = 0; wrappingModeNdx < 2; ++wrappingModeNdx) 1556 { 1557 std::ostringstream caseName; 1558 1559 caseName << sizes[sizeNdx][0] << "x" << sizes[sizeNdx][1]; 1560 1561 switch (filters[magFilterNdx]) 1562 { 1563 case VK_FILTER_NEAREST: 1564 caseName << "_nearest"; 1565 break; 1566 1567 case VK_FILTER_LINEAR: 1568 caseName << "_linear"; 1569 break; 1570 1571 default: 1572 break; 1573 } 1574 1575 switch (filters[minFilterNdx]) 1576 { 1577 case VK_FILTER_NEAREST: 1578 caseName << "_nearest"; 1579 break; 1580 1581 case VK_FILTER_LINEAR: 1582 caseName << "_linear"; 1583 break; 1584 1585 default: 1586 break; 1587 } 1588 1589 switch (mipmapFilters[mipmapFilterNdx]) 1590 { 1591 case VK_SAMPLER_MIPMAP_MODE_NEAREST: 1592 caseName << "_mipmap_nearest"; 1593 break; 1594 1595 case VK_SAMPLER_MIPMAP_MODE_LINEAR: 1596 caseName << "_mipmap_linear"; 1597 break; 1598 1599 default: 1600 break; 1601 } 1602 1603 switch (wrappingModes[wrappingModeNdx]) 1604 { 1605 case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: 1606 caseName << "_clamp"; 1607 break; 1608 1609 case VK_SAMPLER_ADDRESS_MODE_REPEAT: 1610 caseName << "_repeat"; 1611 break; 1612 1613 default: 1614 break; 1615 } 1616 1617 Texture2DGradientTestCase* testCase = 1618 new Texture2DGradientTestCase( 1619 testCtx, 1620 caseName.str().c_str(), 1621 "...", 1622 mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), 1623 sizes[sizeNdx], 1624 filters[magFilterNdx], 1625 filters[minFilterNdx], 1626 mipmapFilters[mipmapFilterNdx], 1627 wrappingModes[wrappingModeNdx], 1628 false); 1629 1630 tests->addChild(testCase); 1631 } 1632 } 1633 } 1634 } 1635 } 1636 1637 return tests.release(); 1638} 1639 1640TestCaseGroup* create2DTests (TestContext& testCtx) 1641{ 1642 de::MovePtr<TestCaseGroup> tests( 1643 new TestCaseGroup(testCtx, "2d", "2D Image filtering tests")); 1644 1645 tests->addChild(create2DSizeTests(testCtx)); 1646 tests->addChild(create2DFormatTests(testCtx)); 1647 tests->addChild(create2DDerivTests(testCtx)); 1648 1649 return tests.release(); 1650} 1651 1652} // anonymous 1653 1654TestCaseGroup* createExplicitLodTests (TestContext& testCtx) 1655{ 1656 de::MovePtr<TestCaseGroup> tests( 1657 new TestCaseGroup(testCtx, "explicit_lod", "Texture filtering with explicit LOD")); 1658 1659 tests->addChild(create2DTests(testCtx)); 1660 1661 return tests.release(); 1662} 1663 1664} // texture 1665} // vkt 1666