1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 The Khronos Group Inc. 6 * Copyright (c) 2015 Imagination Technologies Ltd. 7 * Copyright (c) 2023 LunarG, Inc. 8 * Copyright (c) 2023 Nintendo 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * 22 *//*! 23 * \file 24 * \brief Image sampling case 25 *//*--------------------------------------------------------------------*/ 26 27#include "vktPipelineImageSamplingInstance.hpp" 28#include "vktPipelineClearUtil.hpp" 29#include "vktPipelineReferenceRenderer.hpp" 30#include "vkBuilderUtil.hpp" 31#include "vkImageUtil.hpp" 32#include "vkPrograms.hpp" 33#include "vkQueryUtil.hpp" 34#include "vkRefUtil.hpp" 35#include "vkTypeUtil.hpp" 36#include "vkCmdUtil.hpp" 37#include "vkTypeUtil.hpp" 38#include "vkObjUtil.hpp" 39#include "tcuTexLookupVerifier.hpp" 40#include "tcuTextureUtil.hpp" 41#include "tcuTestLog.hpp" 42#include "deSTLUtil.hpp" 43 44namespace vkt 45{ 46namespace pipeline 47{ 48 49using namespace vk; 50using de::MovePtr; 51using de::UniquePtr; 52 53namespace 54{ 55de::MovePtr<Allocation> allocateBuffer (const InstanceInterface& vki, 56 const DeviceInterface& vkd, 57 const VkPhysicalDevice& physDevice, 58 const VkDevice device, 59 const VkBuffer& buffer, 60 const MemoryRequirement requirement, 61 Allocator& allocator, 62 AllocationKind allocationKind) 63{ 64 switch (allocationKind) 65 { 66 case ALLOCATION_KIND_SUBALLOCATED: 67 { 68 const VkMemoryRequirements memoryRequirements = getBufferMemoryRequirements(vkd, device, buffer); 69 70 return allocator.allocate(memoryRequirements, requirement); 71 } 72 73 case ALLOCATION_KIND_DEDICATED: 74 { 75 return allocateDedicated(vki, vkd, physDevice, device, buffer, requirement); 76 } 77 78 default: 79 { 80 TCU_THROW(InternalError, "Invalid allocation kind"); 81 } 82 } 83} 84 85de::MovePtr<Allocation> allocateImage (const InstanceInterface& vki, 86 const DeviceInterface& vkd, 87 const VkPhysicalDevice& physDevice, 88 const VkDevice device, 89 const VkImage& image, 90 const MemoryRequirement requirement, 91 Allocator& allocator, 92 AllocationKind allocationKind) 93{ 94 switch (allocationKind) 95 { 96 case ALLOCATION_KIND_SUBALLOCATED: 97 { 98 const VkMemoryRequirements memoryRequirements = getImageMemoryRequirements(vkd, device, image); 99 100 return allocator.allocate(memoryRequirements, requirement); 101 } 102 103 case ALLOCATION_KIND_DEDICATED: 104 { 105 return allocateDedicated(vki, vkd, physDevice, device, image, requirement); 106 } 107 108 default: 109 { 110 TCU_THROW(InternalError, "Invalid allocation kind"); 111 } 112 } 113} 114 115static VkImageType getCompatibleImageType (VkImageViewType viewType) 116{ 117 switch (viewType) 118 { 119 case VK_IMAGE_VIEW_TYPE_1D: return VK_IMAGE_TYPE_1D; 120 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return VK_IMAGE_TYPE_1D; 121 case VK_IMAGE_VIEW_TYPE_2D: return VK_IMAGE_TYPE_2D; 122 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: return VK_IMAGE_TYPE_2D; 123 case VK_IMAGE_VIEW_TYPE_3D: return VK_IMAGE_TYPE_3D; 124 case VK_IMAGE_VIEW_TYPE_CUBE: return VK_IMAGE_TYPE_2D; 125 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return VK_IMAGE_TYPE_2D; 126 default: 127 break; 128 } 129 130 DE_ASSERT(false); 131 return VK_IMAGE_TYPE_1D; 132} 133 134template<typename TcuFormatType> 135static MovePtr<TestTexture> createTestTexture (const TcuFormatType format, VkImageViewType viewType, const tcu::IVec3& size, int layerCount) 136{ 137 MovePtr<TestTexture> texture; 138 const VkImageType imageType = getCompatibleImageType(viewType); 139 140 switch (imageType) 141 { 142 case VK_IMAGE_TYPE_1D: 143 if (layerCount == 1) 144 texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x())); 145 else 146 texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount)); 147 148 break; 149 150 case VK_IMAGE_TYPE_2D: 151 if (layerCount == 1) 152 { 153 texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y())); 154 } 155 else 156 { 157 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 158 { 159 if (layerCount == tcu::CUBEFACE_LAST && viewType == VK_IMAGE_VIEW_TYPE_CUBE) 160 { 161 texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x())); 162 } 163 else 164 { 165 DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0); 166 167 texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount)); 168 } 169 } 170 else 171 { 172 texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount)); 173 } 174 } 175 176 break; 177 178 case VK_IMAGE_TYPE_3D: 179 texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z())); 180 break; 181 182 default: 183 DE_ASSERT(false); 184 } 185 186 return texture; 187} 188 189} // anonymous 190 191void checkSupportImageSamplingInstance (Context& context, ImageSamplingInstanceParams params) 192{ 193 194 if (de::abs(params.samplerParams.mipLodBias) > context.getDeviceProperties().limits.maxSamplerLodBias) 195 TCU_THROW(NotSupportedError, "Unsupported sampler Lod bias value"); 196 197 if (!isSupportedSamplableFormat(context.getInstanceInterface(), context.getPhysicalDevice(), params.imageFormat)) 198 throw tcu::NotSupportedError(std::string("Unsupported format for sampling: ") + getFormatName(params.imageFormat)); 199 200 if ((deUint32)params.imageCount > context.getDeviceProperties().limits.maxColorAttachments) 201 throw tcu::NotSupportedError(std::string("Unsupported render target count: ") + de::toString(params.imageCount)); 202 203 if ((params.samplerParams.minFilter == VK_FILTER_LINEAR || 204 params.samplerParams.magFilter == VK_FILTER_LINEAR || 205 params.samplerParams.mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR) && 206 !isLinearFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(), params.imageFormat, VK_IMAGE_TILING_OPTIMAL)) 207 throw tcu::NotSupportedError(std::string("Unsupported format for linear filtering: ") + getFormatName(params.imageFormat)); 208 209 if (params.separateStencilUsage) 210 { 211 context.requireDeviceFunctionality("VK_EXT_separate_stencil_usage"); 212 context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2"); 213 214 const VkImageStencilUsageCreateInfo stencilUsage = 215 { 216 VK_STRUCTURE_TYPE_IMAGE_STENCIL_USAGE_CREATE_INFO, 217 DE_NULL, 218 VK_IMAGE_USAGE_TRANSFER_DST_BIT 219 }; 220 221 const VkPhysicalDeviceImageFormatInfo2 formatInfo2 = 222 { 223 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // VkStructureType sType 224 params.separateStencilUsage ? &stencilUsage 225 : DE_NULL, // const void* pNext 226 params.imageFormat, // VkFormat format 227 getCompatibleImageType(params.imageViewType), // VkImageType type 228 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling 229 VK_IMAGE_USAGE_SAMPLED_BIT 230 | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage 231 (VkImageCreateFlags)0u // VkImageCreateFlags flags 232 }; 233 234 VkImageFormatProperties2 extProperties = 235 { 236 VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, 237 DE_NULL, 238 { 239 { 240 0, // width 241 0, // height 242 0, // depth 243 }, 244 0u, // maxMipLevels 245 0u, // maxArrayLayers 246 0, // sampleCounts 247 0u, // maxResourceSize 248 }, 249 }; 250 251 if ((context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &formatInfo2, &extProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED) 252 || extProperties.imageFormatProperties.maxExtent.width < (deUint32)params.imageSize.x() 253 || extProperties.imageFormatProperties.maxExtent.height < (deUint32)params.imageSize.y()) 254 { 255 TCU_THROW(NotSupportedError, "Image format not supported"); 256 } 257 } 258 259 void const* pNext = params.samplerParams.pNext; 260 while (pNext != DE_NULL) 261 { 262 const VkStructureType nextType = *reinterpret_cast<const VkStructureType*>(pNext); 263 switch (nextType) 264 { 265 case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO: 266 { 267 context.requireDeviceFunctionality("VK_EXT_sampler_filter_minmax"); 268 269 if (!isMinMaxFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(), params.imageFormat, VK_IMAGE_TILING_OPTIMAL)) 270 throw tcu::NotSupportedError(std::string("Unsupported format for min/max filtering: ") + getFormatName(params.imageFormat)); 271 272 pNext = reinterpret_cast<const VkSamplerReductionModeCreateInfo*>(pNext)->pNext; 273 break; 274 } 275 case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO: 276 context.requireDeviceFunctionality("VK_KHR_sampler_ycbcr_conversion"); 277 278 pNext = reinterpret_cast<const VkSamplerYcbcrConversionInfo*>(pNext)->pNext; 279 break; 280 case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT: 281 pNext = reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT*>(pNext)->pNext; 282 283 if (!context.getCustomBorderColorFeaturesEXT().customBorderColors) 284 { 285 throw tcu::NotSupportedError("customBorderColors feature is not supported"); 286 } 287 288 break; 289 default: 290 TCU_FAIL("Unrecognized sType in chained sampler create info"); 291 } 292 } 293 294 if (params.samplerParams.addressModeU == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE || 295 params.samplerParams.addressModeV == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE || 296 params.samplerParams.addressModeW == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE) 297 { 298 context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge"); 299 } 300 301 if ((isCompressedFormat(params.imageFormat) || isDepthStencilFormat(params.imageFormat)) && params.imageViewType == VK_IMAGE_VIEW_TYPE_3D) 302 { 303 // \todo [2016-01-22 pyry] Mandate VK_ERROR_FORMAT_NOT_SUPPORTED 304 try 305 { 306 const VkImageFormatProperties formatProperties = getPhysicalDeviceImageFormatProperties(context.getInstanceInterface(), 307 context.getPhysicalDevice(), 308 params.imageFormat, 309 VK_IMAGE_TYPE_3D, 310 VK_IMAGE_TILING_OPTIMAL, 311 VK_IMAGE_USAGE_SAMPLED_BIT, 312 (VkImageCreateFlags)0); 313 314 if (formatProperties.maxExtent.width == 0 && 315 formatProperties.maxExtent.height == 0 && 316 formatProperties.maxExtent.depth == 0) 317 TCU_THROW(NotSupportedError, "3D compressed or depth format not supported"); 318 } 319 catch (const Error&) 320 { 321 TCU_THROW(NotSupportedError, "3D compressed or depth format not supported"); 322 } 323 } 324 325 if (params.imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 326 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY); 327 328 if (params.allocationKind == ALLOCATION_KIND_DEDICATED) 329 context.requireDeviceFunctionality("VK_KHR_dedicated_allocation"); 330 331#ifndef CTS_USES_VULKANSC 332 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset")) 333 { 334 const auto portabilitySubsetFeatures = context.getPortabilitySubsetFeatures(); 335 const auto componentMapping = params.componentMapping; 336 if (!portabilitySubsetFeatures.imageViewFormatSwizzle && 337 ((componentMapping.r != VK_COMPONENT_SWIZZLE_IDENTITY) || 338 (componentMapping.g != VK_COMPONENT_SWIZZLE_IDENTITY) || 339 (componentMapping.b != VK_COMPONENT_SWIZZLE_IDENTITY) || 340 (componentMapping.a != VK_COMPONENT_SWIZZLE_IDENTITY))) 341 { 342 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Implementation does not support remapping format components"); 343 } 344 } 345 346 bool formatRgba10x6WithoutYCbCrSampler = context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler; 347#else 348 bool formatRgba10x6WithoutYCbCrSampler = VK_FALSE; 349#endif // CTS_USES_VULKANSC 350 351 if ((params.imageFormat == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16) && (params.subresourceRange.levelCount > 1) && (formatRgba10x6WithoutYCbCrSampler == VK_FALSE)) 352 { 353 TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported"); 354 } 355} 356 357ImageSamplingInstance::ImageSamplingInstance (Context& context, 358 ImageSamplingInstanceParams params) 359 : vkt::TestInstance (context) 360 , m_allocationKind (params.allocationKind) 361 , m_samplingType (params.samplingType) 362 , m_imageViewType (params.imageViewType) 363 , m_imageFormat (params.imageFormat) 364 , m_imageSize (params.imageSize) 365 , m_layerCount (params.layerCount) 366 , m_imageCount (params.imageCount) 367 , m_componentMapping (params.componentMapping) 368 , m_componentMask (true) 369 , m_subresourceRange (params.subresourceRange) 370 , m_samplerParams (params.samplerParams) 371 , m_samplerLod (params.samplerLod) 372 , m_renderSize (params.renderSize) 373 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM) 374 , m_vertices (params.vertices) 375 , m_graphicsPipeline (context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), m_context.getDeviceExtensions(), params.pipelineConstructionType, params.pipelineCreateFlags) 376 , m_pipelineConstructionType (params.pipelineConstructionType) 377 , m_imageLayout (params.imageLayout) 378{ 379} 380 381void ImageSamplingInstance::setup () 382{ 383 const InstanceInterface& vki = m_context.getInstanceInterface(); 384 const DeviceInterface& vk = m_context.getDeviceInterface(); 385 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice(); 386 const VkDevice vkDevice = m_context.getDevice(); 387 const VkQueue queue = m_context.getUniversalQueue(); 388 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 389 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 390 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; 391 392 void const* pNext = m_samplerParams.pNext; 393 while (pNext != DE_NULL) 394 { 395 const VkStructureType nextType = *reinterpret_cast<const VkStructureType*>(pNext); 396 switch (nextType) 397 { 398 case VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO: 399 { 400 VkPhysicalDeviceSamplerFilterMinmaxProperties physicalDeviceSamplerMinMaxProperties = 401 { 402 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES, 403 DE_NULL, 404 DE_FALSE, 405 DE_FALSE 406 }; 407 VkPhysicalDeviceProperties2 physicalDeviceProperties; 408 physicalDeviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; 409 physicalDeviceProperties.pNext = &physicalDeviceSamplerMinMaxProperties; 410 411 vki.getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &physicalDeviceProperties); 412 413 if (physicalDeviceSamplerMinMaxProperties.filterMinmaxImageComponentMapping != VK_TRUE) 414 { 415 // If filterMinmaxImageComponentMapping is VK_FALSE the component mapping of the image 416 // view used with min/max filtering must have been created with the r component set to 417 // VK_COMPONENT_SWIZZLE_IDENTITY. Only the r component of the sampled image value is 418 // defined and the other component values are undefined 419 420 m_componentMask = tcu::BVec4(true, false, false, false); 421 422 if (m_componentMapping.r != VK_COMPONENT_SWIZZLE_IDENTITY && m_componentMapping.r != VK_COMPONENT_SWIZZLE_R) 423 { 424 TCU_THROW(NotSupportedError, "filterMinmaxImageComponentMapping is not supported (R mapping is not IDENTITY)"); 425 } 426 } 427 pNext = reinterpret_cast<const VkSamplerReductionModeCreateInfo*>(pNext)->pNext; 428 } 429 break; 430 case VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO: 431 pNext = reinterpret_cast<const VkSamplerYcbcrConversionInfo*>(pNext)->pNext; 432 break; 433 case VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT: 434 { 435 const VkSamplerCustomBorderColorCreateInfoEXT customBorderColorCreateInfo = *reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT*>(pNext); 436 437 VkPhysicalDeviceCustomBorderColorFeaturesEXT physicalDeviceCustomBorderColorFeatures = 438 { 439 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT, 440 DE_NULL, 441 DE_FALSE, 442 DE_FALSE 443 }; 444 VkPhysicalDeviceFeatures2 physicalDeviceFeatures; 445 physicalDeviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; 446 physicalDeviceFeatures.pNext = &physicalDeviceCustomBorderColorFeatures; 447 448 vki.getPhysicalDeviceFeatures2(m_context.getPhysicalDevice(), &physicalDeviceFeatures); 449 450 if (physicalDeviceCustomBorderColorFeatures.customBorderColors != VK_TRUE) 451 { 452 TCU_THROW(NotSupportedError, "customBorderColors are not supported"); 453 } 454 455 if (physicalDeviceCustomBorderColorFeatures.customBorderColorWithoutFormat != VK_TRUE && 456 customBorderColorCreateInfo.format == VK_FORMAT_UNDEFINED) 457 { 458 TCU_THROW(NotSupportedError, "customBorderColorWithoutFormat is not supported"); 459 } 460 461 pNext = reinterpret_cast<const VkSamplerCustomBorderColorCreateInfoEXT*>(pNext)->pNext; 462 } 463 break; 464 default: 465 TCU_FAIL("Unrecognized sType in chained sampler create info"); 466 } 467 } 468 469 // Create texture images, views and samplers 470 { 471 VkImageCreateFlags imageFlags = 0u; 472 473 if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 474 imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; 475 476 // Initialize texture data 477 if (isCompressedFormat(m_imageFormat)) 478 m_texture = createTestTexture(mapVkCompressedFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount); 479 else 480 m_texture = createTestTexture(mapVkFormat(m_imageFormat), m_imageViewType, m_imageSize, m_layerCount); 481 482 const VkImageCreateInfo imageParams = 483 { 484 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 485 DE_NULL, // const void* pNext; 486 imageFlags, // VkImageCreateFlags flags; 487 getCompatibleImageType(m_imageViewType), // VkImageType imageType; 488 m_imageFormat, // VkFormat format; 489 { // VkExtent3D extent; 490 (deUint32)m_imageSize.x(), 491 (deUint32)m_imageSize.y(), 492 (deUint32)m_imageSize.z() 493 }, 494 (deUint32)m_texture->getNumLevels(), // deUint32 mipLevels; 495 (deUint32)m_layerCount, // deUint32 arrayLayers; 496 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 497 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 498 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; 499 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 500 1u, // deUint32 queueFamilyIndexCount; 501 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 502 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; 503 }; 504 505 m_images.resize(m_imageCount); 506 m_imageAllocs.resize(m_imageCount); 507 m_imageViews.resize(m_imageCount); 508 509 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx) 510 { 511 m_images[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &imageParams))); 512 m_imageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_images[imgNdx], MemoryRequirement::Any, memAlloc, m_allocationKind))); 513 VK_CHECK(vk.bindImageMemory(vkDevice, **m_images[imgNdx], (*m_imageAllocs[imgNdx])->getMemory(), (*m_imageAllocs[imgNdx])->getOffset())); 514 515 // Upload texture data 516 uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, **m_images[imgNdx]); 517 518 // Create image view and sampler 519 const VkImageViewCreateInfo imageViewParams = 520 { 521 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 522 DE_NULL, // const void* pNext; 523 0u, // VkImageViewCreateFlags flags; 524 **m_images[imgNdx], // VkImage image; 525 m_imageViewType, // VkImageViewType viewType; 526 m_imageFormat, // VkFormat format; 527 m_componentMapping, // VkComponentMapping components; 528 m_subresourceRange, // VkImageSubresourceRange subresourceRange; 529 }; 530 531 m_imageViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &imageViewParams))); 532 } 533 534 m_sampler = createSampler(vk, vkDevice, &m_samplerParams); 535 } 536 537 // Create descriptor set for image and sampler 538 { 539 DescriptorPoolBuilder descriptorPoolBuilder; 540 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) 541 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_SAMPLER, 1u); 542 descriptorPoolBuilder.addType(m_samplingType, m_imageCount); 543 m_descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 544 m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? m_imageCount + 1u : m_imageCount); 545 546 DescriptorSetLayoutBuilder setLayoutBuilder; 547 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) 548 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT); 549 setLayoutBuilder.addArrayBinding(m_samplingType, m_imageCount, VK_SHADER_STAGE_FRAGMENT_BIT); 550 m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice); 551 552 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = 553 { 554 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType; 555 DE_NULL, // const void* pNext; 556 *m_descriptorPool, // VkDescriptorPool descriptorPool; 557 1u, // deUint32 setLayoutCount; 558 &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts; 559 }; 560 561 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo); 562 563 const VkSampler sampler = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? DE_NULL : *m_sampler; 564 std::vector<VkDescriptorImageInfo> descriptorImageInfo(m_imageCount); 565 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx) 566 { 567 descriptorImageInfo[imgNdx].sampler = sampler; // VkSampler sampler; 568 descriptorImageInfo[imgNdx].imageView = **m_imageViews[imgNdx]; // VkImageView imageView; 569 descriptorImageInfo[imgNdx].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; // VkImageLayout imageLayout; 570 } 571 572 DescriptorSetUpdateBuilder setUpdateBuilder; 573 if (m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) 574 { 575 const VkDescriptorImageInfo descriptorSamplerInfo = 576 { 577 *m_sampler, // VkSampler sampler; 578 DE_NULL, // VkImageView imageView; 579 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout; 580 }; 581 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_SAMPLER, &descriptorSamplerInfo); 582 } 583 584 const deUint32 binding = m_samplingType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ? 1u : 0u; 585 setUpdateBuilder.writeArray(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(binding), m_samplingType, m_imageCount, descriptorImageInfo.data()); 586 setUpdateBuilder.update(vk, vkDevice); 587 } 588 589 // Create color images and views 590 { 591 const VkImageCreateInfo colorImageParams = 592 { 593 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 594 DE_NULL, // const void* pNext; 595 0u, // VkImageCreateFlags flags; 596 VK_IMAGE_TYPE_2D, // VkImageType imageType; 597 m_colorFormat, // VkFormat format; 598 { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u }, // VkExtent3D extent; 599 1u, // deUint32 mipLevels; 600 1u, // deUint32 arrayLayers; 601 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 602 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 603 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; 604 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 605 1u, // deUint32 queueFamilyIndexCount; 606 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 607 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; 608 }; 609 610 m_colorImages.resize(m_imageCount); 611 m_colorImageAllocs.resize(m_imageCount); 612 m_colorAttachmentViews.resize(m_imageCount); 613 614 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx) 615 { 616 m_colorImages[imgNdx] = SharedImagePtr(new UniqueImage(createImage(vk, vkDevice, &colorImageParams))); 617 m_colorImageAllocs[imgNdx] = SharedAllocPtr(new UniqueAlloc(allocateImage(vki, vk, physDevice, vkDevice, **m_colorImages[imgNdx], MemoryRequirement::Any, memAlloc, m_allocationKind))); 618 VK_CHECK(vk.bindImageMemory(vkDevice, **m_colorImages[imgNdx], (*m_colorImageAllocs[imgNdx])->getMemory(), (*m_colorImageAllocs[imgNdx])->getOffset())); 619 620 const VkImageViewCreateInfo colorAttachmentViewParams = 621 { 622 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 623 DE_NULL, // const void* pNext; 624 0u, // VkImageViewCreateFlags flags; 625 **m_colorImages[imgNdx], // VkImage image; 626 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 627 m_colorFormat, // VkFormat format; 628 componentMappingRGBA, // VkComponentMapping components; 629 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 630 }; 631 632 m_colorAttachmentViews[imgNdx] = SharedImageViewPtr(new UniqueImageView(createImageView(vk, vkDevice, &colorAttachmentViewParams))); 633 } 634 } 635 636 // Create render pass 637 { 638 std::vector<VkAttachmentDescription> colorAttachmentDescriptions(m_imageCount); 639 std::vector<VkAttachmentReference> colorAttachmentReferences(m_imageCount); 640 641 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx) 642 { 643 colorAttachmentDescriptions[imgNdx].flags = 0u; // VkAttachmentDescriptionFlags flags; 644 colorAttachmentDescriptions[imgNdx].format = m_colorFormat; // VkFormat format; 645 colorAttachmentDescriptions[imgNdx].samples = VK_SAMPLE_COUNT_1_BIT; // VkSampleCountFlagBits samples; 646 colorAttachmentDescriptions[imgNdx].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // VkAttachmentLoadOp loadOp; 647 colorAttachmentDescriptions[imgNdx].storeOp = VK_ATTACHMENT_STORE_OP_STORE; // VkAttachmentStoreOp storeOp; 648 colorAttachmentDescriptions[imgNdx].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; // VkAttachmentLoadOp stencilLoadOp; 649 colorAttachmentDescriptions[imgNdx].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // VkAttachmentStoreOp stencilStoreOp; 650 colorAttachmentDescriptions[imgNdx].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout initialLayout; 651 colorAttachmentDescriptions[imgNdx].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout finalLayout; 652 653 colorAttachmentReferences[imgNdx].attachment = (deUint32)imgNdx; // deUint32 attachment; 654 colorAttachmentReferences[imgNdx].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout layout; 655 } 656 657 const VkSubpassDescription subpassDescription = 658 { 659 0u, // VkSubpassDescriptionFlags flags; 660 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 661 0u, // deUint32 inputAttachmentCount; 662 DE_NULL, // const VkAttachmentReference* pInputAttachments; 663 (deUint32)m_imageCount, // deUint32 colorAttachmentCount; 664 &colorAttachmentReferences[0], // const VkAttachmentReference* pColorAttachments; 665 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 666 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 667 0u, // deUint32 preserveAttachmentCount; 668 DE_NULL // const VkAttachmentReference* pPreserveAttachments; 669 }; 670 671 const VkRenderPassCreateInfo renderPassParams = 672 { 673 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 674 DE_NULL, // const void* pNext; 675 0u, // VkRenderPassCreateFlags flags; 676 (deUint32)m_imageCount, // deUint32 attachmentCount; 677 &colorAttachmentDescriptions[0], // const VkAttachmentDescription* pAttachments; 678 1u, // deUint32 subpassCount; 679 &subpassDescription, // const VkSubpassDescription* pSubpasses; 680 0u, // deUint32 dependencyCount; 681 DE_NULL // const VkSubpassDependency* pDependencies; 682 }; 683 684 m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, vkDevice, &renderPassParams); 685 } 686 687 // Create framebuffer 688 { 689 std::vector<VkImage> images (m_imageCount); 690 std::vector<VkImageView> pAttachments (m_imageCount); 691 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx) 692 { 693 images[imgNdx] = m_colorImages[imgNdx]->get(); 694 pAttachments[imgNdx] = m_colorAttachmentViews[imgNdx]->get(); 695 } 696 697 const VkFramebufferCreateInfo framebufferParams = 698 { 699 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 700 DE_NULL, // const void* pNext; 701 0u, // VkFramebufferCreateFlags flags; 702 *m_renderPass, // VkRenderPass renderPass; 703 (deUint32)m_imageCount, // deUint32 attachmentCount; 704 &pAttachments[0], // const VkImageView* pAttachments; 705 (deUint32)m_renderSize.x(), // deUint32 width; 706 (deUint32)m_renderSize.y(), // deUint32 height; 707 1u // deUint32 layers; 708 }; 709 710 m_renderPass.createFramebuffer(vk, vkDevice, &framebufferParams, images); 711 } 712 713 // Create pipeline layout 714 { 715#ifndef CTS_USES_VULKANSC 716 VkPipelineLayoutCreateFlags pipelineLayoutFlags = (!isConstructionTypeLibrary(m_pipelineConstructionType)) ? 0u : deUint32(VK_PIPELINE_LAYOUT_CREATE_INDEPENDENT_SETS_BIT_EXT); 717#else 718 VkPipelineLayoutCreateFlags pipelineLayoutFlags = 0u; 719#endif // CTS_USES_VULKANSC 720 VkPipelineLayoutCreateInfo pipelineLayoutParams 721 { 722 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 723 DE_NULL, // const void* pNext; 724 pipelineLayoutFlags, // VkPipelineLayoutCreateFlags flags; 725 0u, // deUint32 setLayoutCount; 726 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts; 727 0u, // deUint32 pushConstantRangeCount; 728 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 729 }; 730 731 m_preRasterizationStatePipelineLayout = PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams); 732 pipelineLayoutParams.setLayoutCount = 1u; 733 pipelineLayoutParams.pSetLayouts = &m_descriptorSetLayout.get(); 734 m_fragmentStatePipelineLayout = PipelineLayoutWrapper(m_pipelineConstructionType, vk, vkDevice, &pipelineLayoutParams); 735 } 736 737 m_vertexShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0); 738 m_fragmentShaderModule = ShaderWrapper(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0); 739 740 // Create pipeline 741 { 742 const VkVertexInputBindingDescription vertexInputBindingDescription = 743 { 744 0u, // deUint32 binding; 745 sizeof(Vertex4Tex4), // deUint32 strideInBytes; 746 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate; 747 }; 748 749 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = 750 { 751 { 752 0u, // deUint32 location; 753 0u, // deUint32 binding; 754 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 755 0u // deUint32 offset; 756 }, 757 { 758 1u, // deUint32 location; 759 0u, // deUint32 binding; 760 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 761 DE_OFFSET_OF(Vertex4Tex4, texCoord), // deUint32 offset; 762 } 763 }; 764 765 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 766 { 767 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 768 DE_NULL, // const void* pNext; 769 0u, // VkPipelineVertexInputStateCreateFlags flags; 770 1u, // deUint32 vertexBindingDescriptionCount; 771 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 772 2u, // deUint32 vertexAttributeDescriptionCount; 773 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 774 }; 775 776 const std::vector<VkViewport> viewports { makeViewport(m_renderSize) }; 777 const std::vector<VkRect2D> scissors { makeRect2D(m_renderSize) }; 778 779 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(m_imageCount); 780 781 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx) 782 { 783 colorBlendAttachmentStates[imgNdx].blendEnable = false; // VkBool32 blendEnable; 784 colorBlendAttachmentStates[imgNdx].srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // VkBlendFactor srcColorBlendFactor; 785 colorBlendAttachmentStates[imgNdx].dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstColorBlendFactor; 786 colorBlendAttachmentStates[imgNdx].colorBlendOp = VK_BLEND_OP_ADD; // VkBlendOp colorBlendOp; 787 colorBlendAttachmentStates[imgNdx].srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // VkBlendFactor srcAlphaBlendFactor; 788 colorBlendAttachmentStates[imgNdx].dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // VkBlendFactor dstAlphaBlendFactor; 789 colorBlendAttachmentStates[imgNdx].alphaBlendOp = VK_BLEND_OP_ADD; // VkBlendOp alphaBlendOp; 790 colorBlendAttachmentStates[imgNdx].colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask; 791 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; 792 } 793 794 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = 795 { 796 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 797 DE_NULL, // const void* pNext; 798 0u, // VkPipelineColorBlendStateCreateFlags flags; 799 false, // VkBool32 logicOpEnable; 800 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 801 (deUint32)m_imageCount, // deUint32 attachmentCount; 802 &colorBlendAttachmentStates[0], // const VkPipelineColorBlendAttachmentState* pAttachments; 803 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]; 804 }; 805 806 m_graphicsPipeline.setMonolithicPipelineLayout(m_fragmentStatePipelineLayout) 807 .setDefaultDepthStencilState() 808 .setDefaultRasterizationState() 809 .setDefaultMultisampleState() 810 .setupVertexInputState(&vertexInputStateParams) 811 .setupPreRasterizationShaderState(viewports, 812 scissors, 813 m_preRasterizationStatePipelineLayout, 814 *m_renderPass, 815 0u, 816 m_vertexShaderModule) 817 .setupFragmentShaderState(m_fragmentStatePipelineLayout, *m_renderPass, 0u, m_fragmentShaderModule) 818 .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams) 819 .buildPipeline(); 820 } 821 822 // Create vertex buffer 823 { 824 const VkDeviceSize vertexBufferSize = (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4)); 825 const VkBufferCreateInfo vertexBufferParams = 826 { 827 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 828 DE_NULL, // const void* pNext; 829 0u, // VkBufferCreateFlags flags; 830 vertexBufferSize, // VkDeviceSize size; 831 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 832 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 833 1u, // deUint32 queueFamilyIndexCount; 834 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 835 }; 836 837 DE_ASSERT(vertexBufferSize > 0); 838 839 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); 840 m_vertexBufferAlloc = allocateBuffer(vki, vk, physDevice, vkDevice, *m_vertexBuffer, MemoryRequirement::HostVisible, memAlloc, m_allocationKind); 841 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset())); 842 843 // Load vertices into vertex buffer 844 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize); 845 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc); 846 } 847 848 // Create command pool 849 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex); 850 851 // Create command buffer 852 { 853 const std::vector<VkClearValue> attachmentClearValues (m_imageCount, defaultClearValue(m_colorFormat)); 854 855 std::vector<VkImageMemoryBarrier> preAttachmentBarriers(m_imageCount); 856 857 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx) 858 { 859 preAttachmentBarriers[imgNdx].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; // VkStructureType sType; 860 preAttachmentBarriers[imgNdx].pNext = DE_NULL; // const void* pNext; 861 preAttachmentBarriers[imgNdx].srcAccessMask = 0u; // VkAccessFlags srcAccessMask; 862 preAttachmentBarriers[imgNdx].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; // VkAccessFlags dstAccessMask; 863 preAttachmentBarriers[imgNdx].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED; // VkImageLayout oldLayout; 864 preAttachmentBarriers[imgNdx].newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; // VkImageLayout newLayout; 865 preAttachmentBarriers[imgNdx].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // deUint32 srcQueueFamilyIndex; 866 preAttachmentBarriers[imgNdx].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; // deUint32 dstQueueFamilyIndex; 867 preAttachmentBarriers[imgNdx].image = **m_colorImages[imgNdx]; // VkImage image; 868 preAttachmentBarriers[imgNdx].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; // VkImageSubresourceRange subresourceRange; 869 preAttachmentBarriers[imgNdx].subresourceRange.baseMipLevel = 0u; 870 preAttachmentBarriers[imgNdx].subresourceRange.levelCount = 1u; 871 preAttachmentBarriers[imgNdx].subresourceRange.baseArrayLayer = 0u; 872 preAttachmentBarriers[imgNdx].subresourceRange.layerCount = 1u; 873 } 874 875 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY); 876 877 beginCommandBuffer(vk, *m_cmdBuffer, 0u); 878 879 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 880 0u, DE_NULL, 0u, DE_NULL, (deUint32)m_imageCount, &preAttachmentBarriers[0]); 881 882 m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), (deUint32)attachmentClearValues.size(), &attachmentClearValues[0]); 883 884 m_graphicsPipeline.bind(*m_cmdBuffer); 885 886 m_fragmentStatePipelineLayout.bindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 1, &m_descriptorSet.get(), 0, DE_NULL); 887 888 const VkDeviceSize vertexBufferOffset = 0; 889 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset); 890 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0); 891 892 m_renderPass.end(vk, *m_cmdBuffer); 893 endCommandBuffer(vk, *m_cmdBuffer); 894 } 895} 896 897ImageSamplingInstance::~ImageSamplingInstance (void) 898{ 899} 900 901tcu::TestStatus ImageSamplingInstance::iterate (void) 902{ 903 const DeviceInterface& vk = m_context.getDeviceInterface(); 904 const VkDevice vkDevice = m_context.getDevice(); 905 const VkQueue queue = m_context.getUniversalQueue(); 906 907 setup(); 908 909 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get()); 910 911 return verifyImage(); 912} 913 914namespace 915{ 916 917bool isLookupResultValid (const tcu::Texture1DView& texture, 918 const tcu::Sampler& sampler, 919 const tcu::LookupPrecision& precision, 920 const tcu::Vec4& coords, 921 const tcu::Vec2& lodBounds, 922 const tcu::Vec4& result) 923{ 924 return tcu::isLookupResultValid(texture, sampler, precision, coords.x(), lodBounds, result); 925} 926 927bool isLookupResultValid (const tcu::Texture1DArrayView& texture, 928 const tcu::Sampler& sampler, 929 const tcu::LookupPrecision& precision, 930 const tcu::Vec4& coords, 931 const tcu::Vec2& lodBounds, 932 const tcu::Vec4& result) 933{ 934 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1), lodBounds, result); 935} 936 937bool isLookupResultValid (const tcu::Texture2DView& texture, 938 const tcu::Sampler& sampler, 939 const tcu::LookupPrecision& precision, 940 const tcu::Vec4& coords, 941 const tcu::Vec2& lodBounds, 942 const tcu::Vec4& result) 943{ 944 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1), lodBounds, result); 945} 946 947bool isLookupResultValid (const tcu::Texture2DArrayView& texture, 948 const tcu::Sampler& sampler, 949 const tcu::LookupPrecision& precision, 950 const tcu::Vec4& coords, 951 const tcu::Vec2& lodBounds, 952 const tcu::Vec4& result) 953{ 954 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result); 955} 956 957bool isLookupResultValid (const tcu::TextureCubeView& texture, 958 const tcu::Sampler& sampler, 959 const tcu::LookupPrecision& precision, 960 const tcu::Vec4& coords, 961 const tcu::Vec2& lodBounds, 962 const tcu::Vec4& result) 963{ 964 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result); 965} 966 967bool isLookupResultValid (const tcu::TextureCubeArrayView& texture, 968 const tcu::Sampler& sampler, 969 const tcu::LookupPrecision& precision, 970 const tcu::Vec4& coords, 971 const tcu::Vec2& lodBounds, 972 const tcu::Vec4& result) 973{ 974 return tcu::isLookupResultValid(texture, sampler, precision, tcu::IVec4(precision.coordBits.x()), coords, lodBounds, result); 975} 976 977bool isLookupResultValid(const tcu::Texture3DView& texture, 978 const tcu::Sampler& sampler, 979 const tcu::LookupPrecision& precision, 980 const tcu::Vec4& coords, 981 const tcu::Vec2& lodBounds, 982 const tcu::Vec4& result) 983{ 984 return tcu::isLookupResultValid(texture, sampler, precision, coords.swizzle(0,1,2), lodBounds, result); 985} 986 987template<typename TextureViewType> 988bool validateResultImage (const TextureViewType& texture, 989 const tcu::Sampler& sampler, 990 const tcu::ConstPixelBufferAccess& texCoords, 991 const tcu::Vec2& lodBounds, 992 const tcu::LookupPrecision& lookupPrecision, 993 const tcu::Vec4& lookupScale, 994 const tcu::Vec4& lookupBias, 995 const tcu::ConstPixelBufferAccess& result, 996 const tcu::PixelBufferAccess& errorMask) 997{ 998 const int w = result.getWidth(); 999 const int h = result.getHeight(); 1000 bool allOk = true; 1001 1002 for (int y = 0; y < h; ++y) 1003 { 1004 for (int x = 0; x < w; ++x) 1005 { 1006 const tcu::Vec4 resultPixel = result.getPixel(x, y); 1007 const tcu::Vec4 resultColor = (resultPixel - lookupBias) / lookupScale; 1008 const tcu::Vec4 texCoord = texCoords.getPixel(x, y); 1009 const bool pixelOk = isLookupResultValid(texture, sampler, lookupPrecision, texCoord, lodBounds, resultColor); 1010 1011 errorMask.setPixel(tcu::Vec4(pixelOk?0.0f:1.0f, pixelOk?1.0f:0.0f, 0.0f, 1.0f), x, y); 1012 1013 if (!pixelOk) 1014 allOk = false; 1015 } 1016 } 1017 1018 return allOk; 1019} 1020 1021template<typename ScalarType> 1022ScalarType getSwizzledComp (const tcu::Vector<ScalarType, 4>& vec, vk::VkComponentSwizzle comp, int identityNdx) 1023{ 1024 if (comp == vk::VK_COMPONENT_SWIZZLE_IDENTITY) 1025 return vec[identityNdx]; 1026 else if (comp == vk::VK_COMPONENT_SWIZZLE_ZERO) 1027 return ScalarType(0); 1028 else if (comp == vk::VK_COMPONENT_SWIZZLE_ONE) 1029 return ScalarType(1); 1030 else 1031 return vec[comp - vk::VK_COMPONENT_SWIZZLE_R]; 1032} 1033 1034template<typename ScalarType> 1035tcu::Vector<ScalarType, 4> swizzle (const tcu::Vector<ScalarType, 4>& vec, const vk::VkComponentMapping& swz) 1036{ 1037 return tcu::Vector<ScalarType, 4>(getSwizzledComp(vec, swz.r, 0), 1038 getSwizzledComp(vec, swz.g, 1), 1039 getSwizzledComp(vec, swz.b, 2), 1040 getSwizzledComp(vec, swz.a, 3)); 1041} 1042 1043/*--------------------------------------------------------------------*//*! 1044* \brief Swizzle scale or bias vector by given mapping 1045* 1046* \param vec scale or bias vector 1047* \param swz swizzle component mapping, may include ZERO, ONE, or IDENTITY 1048* \param zeroOrOneValue vector value for component swizzled as ZERO or ONE 1049* \return swizzled vector 1050*//*--------------------------------------------------------------------*/ 1051tcu::Vec4 swizzleScaleBias (const tcu::Vec4& vec, const vk::VkComponentMapping& swz, float zeroOrOneValue) 1052{ 1053 1054 // Remove VK_COMPONENT_SWIZZLE_IDENTITY to avoid addressing channelValues[0] 1055 const vk::VkComponentMapping nonIdentitySwz = 1056 { 1057 swz.r == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_R : swz.r, 1058 swz.g == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_G : swz.g, 1059 swz.b == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_B : swz.b, 1060 swz.a == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_A : swz.a 1061 }; 1062 1063 const float channelValues[] = 1064 { 1065 -1.0f, // impossible 1066 zeroOrOneValue, // SWIZZLE_ZERO 1067 zeroOrOneValue, // SWIZZLE_ONE 1068 vec.x(), 1069 vec.y(), 1070 vec.z(), 1071 vec.w(), 1072 }; 1073 1074 return tcu::Vec4(channelValues[nonIdentitySwz.r], channelValues[nonIdentitySwz.g], channelValues[nonIdentitySwz.b], channelValues[nonIdentitySwz.a]); 1075} 1076 1077template<typename ScalarType> 1078void swizzleT (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz) 1079{ 1080 for (int z = 0; z < dst.getDepth(); ++z) 1081 for (int y = 0; y < dst.getHeight(); ++y) 1082 for (int x = 0; x < dst.getWidth(); ++x) 1083 dst.setPixel(swizzle(src.getPixelT<ScalarType>(x, y, z), swz), x, y, z); 1084} 1085 1086void swizzleFromSRGB (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz) 1087{ 1088 for (int z = 0; z < dst.getDepth(); ++z) 1089 for (int y = 0; y < dst.getHeight(); ++y) 1090 for (int x = 0; x < dst.getWidth(); ++x) 1091 dst.setPixel(swizzle(tcu::sRGBToLinear(src.getPixelT<float>(x, y, z)), swz), x, y, z); 1092} 1093 1094void swizzle (const tcu::ConstPixelBufferAccess& src, const tcu::PixelBufferAccess& dst, const vk::VkComponentMapping& swz) 1095{ 1096 const tcu::TextureChannelClass chnClass = tcu::getTextureChannelClass(dst.getFormat().type); 1097 1098 DE_ASSERT(src.getWidth() == dst.getWidth() && 1099 src.getHeight() == dst.getHeight() && 1100 src.getDepth() == dst.getDepth()); 1101 1102 if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) 1103 swizzleT<deInt32>(src, dst, swz); 1104 else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) 1105 swizzleT<deUint32>(src, dst, swz); 1106 else if (tcu::isSRGB(src.getFormat()) && !tcu::isSRGB(dst.getFormat())) 1107 swizzleFromSRGB(src, dst, swz); 1108 else 1109 swizzleT<float>(src, dst, swz); 1110} 1111 1112bool isIdentitySwizzle (const vk::VkComponentMapping& swz) 1113{ 1114 return (swz.r == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.r == vk::VK_COMPONENT_SWIZZLE_R) && 1115 (swz.g == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.g == vk::VK_COMPONENT_SWIZZLE_G) && 1116 (swz.b == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.b == vk::VK_COMPONENT_SWIZZLE_B) && 1117 (swz.a == vk::VK_COMPONENT_SWIZZLE_IDENTITY || swz.a == vk::VK_COMPONENT_SWIZZLE_A); 1118} 1119 1120template<typename TextureViewType> struct TexViewTraits; 1121 1122template<> struct TexViewTraits<tcu::Texture1DView> { typedef tcu::Texture1D TextureType; }; 1123template<> struct TexViewTraits<tcu::Texture1DArrayView> { typedef tcu::Texture1DArray TextureType; }; 1124template<> struct TexViewTraits<tcu::Texture2DView> { typedef tcu::Texture2D TextureType; }; 1125template<> struct TexViewTraits<tcu::Texture2DArrayView> { typedef tcu::Texture2DArray TextureType; }; 1126template<> struct TexViewTraits<tcu::TextureCubeView> { typedef tcu::TextureCube TextureType; }; 1127template<> struct TexViewTraits<tcu::TextureCubeArrayView> { typedef tcu::TextureCubeArray TextureType; }; 1128template<> struct TexViewTraits<tcu::Texture3DView> { typedef tcu::Texture3D TextureType; }; 1129 1130template<typename TextureViewType> 1131typename TexViewTraits<TextureViewType>::TextureType* createSkeletonClone (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0); 1132 1133tcu::TextureFormat getSwizzleTargetFormat (tcu::TextureFormat format) 1134{ 1135 // Swizzled texture needs to hold all four channels 1136 // \todo [2016-09-21 pyry] We could save some memory by using smaller formats 1137 // when possible (for example U8). 1138 1139 const tcu::TextureChannelClass chnClass = tcu::getTextureChannelClass(format.type); 1140 1141 if (chnClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) 1142 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32); 1143 else if (chnClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) 1144 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32); 1145 else 1146 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT); 1147} 1148 1149template<> 1150tcu::Texture1D* createSkeletonClone<tcu::Texture1DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0) 1151{ 1152 return new tcu::Texture1D(format, level0.getWidth()); 1153} 1154 1155template<> 1156tcu::Texture1DArray* createSkeletonClone<tcu::Texture1DArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0) 1157{ 1158 return new tcu::Texture1DArray(format, level0.getWidth(), level0.getHeight()); 1159} 1160 1161template<> 1162tcu::Texture2D* createSkeletonClone<tcu::Texture2DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0) 1163{ 1164 return new tcu::Texture2D(format, level0.getWidth(), level0.getHeight()); 1165} 1166 1167template<> 1168tcu::Texture2DArray* createSkeletonClone<tcu::Texture2DArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0) 1169{ 1170 return new tcu::Texture2DArray(format, level0.getWidth(), level0.getHeight(), level0.getDepth()); 1171} 1172 1173template<> 1174tcu::Texture3D* createSkeletonClone<tcu::Texture3DView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0) 1175{ 1176 return new tcu::Texture3D(format, level0.getWidth(), level0.getHeight(), level0.getDepth()); 1177} 1178 1179template<> 1180tcu::TextureCubeArray* createSkeletonClone<tcu::TextureCubeArrayView> (tcu::TextureFormat format, const tcu::ConstPixelBufferAccess& level0) 1181{ 1182 return new tcu::TextureCubeArray(format, level0.getWidth(), level0.getDepth()); 1183} 1184 1185template<typename TextureViewType> 1186MovePtr<typename TexViewTraits<TextureViewType>::TextureType> createSwizzledCopy (const TextureViewType& texture, const vk::VkComponentMapping& swz) 1187{ 1188 MovePtr<typename TexViewTraits<TextureViewType>::TextureType> copy (createSkeletonClone<TextureViewType>(getSwizzleTargetFormat(texture.getLevel(0).getFormat()), texture.getLevel(0))); 1189 1190 for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx) 1191 { 1192 copy->allocLevel(levelNdx); 1193 swizzle(texture.getLevel(levelNdx), copy->getLevel(levelNdx), swz); 1194 } 1195 1196 return copy; 1197} 1198 1199template<> 1200MovePtr<tcu::TextureCube> createSwizzledCopy (const tcu::TextureCubeView& texture, const vk::VkComponentMapping& swz) 1201{ 1202 MovePtr<tcu::TextureCube> copy (new tcu::TextureCube(getSwizzleTargetFormat(texture.getLevelFace(0, tcu::CUBEFACE_NEGATIVE_X).getFormat()), texture.getSize())); 1203 1204 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx) 1205 { 1206 for (int levelNdx = 0; levelNdx < texture.getNumLevels(); ++levelNdx) 1207 { 1208 copy->allocLevel((tcu::CubeFace)faceNdx, levelNdx); 1209 swizzle(texture.getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), copy->getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), swz); 1210 } 1211 } 1212 1213 return copy; 1214} 1215 1216template<typename TextureViewType> 1217bool validateResultImage (const TextureViewType& texture, 1218 const tcu::Sampler& sampler, 1219 const vk::VkComponentMapping& swz, 1220 const tcu::ConstPixelBufferAccess& texCoords, 1221 const tcu::Vec2& lodBounds, 1222 const tcu::LookupPrecision& lookupPrecision, 1223 const tcu::Vec4& lookupScale, 1224 const tcu::Vec4& lookupBias, 1225 const tcu::ConstPixelBufferAccess& result, 1226 const tcu::PixelBufferAccess& errorMask) 1227{ 1228 if (isIdentitySwizzle(swz)) 1229 return validateResultImage(texture, sampler, texCoords, lodBounds, lookupPrecision, lookupScale, lookupBias, result, errorMask); 1230 else 1231 { 1232 // There is (currently) no way to handle swizzling inside validation loop 1233 // and thus we need to pre-swizzle the texture. 1234 UniquePtr<typename TexViewTraits<TextureViewType>::TextureType> swizzledTex (createSwizzledCopy(texture, swz)); 1235 1236 return validateResultImage(*swizzledTex, sampler, texCoords, lodBounds, lookupPrecision, swizzleScaleBias(lookupScale, swz, 1.0f), swizzleScaleBias(lookupBias, swz, 0.0f), result, errorMask); 1237 } 1238} 1239 1240vk::VkImageSubresourceRange resolveSubresourceRange (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource) 1241{ 1242 vk::VkImageSubresourceRange resolved = subresource; 1243 1244 if (subresource.levelCount == VK_REMAINING_MIP_LEVELS) 1245 resolved.levelCount = testTexture.getNumLevels()-subresource.baseMipLevel; 1246 1247 if (subresource.layerCount == VK_REMAINING_ARRAY_LAYERS) 1248 resolved.layerCount = testTexture.getArraySize()-subresource.baseArrayLayer; 1249 1250 return resolved; 1251} 1252 1253MovePtr<tcu::Texture1DView> getTexture1DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels) 1254{ 1255 DE_ASSERT(subresource.layerCount == 1); 1256 1257 levels.resize(subresource.levelCount); 1258 1259 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx) 1260 { 1261 const tcu::ConstPixelBufferAccess& srcLevel = testTexture.getLevel((int)subresource.baseMipLevel+levelNdx, subresource.baseArrayLayer); 1262 1263 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, 0, srcLevel.getWidth(), 1, 1); 1264 } 1265 1266 return MovePtr<tcu::Texture1DView>(new tcu::Texture1DView((int)levels.size(), &levels[0])); 1267} 1268 1269MovePtr<tcu::Texture1DArrayView> getTexture1DArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels) 1270{ 1271 const TestTexture1D* tex1D = dynamic_cast<const TestTexture1D*>(&testTexture); 1272 const TestTexture1DArray* tex1DArray = dynamic_cast<const TestTexture1DArray*>(&testTexture); 1273 1274 DE_ASSERT(!!tex1D != !!tex1DArray); 1275 DE_ASSERT(tex1DArray || subresource.baseArrayLayer == 0); 1276 1277 levels.resize(subresource.levelCount); 1278 1279 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx) 1280 { 1281 const tcu::ConstPixelBufferAccess& srcLevel = tex1D ? tex1D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx) 1282 : tex1DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx); 1283 1284 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, (int)subresource.baseArrayLayer, 0, srcLevel.getWidth(), (int)subresource.layerCount, 1); 1285 } 1286 1287 return MovePtr<tcu::Texture1DArrayView>(new tcu::Texture1DArrayView((int)levels.size(), &levels[0])); 1288} 1289 1290MovePtr<tcu::Texture2DView> getTexture2DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels) 1291{ 1292 const TestTexture2D* tex2D = dynamic_cast<const TestTexture2D*>(&testTexture); 1293 const TestTexture2DArray* tex2DArray = dynamic_cast<const TestTexture2DArray*>(&testTexture); 1294 1295 DE_ASSERT(subresource.layerCount == 1); 1296 DE_ASSERT(!!tex2D != !!tex2DArray); 1297 DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0); 1298 1299 levels.resize(subresource.levelCount); 1300 1301 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx) 1302 { 1303 const tcu::ConstPixelBufferAccess& srcLevel = tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx) 1304 : tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx); 1305 1306 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), 1); 1307 } 1308 1309 return MovePtr<tcu::Texture2DView>(new tcu::Texture2DView((int)levels.size(), &levels[0])); 1310} 1311 1312MovePtr<tcu::Texture2DArrayView> getTexture2DArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels) 1313{ 1314 const TestTexture2D* tex2D = dynamic_cast<const TestTexture2D*>(&testTexture); 1315 const TestTexture2DArray* tex2DArray = dynamic_cast<const TestTexture2DArray*>(&testTexture); 1316 1317 DE_ASSERT(!!tex2D != !!tex2DArray); 1318 DE_ASSERT(tex2DArray || subresource.baseArrayLayer == 0); 1319 1320 levels.resize(subresource.levelCount); 1321 1322 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx) 1323 { 1324 const tcu::ConstPixelBufferAccess& srcLevel = tex2D ? tex2D->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx) 1325 : tex2DArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx); 1326 1327 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), (int)subresource.layerCount); 1328 } 1329 1330 return MovePtr<tcu::Texture2DArrayView>(new tcu::Texture2DArrayView((int)levels.size(), &levels[0])); 1331} 1332 1333MovePtr<tcu::TextureCubeView> getTextureCubeView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels) 1334{ 1335 const static tcu::CubeFace s_faceMap[tcu::CUBEFACE_LAST] = 1336 { 1337 tcu::CUBEFACE_POSITIVE_X, 1338 tcu::CUBEFACE_NEGATIVE_X, 1339 tcu::CUBEFACE_POSITIVE_Y, 1340 tcu::CUBEFACE_NEGATIVE_Y, 1341 tcu::CUBEFACE_POSITIVE_Z, 1342 tcu::CUBEFACE_NEGATIVE_Z 1343 }; 1344 1345 const TestTextureCube* texCube = dynamic_cast<const TestTextureCube*>(&testTexture); 1346 const TestTextureCubeArray* texCubeArray = dynamic_cast<const TestTextureCubeArray*>(&testTexture); 1347 1348 DE_ASSERT(!!texCube != !!texCubeArray); 1349 DE_ASSERT(subresource.layerCount == 6); 1350 DE_ASSERT(texCubeArray || subresource.baseArrayLayer == 0); 1351 1352 levels.resize(subresource.levelCount*tcu::CUBEFACE_LAST); 1353 1354 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx) 1355 { 1356 for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx) 1357 { 1358 const tcu::ConstPixelBufferAccess& srcLevel = texCubeArray ? texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx) 1359 : texCube->getTexture().getLevelFace(levelNdx, s_faceMap[faceNdx]); 1360 1361 levels[faceNdx*subresource.levelCount + levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer + (texCubeArray ? faceNdx : 0), srcLevel.getWidth(), srcLevel.getHeight(), 1); 1362 } 1363 } 1364 1365 { 1366 const tcu::ConstPixelBufferAccess* reordered[tcu::CUBEFACE_LAST]; 1367 1368 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx) 1369 reordered[s_faceMap[faceNdx]] = &levels[faceNdx*subresource.levelCount]; 1370 1371 return MovePtr<tcu::TextureCubeView>(new tcu::TextureCubeView((int)subresource.levelCount, reordered)); 1372 } 1373} 1374 1375MovePtr<tcu::TextureCubeArrayView> getTextureCubeArrayView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels) 1376{ 1377 const TestTextureCubeArray* texCubeArray = dynamic_cast<const TestTextureCubeArray*>(&testTexture); 1378 1379 DE_ASSERT(texCubeArray); 1380 DE_ASSERT(subresource.layerCount%6 == 0); 1381 1382 levels.resize(subresource.levelCount); 1383 1384 for (int levelNdx = 0; levelNdx < (int)subresource.levelCount; ++levelNdx) 1385 { 1386 const tcu::ConstPixelBufferAccess& srcLevel = texCubeArray->getTexture().getLevel((int)subresource.baseMipLevel+levelNdx); 1387 1388 levels[levelNdx] = tcu::getSubregion(srcLevel, 0, 0, (int)subresource.baseArrayLayer, srcLevel.getWidth(), srcLevel.getHeight(), (int)subresource.layerCount); 1389 } 1390 1391 return MovePtr<tcu::TextureCubeArrayView>(new tcu::TextureCubeArrayView((int)levels.size(), &levels[0])); 1392} 1393 1394MovePtr<tcu::Texture3DView> getTexture3DView (const TestTexture& testTexture, const vk::VkImageSubresourceRange& subresource, std::vector<tcu::ConstPixelBufferAccess>& levels) 1395{ 1396 DE_ASSERT(subresource.baseArrayLayer == 0 && subresource.layerCount == 1); 1397 1398 levels.resize(subresource.levelCount); 1399 1400 for (int levelNdx = 0; levelNdx < (int)levels.size(); ++levelNdx) 1401 levels[levelNdx] = testTexture.getLevel((int)subresource.baseMipLevel+levelNdx, subresource.baseArrayLayer); 1402 1403 return MovePtr<tcu::Texture3DView>(new tcu::Texture3DView((int)levels.size(), &levels[0])); 1404} 1405 1406bool validateResultImage (const TestTexture& texture, 1407 const VkImageViewType imageViewType, 1408 const VkImageSubresourceRange& subresource, 1409 const tcu::Sampler& sampler, 1410 const vk::VkComponentMapping& componentMapping, 1411 const tcu::ConstPixelBufferAccess& coordAccess, 1412 const tcu::Vec2& lodBounds, 1413 const tcu::LookupPrecision& lookupPrecision, 1414 const tcu::Vec4& lookupScale, 1415 const tcu::Vec4& lookupBias, 1416 const tcu::ConstPixelBufferAccess& resultAccess, 1417 const tcu::PixelBufferAccess& errorAccess) 1418{ 1419 std::vector<tcu::ConstPixelBufferAccess> levels; 1420 1421 switch (imageViewType) 1422 { 1423 case VK_IMAGE_VIEW_TYPE_1D: 1424 { 1425 UniquePtr<tcu::Texture1DView> texView(getTexture1DView(texture, subresource, levels)); 1426 1427 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess); 1428 } 1429 1430 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 1431 { 1432 UniquePtr<tcu::Texture1DArrayView> texView(getTexture1DArrayView(texture, subresource, levels)); 1433 1434 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess); 1435 } 1436 1437 case VK_IMAGE_VIEW_TYPE_2D: 1438 { 1439 UniquePtr<tcu::Texture2DView> texView(getTexture2DView(texture, subresource, levels)); 1440 1441 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess); 1442 } 1443 1444 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 1445 { 1446 UniquePtr<tcu::Texture2DArrayView> texView(getTexture2DArrayView(texture, subresource, levels)); 1447 1448 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess); 1449 } 1450 1451 case VK_IMAGE_VIEW_TYPE_CUBE: 1452 { 1453 UniquePtr<tcu::TextureCubeView> texView(getTextureCubeView(texture, subresource, levels)); 1454 1455 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess); 1456 } 1457 1458 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 1459 { 1460 UniquePtr<tcu::TextureCubeArrayView> texView(getTextureCubeArrayView(texture, subresource, levels)); 1461 1462 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess); 1463 } 1464 1465 case VK_IMAGE_VIEW_TYPE_3D: 1466 { 1467 UniquePtr<tcu::Texture3DView> texView(getTexture3DView(texture, subresource, levels)); 1468 1469 return validateResultImage(*texView, sampler, componentMapping, coordAccess, lodBounds, lookupPrecision, lookupScale, lookupBias, resultAccess, errorAccess); 1470 } 1471 1472 default: 1473 DE_ASSERT(false); 1474 return false; 1475 } 1476} 1477 1478} // anonymous 1479 1480tcu::TestStatus ImageSamplingInstance::verifyImage (void) 1481{ 1482 const VkPhysicalDeviceLimits& limits = m_context.getDeviceProperties().limits; 1483 // \note Color buffer is used to capture coordinates - not sampled texture values 1484 const tcu::TextureFormat colorFormat (tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT); 1485 const tcu::TextureFormat depthStencilFormat; // Undefined depth/stencil format. 1486 const CoordinateCaptureProgram coordCaptureProgram; 1487 const rr::Program rrProgram = coordCaptureProgram.getReferenceProgram(); 1488 ReferenceRenderer refRenderer (m_renderSize.x(), m_renderSize.y(), 1, colorFormat, depthStencilFormat, &rrProgram); 1489 const bool useStencilAspect = (m_subresourceRange.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT); 1490 1491 bool compareOkAll = true; 1492 1493 tcu::Vec4 lookupScale (1.0f); 1494 tcu::Vec4 lookupBias (0.0f); 1495 1496 getLookupScaleBias(m_imageFormat, lookupScale, lookupBias, useStencilAspect); 1497 1498 // Render out coordinates 1499 { 1500 const rr::RenderState renderState(refRenderer.getViewportState(), m_context.getDeviceProperties().limits.subPixelPrecisionBits); 1501 refRenderer.draw(renderState, rr::PRIMITIVETYPE_TRIANGLES, m_vertices); 1502 } 1503 1504 // Verify results 1505 { 1506 const tcu::Sampler sampler = mapVkSampler(m_samplerParams); 1507 const float referenceLod = de::clamp(m_samplerParams.mipLodBias + m_samplerLod, m_samplerParams.minLod, m_samplerParams.maxLod); 1508 const float lodError = 1.0f / static_cast<float>((1u << limits.mipmapPrecisionBits) - 1u); 1509 const tcu::Vec2 lodBounds (referenceLod - lodError, referenceLod + lodError); 1510 const vk::VkImageSubresourceRange subresource = resolveSubresourceRange(*m_texture, m_subresourceRange); 1511 1512 const tcu::ConstPixelBufferAccess coordAccess = refRenderer.getAccess(); 1513 tcu::TextureLevel errorMask (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), (int)m_renderSize.x(), (int)m_renderSize.y()); 1514 const tcu::PixelBufferAccess errorAccess = errorMask.getAccess(); 1515 1516 const bool isNearestOnly = (m_samplerParams.minFilter == VK_FILTER_NEAREST && m_samplerParams.magFilter == VK_FILTER_NEAREST); 1517 1518 tcu::LookupPrecision lookupPrecision; 1519 1520 // Set precision requirements - very low for these tests as 1521 // the point of the test is not to validate accuracy. 1522 lookupPrecision.coordBits = tcu::IVec3(17, 17, 17); 1523 lookupPrecision.uvwBits = tcu::IVec3(5, 5, 5); 1524 lookupPrecision.colorMask = m_componentMask; 1525 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(max((tcu::IVec4(8, 8, 8, 8) - (isNearestOnly ? 1 : 2)), tcu::IVec4(0))) / swizzleScaleBias(lookupScale, m_componentMapping, 1.0f); 1526 1527 if (m_imageFormat == VK_FORMAT_BC5_UNORM_BLOCK || m_imageFormat == VK_FORMAT_BC5_SNORM_BLOCK) 1528 lookupPrecision.colorThreshold = tcu::Vec4(0.06f, 0.06f, 0.06f, 0.06f); 1529 if (tcu::isSRGB(m_texture->getTextureFormat())) 1530 lookupPrecision.colorThreshold += tcu::Vec4(4.f / 255.f); 1531 1532 de::MovePtr<TestTexture> textureCopy; 1533 TestTexture* texture = DE_NULL; 1534 1535 if (isCombinedDepthStencilType(m_texture->getTextureFormat().type)) 1536 { 1537 // Verification loop does not support reading from combined depth stencil texture levels. 1538 // Get rid of stencil component. 1539 1540 tcu::TextureFormat::ChannelOrder channelOrder = tcu::TextureFormat::CHANNELORDER_LAST; 1541 tcu::TextureFormat::ChannelType channelType = tcu::TextureFormat::CHANNELTYPE_LAST; 1542 1543 if (subresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT) 1544 { 1545 channelOrder = tcu::TextureFormat::S; 1546 channelType = tcu::TextureFormat::UNSIGNED_INT8; 1547 } 1548 else 1549 { 1550 channelOrder = tcu::TextureFormat::D; 1551 1552 switch (m_texture->getTextureFormat().type) 1553 { 1554 case tcu::TextureFormat::UNSIGNED_INT_16_8_8: 1555 channelType = tcu::TextureFormat::UNORM_INT16; 1556 break; 1557 case tcu::TextureFormat::UNSIGNED_INT_24_8: 1558 case tcu::TextureFormat::UNSIGNED_INT_24_8_REV: 1559 channelType = tcu::TextureFormat::UNORM_INT24; 1560 break; 1561 case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: 1562 channelType = tcu::TextureFormat::FLOAT; 1563 break; 1564 default: 1565 DE_FATAL("Unhandled texture format type in switch"); 1566 } 1567 } 1568 1569 textureCopy = m_texture->copy(tcu::TextureFormat(channelOrder, channelType)); 1570 texture = textureCopy.get(); 1571 } 1572 else 1573 { 1574 texture = m_texture.get(); 1575 } 1576 1577 for (int imgNdx = 0; imgNdx < m_imageCount; ++imgNdx) 1578 { 1579 // Read back result image 1580 UniquePtr<tcu::TextureLevel> result (readColorAttachment(m_context.getDeviceInterface(), 1581 m_context.getDevice(), 1582 m_context.getUniversalQueue(), 1583 m_context.getUniversalQueueFamilyIndex(), 1584 m_context.getDefaultAllocator(), 1585 **m_colorImages[imgNdx], 1586 m_colorFormat, 1587 m_renderSize)); 1588 const tcu::ConstPixelBufferAccess resultAccess = result->getAccess(); 1589 bool compareOk = validateResultImage(*texture, 1590 m_imageViewType, 1591 subresource, 1592 sampler, 1593 m_componentMapping, 1594 coordAccess, 1595 lodBounds, 1596 lookupPrecision, 1597 lookupScale, 1598 lookupBias, 1599 resultAccess, 1600 errorAccess); 1601 if (!compareOk) 1602 m_context.getTestContext().getLog() 1603 << tcu::TestLog::Image("Result", "Result Image", resultAccess) 1604 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorAccess); 1605 1606 compareOkAll = compareOkAll && compareOk; 1607 } 1608 } 1609 1610 if (compareOkAll) 1611 return tcu::TestStatus::pass("Result image matches reference"); 1612 else 1613 return tcu::TestStatus::fail("Image mismatch"); 1614} 1615 1616} // pipeline 1617} // vkt 1618