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 OpImageQuery & YCbCr Tests 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktYCbCrImageQueryTests.hpp" 25 #include "vktTestCaseUtil.hpp" 26 #include "vktTestGroupUtil.hpp" 27 #include "vktShaderExecutor.hpp" 28 #include "vktYCbCrUtil.hpp" 29 #include "vktDrawUtil.hpp" 30 31 #include "vkStrUtil.hpp" 32 #include "vkRef.hpp" 33 #include "vkRefUtil.hpp" 34 #include "vkTypeUtil.hpp" 35 #include "vkQueryUtil.hpp" 36 #include "vkMemUtil.hpp" 37 #include "vkImageUtil.hpp" 38 39 #include "tcuTestLog.hpp" 40 #include "tcuVectorUtil.hpp" 41 #include "tcuTexLookupVerifier.hpp" 42 43 #include "deStringUtil.hpp" 44 #include "deSharedPtr.hpp" 45 #include "deUniquePtr.hpp" 46 #include "deRandom.hpp" 47 #include "deSTLUtil.hpp" 48 49 namespace vkt 50 { 51 namespace ycbcr 52 { 53 namespace 54 { 55 56 using namespace vk; 57 using namespace shaderexecutor; 58 59 using tcu::UVec2; 60 using tcu::Vec2; 61 using tcu::Vec4; 62 using tcu::TestLog; 63 using de::MovePtr; 64 using de::UniquePtr; 65 using std::vector; 66 using std::string; 67 68 typedef de::SharedPtr<Allocation> AllocationSp; 69 typedef de::SharedPtr<vk::Unique<VkBuffer> > VkBufferSp; 70 71 enum QueryType 72 { 73 QUERY_TYPE_IMAGE_SIZE_LOD, // OpImageQuerySizeLod 74 QUERY_TYPE_IMAGE_LOD, // OpImageQueryLod 75 QUERY_TYPE_IMAGE_LEVELS, // OpImageQueryLevels 76 77 QUERY_TYPE_LAST 78 }; 79 80 struct TestParameters 81 { 82 QueryType query; 83 VkFormat format; 84 VkImageCreateFlags flags; 85 glu::ShaderType shaderType; 86 87 TestParameters (QueryType query_, VkFormat format_, VkImageCreateFlags flags_, glu::ShaderType shaderType_) 88 : query (query_) 89 , format (format_) 90 , flags (flags_) 91 , shaderType(shaderType_) 92 { 93 } 94 95 TestParameters (void) 96 : query (QUERY_TYPE_LAST) 97 , format (VK_FORMAT_UNDEFINED) 98 , flags (0u) 99 , shaderType(glu::SHADERTYPE_LAST) 100 { 101 } 102 }; 103 104 ShaderSpec getShaderSpec (const TestParameters& params) 105 { 106 ShaderSpec spec; 107 const char* expr = DE_NULL; 108 glu::DataType resultType = glu::TYPE_LAST; 109 110 switch (params.query) 111 { 112 case QUERY_TYPE_IMAGE_SIZE_LOD: 113 expr = "textureSize(u_image, lod)"; 114 resultType = glu::TYPE_INT_VEC2; 115 break; 116 117 case QUERY_TYPE_IMAGE_LEVELS: 118 expr = "textureQueryLevels(u_image)"; 119 resultType = glu::TYPE_INT; 120 break; 121 122 default: 123 DE_FATAL("Unknown query"); 124 } 125 126 spec.glslVersion = glu::GLSL_VERSION_450; 127 128 spec.inputs.push_back(Symbol("lod", glu::VarType(glu::TYPE_INT, glu::PRECISION_HIGHP))); 129 spec.outputs.push_back(Symbol("result", glu::VarType(resultType, glu::PRECISION_HIGHP))); 130 131 spec.globalDeclarations = 132 "layout(binding = 0, set = 1) uniform highp sampler2D u_image;\n"; 133 134 spec.source = 135 string("result = ") + expr + ";\n"; 136 137 return spec; 138 } 139 140 Move<VkImage> createTestImage (const DeviceInterface& vkd, 141 VkDevice device, 142 VkFormat format, 143 const UVec2& size, 144 VkImageCreateFlags createFlags) 145 { 146 const VkImageCreateInfo createInfo = 147 { 148 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, 149 DE_NULL, 150 createFlags, 151 VK_IMAGE_TYPE_2D, 152 format, 153 makeExtent3D(size.x(), size.y(), 1u), 154 1u, // mipLevels 155 1u, // arrayLayers 156 VK_SAMPLE_COUNT_1_BIT, 157 VK_IMAGE_TILING_OPTIMAL, 158 VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT, 159 VK_SHARING_MODE_EXCLUSIVE, 160 0u, 161 (const deUint32*)DE_NULL, 162 VK_IMAGE_LAYOUT_UNDEFINED, 163 }; 164 165 return createImage(vkd, device, &createInfo); 166 } 167 168 Move<VkImageView> createImageView (const DeviceInterface& vkd, 169 VkDevice device, 170 VkImage image, 171 VkFormat format) 172 { 173 const VkImageViewCreateInfo viewInfo = 174 { 175 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 176 DE_NULL, 177 (VkImageViewCreateFlags)0, 178 image, 179 VK_IMAGE_VIEW_TYPE_2D, 180 format, 181 { 182 VK_COMPONENT_SWIZZLE_IDENTITY, 183 VK_COMPONENT_SWIZZLE_IDENTITY, 184 VK_COMPONENT_SWIZZLE_IDENTITY, 185 VK_COMPONENT_SWIZZLE_IDENTITY, 186 }, 187 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }, 188 }; 189 190 return createImageView(vkd, device, &viewInfo); 191 } 192 193 class TestImage 194 { 195 public: 196 TestImage (const DeviceInterface& vkd, 197 VkDevice device, 198 Allocator& allocator, 199 VkFormat format, 200 const UVec2& size, 201 const VkImageCreateFlags createFlags); 202 203 const UVec2& getSize (void) const { return m_size; } 204 VkImageView getImageView (void) const { return *m_imageView; } 205 206 private: 207 const UVec2 m_size; 208 const Unique<VkImage> m_image; 209 const vector<AllocationSp> m_allocations; 210 const Unique<VkImageView> m_imageView; 211 }; 212 213 TestImage::TestImage (const DeviceInterface& vkd, 214 VkDevice device, 215 Allocator& allocator, 216 VkFormat format, 217 const UVec2& size, 218 const VkImageCreateFlags createFlags) 219 : m_size (size) 220 , m_image (createTestImage(vkd, device, format, size, createFlags)) 221 , m_allocations (allocateAndBindImageMemory(vkd, device, allocator, *m_image, format, createFlags)) 222 , m_imageView (createImageView(vkd, device, *m_image, format)) 223 { 224 } 225 226 typedef de::SharedPtr<TestImage> TestImageSp; 227 228 Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkd, VkDevice device, VkSampler sampler) 229 { 230 const VkDescriptorSetLayoutBinding binding = 231 { 232 0u, // binding 233 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 234 1u, // descriptorCount 235 VK_SHADER_STAGE_ALL, 236 &sampler 237 }; 238 const VkDescriptorSetLayoutCreateInfo layoutInfo = 239 { 240 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 241 DE_NULL, 242 (VkDescriptorSetLayoutCreateFlags)0u, 243 1u, 244 &binding, 245 }; 246 247 return createDescriptorSetLayout(vkd, device, &layoutInfo); 248 } 249 250 Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkd, VkDevice device) 251 { 252 const VkDescriptorPoolSize poolSizes[] = 253 { 254 { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u }, 255 }; 256 const VkDescriptorPoolCreateInfo poolInfo = 257 { 258 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, 259 DE_NULL, 260 (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 261 1u, // maxSets 262 DE_LENGTH_OF_ARRAY(poolSizes), 263 poolSizes, 264 }; 265 266 return createDescriptorPool(vkd, device, & poolInfo); 267 } 268 269 Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface& vkd, 270 VkDevice device, 271 VkDescriptorPool descPool, 272 VkDescriptorSetLayout descLayout) 273 { 274 const VkDescriptorSetAllocateInfo allocInfo = 275 { 276 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, 277 DE_NULL, 278 descPool, 279 1u, 280 &descLayout, 281 }; 282 283 return allocateDescriptorSet(vkd, device, &allocInfo); 284 } 285 286 void bindImage (const DeviceInterface& vkd, 287 VkDevice device, 288 VkDescriptorSet descriptorSet, 289 VkImageView imageView, 290 VkSampler sampler) 291 { 292 const VkDescriptorImageInfo imageInfo = 293 { 294 sampler, 295 imageView, 296 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL 297 }; 298 const VkWriteDescriptorSet descriptorWrite = 299 { 300 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 301 DE_NULL, 302 descriptorSet, 303 0u, // dstBinding 304 0u, // dstArrayElement 305 1u, // descriptorCount 306 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 307 &imageInfo, 308 (const VkDescriptorBufferInfo*)DE_NULL, 309 (const VkBufferView*)DE_NULL, 310 }; 311 312 vkd.updateDescriptorSets(device, 1u, &descriptorWrite, 0u, DE_NULL); 313 } 314 315 UVec2 getMaxPlaneDivisor (const PlanarFormatDescription& formatDesc) 316 { 317 UVec2 maxDivisor (1u, 1u); 318 319 for (deUint32 ndx = 0; ndx < formatDesc.numPlanes; ++ndx) 320 { 321 maxDivisor.x() = de::max<deUint32>(maxDivisor.x(), formatDesc.planes[ndx].widthDivisor); 322 maxDivisor.y() = de::max<deUint32>(maxDivisor.y(), formatDesc.planes[ndx].heightDivisor); 323 } 324 325 return maxDivisor; 326 } 327 328 tcu::TestStatus testImageQuery (Context& context, TestParameters params) 329 { 330 const bool isYCbCrImage = isYCbCrFormat(params.format); 331 332 if (isYCbCrImage) 333 checkImageSupport(context, params.format, params.flags); 334 335 const DeviceInterface& vkd = context.getDeviceInterface(); 336 const VkDevice device = context.getDevice(); 337 338 const VkSamplerYcbcrConversionCreateInfoKHR conversionInfo = 339 { 340 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR, 341 DE_NULL, 342 params.format, 343 VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR, 344 VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR, 345 { 346 VK_COMPONENT_SWIZZLE_IDENTITY, 347 VK_COMPONENT_SWIZZLE_IDENTITY, 348 VK_COMPONENT_SWIZZLE_IDENTITY, 349 VK_COMPONENT_SWIZZLE_IDENTITY, 350 }, 351 VK_CHROMA_LOCATION_MIDPOINT_KHR, 352 VK_CHROMA_LOCATION_MIDPOINT_KHR, 353 VK_FILTER_NEAREST, 354 VK_FALSE, // forceExplicitReconstruction 355 }; 356 const Unique<VkSamplerYcbcrConversionKHR> conversion (isYCbCrImage 357 ? createSamplerYcbcrConversionKHR(vkd, device, &conversionInfo) 358 : Move<VkSamplerYcbcrConversionKHR>()); 359 360 const VkSamplerYcbcrConversionInfoKHR samplerConversionInfo = 361 { 362 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR, 363 DE_NULL, 364 *conversion, 365 }; 366 367 const VkSamplerCreateInfo samplerInfo = 368 { 369 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, 370 isYCbCrImage ? &samplerConversionInfo : DE_NULL, 371 0u, 372 VK_FILTER_NEAREST, // magFilter 373 VK_FILTER_NEAREST, // minFilter 374 VK_SAMPLER_MIPMAP_MODE_NEAREST, // mipmapMode 375 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU 376 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV 377 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW 378 0.0f, // mipLodBias 379 VK_FALSE, // anisotropyEnable 380 1.0f, // maxAnisotropy 381 VK_FALSE, // compareEnable 382 VK_COMPARE_OP_ALWAYS, // compareOp 383 0.0f, // minLod 384 0.0f, // maxLod 385 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // borderColor 386 VK_FALSE, // unnormalizedCoords 387 }; 388 389 const Unique<VkSampler> sampler (createSampler(vkd, device, &samplerInfo)); 390 const Unique<VkDescriptorSetLayout> descLayout (createDescriptorSetLayout(vkd, device, *sampler)); 391 const Unique<VkDescriptorPool> descPool (createDescriptorPool(vkd, device)); 392 const Unique<VkDescriptorSet> descSet (createDescriptorSet(vkd, device, *descPool, *descLayout)); 393 394 vector<TestImageSp> testImages; 395 396 if (params.query == QUERY_TYPE_IMAGE_SIZE_LOD) 397 { 398 const PlanarFormatDescription& formatDesc = getPlanarFormatDescription(params.format); 399 const UVec2 maxDivisor = getMaxPlaneDivisor(formatDesc); 400 vector<UVec2> testSizes; 401 402 testSizes.push_back(maxDivisor); 403 testSizes.push_back(maxDivisor * UVec2(2u, 1u)); 404 testSizes.push_back(maxDivisor * UVec2(1u, 2u)); 405 testSizes.push_back(maxDivisor * UVec2(63u, 79u)); 406 testSizes.push_back(maxDivisor * UVec2(99u, 1u)); 407 testSizes.push_back(maxDivisor * UVec2(421u, 1117u)); 408 409 testImages.resize(testSizes.size()); 410 411 for (size_t ndx = 0; ndx < testSizes.size(); ++ndx) 412 testImages[ndx] = TestImageSp(new TestImage(vkd, device, context.getDefaultAllocator(), params.format, testSizes[ndx], params.flags)); 413 } 414 else 415 testImages.push_back(TestImageSp(new TestImage(vkd, device, context.getDefaultAllocator(), params.format, UVec2(16, 18), params.flags))); 416 417 { 418 UniquePtr<ShaderExecutor> executor (createExecutor(context, params.shaderType, getShaderSpec(params), *descLayout)); 419 bool allOk = true; 420 421 for (size_t imageNdx = 0; imageNdx < testImages.size(); ++imageNdx) 422 { 423 const deUint32 lod = 0u; 424 UVec2 result (~0u, ~0u); 425 const void* inputs[] = { &lod }; 426 void* outputs[] = { result.getPtr() }; 427 428 bindImage(vkd, device, *descSet, testImages[imageNdx]->getImageView(), *sampler); 429 430 executor->execute(1, inputs, outputs, *descSet); 431 432 switch (params.query) 433 { 434 case QUERY_TYPE_IMAGE_SIZE_LOD: 435 { 436 const UVec2 reference = testImages[imageNdx]->getSize(); 437 438 if (result != reference) 439 { 440 context.getTestContext().getLog() 441 << TestLog::Message << "ERROR: Image " << imageNdx 442 << ": got " << result 443 << ", expected " << reference 444 << TestLog::EndMessage; 445 allOk = false; 446 } 447 break; 448 } 449 450 case QUERY_TYPE_IMAGE_LEVELS: 451 { 452 if (result.x() != 1u) 453 { 454 context.getTestContext().getLog() 455 << TestLog::Message << "ERROR: Image " << imageNdx 456 << ": got " << result.x() 457 << ", expected " << 1 458 << TestLog::EndMessage; 459 allOk = false; 460 } 461 break; 462 } 463 464 default: 465 DE_FATAL("Invalid query type"); 466 } 467 } 468 469 if (allOk) 470 return tcu::TestStatus::pass("Queries passed"); 471 else 472 return tcu::TestStatus::fail("Got invalid results"); 473 } 474 } 475 476 tcu::TestStatus testImageQueryLod (Context& context, TestParameters params) 477 { 478 const bool isYCbCrImage = isYCbCrFormat(params.format); 479 480 if (isYCbCrImage) 481 checkImageSupport(context, params.format, params.flags); 482 483 const DeviceInterface& vkd = context.getDeviceInterface(); 484 const VkDevice device = context.getDevice(); 485 486 const VkSamplerYcbcrConversionCreateInfoKHR conversionInfo = 487 { 488 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO_KHR, 489 DE_NULL, 490 params.format, 491 VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY_KHR, 492 VK_SAMPLER_YCBCR_RANGE_ITU_FULL_KHR, 493 { 494 VK_COMPONENT_SWIZZLE_IDENTITY, 495 VK_COMPONENT_SWIZZLE_IDENTITY, 496 VK_COMPONENT_SWIZZLE_IDENTITY, 497 VK_COMPONENT_SWIZZLE_IDENTITY, 498 }, 499 VK_CHROMA_LOCATION_MIDPOINT_KHR, 500 VK_CHROMA_LOCATION_MIDPOINT_KHR, 501 VK_FILTER_NEAREST, 502 VK_FALSE, // forceExplicitReconstruction 503 }; 504 const Unique<VkSamplerYcbcrConversionKHR> conversion (isYCbCrImage 505 ? createSamplerYcbcrConversionKHR(vkd, device, &conversionInfo) 506 : Move<VkSamplerYcbcrConversionKHR>()); 507 508 const VkSamplerYcbcrConversionInfoKHR samplerConversionInfo = 509 { 510 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO_KHR, 511 DE_NULL, 512 *conversion, 513 }; 514 515 const VkSamplerCreateInfo samplerInfo = 516 { 517 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, 518 isYCbCrImage ? &samplerConversionInfo : DE_NULL, 519 0u, 520 VK_FILTER_NEAREST, // magFilter 521 VK_FILTER_NEAREST, // minFilter 522 VK_SAMPLER_MIPMAP_MODE_NEAREST, // mipmapMode 523 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU 524 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV 525 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW 526 0.0f, // mipLodBias 527 VK_FALSE, // anisotropyEnable 528 1.0f, // maxAnisotropy 529 VK_FALSE, // compareEnable 530 VK_COMPARE_OP_ALWAYS, // compareOp 531 0.0f, // minLod 532 0.0f, // maxLod 533 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // borderColor 534 VK_FALSE, // unnormalizedCoords 535 }; 536 537 const Unique<VkSampler> sampler (createSampler(vkd, device, &samplerInfo)); 538 const Unique<VkDescriptorSetLayout> descLayout (createDescriptorSetLayout(vkd, device, *sampler)); 539 const Unique<VkDescriptorPool> descPool (createDescriptorPool(vkd, device)); 540 const Unique<VkDescriptorSet> descSet (createDescriptorSet(vkd, device, *descPool, *descLayout)); 541 542 vector<TestImageSp> testImages; 543 544 DE_ASSERT(params.query == QUERY_TYPE_IMAGE_LOD); 545 DE_ASSERT(params.shaderType == glu::SHADERTYPE_FRAGMENT); 546 547 { 548 const PlanarFormatDescription& formatDesc = getPlanarFormatDescription(params.format); 549 const UVec2 maxDivisor = getMaxPlaneDivisor(formatDesc); 550 vector<UVec2> testSizes; 551 552 testSizes.push_back(maxDivisor); 553 testSizes.push_back(maxDivisor * UVec2(2u, 1u)); 554 testSizes.push_back(maxDivisor * UVec2(1u, 2u)); 555 testSizes.push_back(maxDivisor * UVec2(4u, 123u)); 556 testSizes.push_back(maxDivisor * UVec2(312u, 13u)); 557 testSizes.push_back(maxDivisor * UVec2(841u, 917u)); 558 559 testImages.resize(testSizes.size()); 560 561 for (size_t ndx = 0; ndx < testSizes.size(); ++ndx) 562 testImages[ndx] = TestImageSp(new TestImage(vkd, device, context.getDefaultAllocator(), params.format, testSizes[ndx], params.flags)); 563 } 564 565 { 566 using namespace drawutil; 567 568 struct LocalUtil 569 { 570 static DrawState getDrawState (UVec2 renderSize) 571 { 572 DrawState state(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, renderSize.x(), renderSize.y()); 573 state.colorFormat = VK_FORMAT_R32G32_SFLOAT; 574 return state; 575 } 576 577 static vector<Vec4> getVertices (void) 578 { 579 vector<Vec4> vertices; 580 581 vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f)); 582 vertices.push_back(Vec4(+1.0f, -1.0f, 0.0f, 1.0f)); 583 vertices.push_back(Vec4(-1.0f, +1.0f, 0.0f, 1.0f)); 584 585 vertices.push_back(Vec4(+1.0f, -1.0f, 0.0f, 1.0f)); 586 vertices.push_back(Vec4(-1.0f, +1.0f, 0.0f, 1.0f)); 587 vertices.push_back(Vec4(+1.0f, +1.0f, 0.0f, 1.0f)); 588 589 return vertices; 590 } 591 592 static VulkanProgram getProgram (Context& ctx, VkDescriptorSetLayout descriptorLayout, VkDescriptorSet descriptorSet) 593 { 594 VulkanProgram prog; 595 596 prog.shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, ctx.getBinaryCollection().get("vert"))); 597 prog.shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, ctx.getBinaryCollection().get("frag"))); 598 599 prog.descriptorSet = descriptorSet; 600 prog.descriptorSetLayout = descriptorLayout; 601 602 return prog; 603 } 604 }; 605 606 const UVec2 renderSize (128, 256); 607 const vector<Vec4> vertices (LocalUtil::getVertices()); 608 const DrawState drawState (LocalUtil::getDrawState(renderSize)); 609 const DrawCallData drawCallData(vertices); 610 const VulkanProgram program (LocalUtil::getProgram(context, *descLayout, *descSet)); 611 612 bool allOk = true; 613 614 context.getTestContext().getLog() 615 << TestLog::Message << "Rendering " << renderSize << " quad" << TestLog::EndMessage; 616 617 for (size_t imageNdx = 0; imageNdx < testImages.size(); ++imageNdx) 618 { 619 context.getTestContext().getLog() 620 << TestLog::Message << "Testing image size " << testImages[imageNdx]->getSize() << TestLog::EndMessage; 621 622 bindImage(vkd, device, *descSet, testImages[imageNdx]->getImageView(), *sampler); 623 624 VulkanDrawContext renderer (context, drawState, drawCallData, program); 625 renderer.draw(); 626 627 { 628 // Only du/dx and dv/dy are non-zero 629 const Vec2 dtdp = testImages[imageNdx]->getSize().cast<float>() / renderSize.cast<float>(); 630 const tcu::LodPrecision lodPrec (16, 4); // Pretty lax since we are not verifying LOD precision 631 const Vec2 lodBounds (tcu::computeLodBoundsFromDerivates(dtdp.x(), 0.0f, 0.0f, dtdp.y(), lodPrec)); 632 tcu::ConstPixelBufferAccess resultImg (renderer.getColorPixels()); 633 const int maxErrors = 5; 634 int numErrors = 0; 635 636 for (int y = 0; y < resultImg.getHeight(); ++y) 637 for (int x = 0; x < resultImg.getWidth(); ++x) 638 { 639 const Vec2 result = resultImg.getPixel(x, y).swizzle(0,1); 640 const bool levelOk = result.x() == 0.0f; 641 const bool lodOk = de::inRange(result.y(), lodBounds.x(), lodBounds.y()); 642 643 if (!levelOk || !lodOk) 644 { 645 if (numErrors < maxErrors) 646 { 647 context.getTestContext().getLog() 648 << TestLog::Message << "ERROR: At (" << x << ", " << y << ")" 649 << ": got " << result 650 << ", expected (0, [" << lodBounds.x() << ", " << lodBounds.y() << "])" 651 << TestLog::EndMessage; 652 } 653 else if (numErrors == maxErrors) 654 context.getTestContext().getLog() << TestLog::Message << "..." << TestLog::EndMessage; 655 656 numErrors += 1; 657 } 658 } 659 660 allOk = allOk && (numErrors == 0); 661 } 662 } 663 664 if (allOk) 665 return tcu::TestStatus::pass("Queries passed"); 666 else 667 return tcu::TestStatus::fail("Got invalid results"); 668 } 669 } 670 671 void initImageQueryPrograms (SourceCollections& dst, TestParameters params) 672 { 673 const ShaderSpec spec = getShaderSpec(params); 674 675 generateSources(params.shaderType, spec, dst); 676 } 677 678 void initImageQueryLodPrograms (SourceCollections& dst, TestParameters) 679 { 680 dst.glslSources.add("vert") 681 << glu::VertexSource("#version 450\n" 682 "layout(location = 0) in highp vec4 a_position;\n" 683 "layout(location = 0) out highp vec2 v_texCoord;\n" 684 "\n" 685 "void main (void)\n" 686 "{\n" 687 " gl_Position = a_position;\n" 688 " v_texCoord = a_position.xy * 0.5 - 0.5;\n" 689 "}\n"); 690 dst.glslSources.add("frag") 691 << glu::FragmentSource("#version 450\n" 692 "layout(binding = 0, set = 0) uniform highp sampler2D u_image;\n" 693 "layout(location = 0) in highp vec2 v_texCoord;\n" 694 "layout(location = 0) out highp vec2 o_lod;\n" 695 "\n" 696 "void main (void)\n" 697 "{\n" 698 " o_lod = textureQueryLod(u_image, v_texCoord);\n" 699 "}\n"); 700 } 701 702 void addImageQueryCase (tcu::TestCaseGroup* group, const TestParameters& params) 703 { 704 std::string name = de::toLower(de::toString(params.format).substr(10)); 705 const bool isLod = params.query == QUERY_TYPE_IMAGE_LOD; 706 707 if ((params.flags & VK_IMAGE_CREATE_DISJOINT_BIT_KHR) != 0) 708 name += "_disjoint"; 709 710 addFunctionCaseWithPrograms(group, 711 name, 712 "", 713 isLod ? initImageQueryLodPrograms : initImageQueryPrograms, 714 isLod ? testImageQueryLod : testImageQuery, 715 params); 716 } 717 718 struct QueryGroupParams 719 { 720 QueryType query; 721 glu::ShaderType shaderType; 722 723 QueryGroupParams (QueryType query_, glu::ShaderType shaderType_) 724 : query (query_) 725 , shaderType(shaderType_) 726 {} 727 728 QueryGroupParams (void) 729 : query (QUERY_TYPE_LAST) 730 , shaderType(glu::SHADERTYPE_LAST) 731 {} 732 }; 733 734 void populateQueryInShaderGroup (tcu::TestCaseGroup* group, QueryGroupParams params) 735 { 736 // "Reference" formats for testing 737 addImageQueryCase(group, TestParameters(params.query, VK_FORMAT_R8G8B8A8_UNORM, 0u, params.shaderType)); 738 739 for (int formatNdx = VK_YCBCR_FORMAT_FIRST; formatNdx < VK_YCBCR_FORMAT_LAST; formatNdx++) 740 { 741 const VkFormat format = (VkFormat)formatNdx; 742 743 addImageQueryCase(group, TestParameters(params.query, format, 0u, params.shaderType)); 744 745 if (getPlaneCount(format) > 1) 746 addImageQueryCase(group, TestParameters(params.query, format, (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT_KHR, params.shaderType)); 747 } 748 } 749 750 void populateQueryGroup (tcu::TestCaseGroup* group, QueryType query) 751 { 752 for (int shaderTypeNdx = 0; shaderTypeNdx < glu::SHADERTYPE_LAST; ++shaderTypeNdx) 753 { 754 const glu::ShaderType shaderType = (glu::ShaderType)shaderTypeNdx; 755 756 if (query == QUERY_TYPE_IMAGE_LOD && shaderType != glu::SHADERTYPE_FRAGMENT) 757 continue; 758 759 addTestGroup(group, glu::getShaderTypeName(shaderType), "", populateQueryInShaderGroup, QueryGroupParams(query, shaderType)); 760 } 761 } 762 763 void populateImageQueryGroup (tcu::TestCaseGroup* group) 764 { 765 addTestGroup(group, "size_lod", "OpImageQuerySizeLod", populateQueryGroup, QUERY_TYPE_IMAGE_SIZE_LOD); 766 addTestGroup(group, "lod", "OpImageQueryLod", populateQueryGroup, QUERY_TYPE_IMAGE_LOD); 767 addTestGroup(group, "levels", "OpImageQueryLevels", populateQueryGroup, QUERY_TYPE_IMAGE_LEVELS); 768 } 769 770 } // namespace 771 772 tcu::TestCaseGroup* createImageQueryTests (tcu::TestContext& testCtx) 773 { 774 return createTestGroup(testCtx, "query", "Image Query Tests", populateImageQueryGroup); 775 } 776 777 } // ycbcr 778 } // vkt 779