1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 The Khronos Group Inc. 6 * Copyright (c) 2015 Imagination Technologies Ltd. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Image sampling case 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktPipelineImageSamplingInstance.hpp" 26 #include "vktPipelineClearUtil.hpp" 27 #include "vktPipelineReferenceRenderer.hpp" 28 #include "vkBuilderUtil.hpp" 29 #include "vkImageUtil.hpp" 30 #include "vkPrograms.hpp" 31 #include "vkQueryUtil.hpp" 32 #include "vkRefUtil.hpp" 33 #include "tcuImageCompare.hpp" 34 35 namespace vkt 36 { 37 namespace pipeline 38 { 39 40 using namespace vk; 41 using de::MovePtr; 42 43 namespace 44 { 45 46 static VkImageType getCompatibleImageType (VkImageViewType viewType) 47 { 48 switch (viewType) 49 { 50 case VK_IMAGE_VIEW_TYPE_1D: return VK_IMAGE_TYPE_1D; 51 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: return VK_IMAGE_TYPE_1D; 52 case VK_IMAGE_VIEW_TYPE_2D: return VK_IMAGE_TYPE_2D; 53 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: return VK_IMAGE_TYPE_2D; 54 case VK_IMAGE_VIEW_TYPE_3D: return VK_IMAGE_TYPE_3D; 55 case VK_IMAGE_VIEW_TYPE_CUBE: return VK_IMAGE_TYPE_2D; 56 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: return VK_IMAGE_TYPE_2D; 57 default: 58 break; 59 } 60 61 DE_ASSERT(false); 62 return VK_IMAGE_TYPE_1D; 63 } 64 65 template<typename TcuFormatType> 66 static MovePtr<TestTexture> createTestTexture (const TcuFormatType format, VkImageViewType viewType, const tcu::IVec3& size, int layerCount) 67 { 68 MovePtr<TestTexture> texture; 69 const VkImageType imageType = getCompatibleImageType(viewType); 70 71 switch (imageType) 72 { 73 case VK_IMAGE_TYPE_1D: 74 if (layerCount == 1) 75 texture = MovePtr<TestTexture>(new TestTexture1D(format, size.x())); 76 else 77 texture = MovePtr<TestTexture>(new TestTexture1DArray(format, size.x(), layerCount)); 78 79 break; 80 81 case VK_IMAGE_TYPE_2D: 82 if (layerCount == 1) 83 { 84 texture = MovePtr<TestTexture>(new TestTexture2D(format, size.x(), size.y())); 85 } 86 else 87 { 88 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 89 { 90 if (layerCount == tcu::CUBEFACE_LAST) 91 { 92 texture = MovePtr<TestTexture>(new TestTextureCube(format, size.x())); 93 } 94 else 95 { 96 DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0); 97 98 texture = MovePtr<TestTexture>(new TestTextureCubeArray(format, size.x(), layerCount)); 99 } 100 } 101 else 102 { 103 texture = MovePtr<TestTexture>(new TestTexture2DArray(format, size.x(), size.y(), layerCount)); 104 } 105 } 106 107 break; 108 109 case VK_IMAGE_TYPE_3D: 110 texture = MovePtr<TestTexture>(new TestTexture3D(format, size.x(), size.y(), size.z())); 111 break; 112 113 default: 114 DE_ASSERT(false); 115 } 116 117 return texture; 118 } 119 120 template<typename TcuTextureType> 121 static void copySubresourceRange (TcuTextureType& dest, const TcuTextureType& src, const VkImageSubresourceRange& subresourceRange) 122 { 123 DE_ASSERT(subresourceRange.levelCount <= (deUint32)dest.getNumLevels()); 124 DE_ASSERT(subresourceRange.baseMipLevel + subresourceRange.levelCount <= (deUint32)src.getNumLevels()); 125 126 for (int levelNdx = 0; levelNdx < dest.getNumLevels(); levelNdx++) 127 { 128 const tcu::ConstPixelBufferAccess srcLevel (src.getLevel(subresourceRange.baseMipLevel + levelNdx)); 129 const deUint32 srcLayerOffset = subresourceRange.baseArrayLayer * srcLevel.getWidth() * srcLevel.getHeight() * srcLevel.getFormat().getPixelSize(); 130 const tcu::ConstPixelBufferAccess srcLevelLayers (srcLevel.getFormat(), srcLevel.getWidth(), srcLevel.getHeight(), subresourceRange.layerCount, (deUint8*)srcLevel.getDataPtr() + srcLayerOffset); 131 132 if (dest.isLevelEmpty(levelNdx)) 133 dest.allocLevel(levelNdx); 134 135 tcu::copy(dest.getLevel(levelNdx), srcLevelLayers); 136 } 137 } 138 139 template<> 140 void copySubresourceRange<tcu::Texture1DArray> (tcu::Texture1DArray& dest, const tcu::Texture1DArray& src, const VkImageSubresourceRange& subresourceRange) 141 { 142 DE_ASSERT(subresourceRange.levelCount <= (deUint32)dest.getNumLevels()); 143 DE_ASSERT(subresourceRange.baseMipLevel + subresourceRange.levelCount <= (deUint32)src.getNumLevels()); 144 145 DE_ASSERT(subresourceRange.layerCount == (deUint32)dest.getNumLayers()); 146 DE_ASSERT(subresourceRange.baseArrayLayer + subresourceRange.layerCount <= (deUint32)src.getNumLayers()); 147 148 for (int levelNdx = 0; levelNdx < dest.getNumLevels(); levelNdx++) 149 { 150 const tcu::ConstPixelBufferAccess srcLevel (src.getLevel(subresourceRange.baseMipLevel + levelNdx)); 151 const deUint32 srcLayerOffset = subresourceRange.baseArrayLayer * srcLevel.getWidth() * srcLevel.getFormat().getPixelSize(); 152 const tcu::ConstPixelBufferAccess srcLevelLayers (srcLevel.getFormat(), srcLevel.getWidth(), subresourceRange.layerCount, 1, (deUint8*)srcLevel.getDataPtr() + srcLayerOffset); 153 154 if (dest.isLevelEmpty(levelNdx)) 155 dest.allocLevel(levelNdx); 156 157 tcu::copy(dest.getLevel(levelNdx), srcLevelLayers); 158 } 159 } 160 161 template<> 162 void copySubresourceRange<tcu::Texture3D>(tcu::Texture3D& dest, const tcu::Texture3D& src, const VkImageSubresourceRange& subresourceRange) 163 { 164 DE_ASSERT(subresourceRange.levelCount <= (deUint32)dest.getNumLevels()); 165 DE_ASSERT(subresourceRange.baseMipLevel + subresourceRange.levelCount <= (deUint32)src.getNumLevels()); 166 167 for (int levelNdx = 0; levelNdx < dest.getNumLevels(); levelNdx++) 168 { 169 const tcu::ConstPixelBufferAccess srcLevel(src.getLevel(subresourceRange.baseMipLevel + levelNdx)); 170 const tcu::ConstPixelBufferAccess srcLevelLayers(srcLevel.getFormat(), srcLevel.getWidth(), srcLevel.getHeight(), srcLevel.getDepth(), (deUint8*)srcLevel.getDataPtr()); 171 172 if (dest.isLevelEmpty(levelNdx)) 173 dest.allocLevel(levelNdx); 174 175 tcu::copy(dest.getLevel(levelNdx), srcLevelLayers); 176 } 177 } 178 179 static MovePtr<Program> createRefProgram(const tcu::TextureFormat& renderTargetFormat, 180 const tcu::Sampler& sampler, 181 float samplerLod, 182 const tcu::UVec4& componentMapping, 183 const TestTexture& testTexture, 184 VkImageViewType viewType, 185 int layerCount, 186 const VkImageSubresourceRange& subresource) 187 { 188 MovePtr<Program> program; 189 const VkImageType imageType = getCompatibleImageType(viewType); 190 tcu::Vec4 lookupScale (1.0f); 191 tcu::Vec4 lookupBias (0.0f); 192 193 if (!testTexture.isCompressed()) 194 { 195 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(testTexture.getLevel(0, 0).getFormat()); 196 197 // Needed to normalize various formats to 0..1 range for writing into RT 198 lookupScale = fmtInfo.lookupScale; 199 lookupBias = fmtInfo.lookupBias; 200 } 201 // else: All supported compressed formats are fine with no normalization. 202 // ASTC LDR blocks decompress to f16 so querying normalization parameters 203 // based on uncompressed formats would actually lead to massive precision loss 204 // and complete lack of coverage in case of R8G8B8A8_UNORM RT. 205 206 switch (imageType) 207 { 208 case VK_IMAGE_TYPE_1D: 209 if (layerCount == 1) 210 { 211 const tcu::Texture1D& texture = dynamic_cast<const TestTexture1D&>(testTexture).getTexture(); 212 program = MovePtr<Program>(new SamplerProgram<tcu::Texture1D>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping)); 213 } 214 else 215 { 216 const tcu::Texture1DArray& texture = dynamic_cast<const TestTexture1DArray&>(testTexture).getTexture(); 217 218 if (subresource.baseMipLevel > 0 || subresource.layerCount < (deUint32)texture.getNumLayers()) 219 { 220 // Not all texture levels and layers are needed. Create new sub-texture. 221 const tcu::ConstPixelBufferAccess baseLevel = texture.getLevel(subresource.baseMipLevel); 222 tcu::Texture1DArray textureView (texture.getFormat(), baseLevel.getWidth(), subresource.layerCount); 223 224 copySubresourceRange(textureView, texture, subresource); 225 226 program = MovePtr<Program>(new SamplerProgram<tcu::Texture1DArray>(renderTargetFormat, textureView, sampler, samplerLod, lookupScale, lookupBias, componentMapping)); 227 } 228 else 229 { 230 program = MovePtr<Program>(new SamplerProgram<tcu::Texture1DArray>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping)); 231 } 232 } 233 break; 234 235 case VK_IMAGE_TYPE_2D: 236 if (layerCount == 1) 237 { 238 const tcu::Texture2D& texture = dynamic_cast<const TestTexture2D&>(testTexture).getTexture(); 239 program = MovePtr<Program>(new SamplerProgram<tcu::Texture2D>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping)); 240 } 241 else 242 { 243 if (viewType == VK_IMAGE_VIEW_TYPE_CUBE || viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 244 { 245 if (layerCount == tcu::CUBEFACE_LAST) 246 { 247 const tcu::TextureCube& texture = dynamic_cast<const TestTextureCube&>(testTexture).getTexture(); 248 program = MovePtr<Program>(new SamplerProgram<tcu::TextureCube>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping)); 249 } 250 else 251 { 252 DE_ASSERT(layerCount % tcu::CUBEFACE_LAST == 0); 253 254 const tcu::TextureCubeArray& texture = dynamic_cast<const TestTextureCubeArray&>(testTexture).getTexture(); 255 256 if (subresource.baseMipLevel > 0 || subresource.layerCount < (deUint32)texture.getDepth()) 257 { 258 DE_ASSERT(subresource.baseArrayLayer + subresource.layerCount <= (deUint32)texture.getDepth()); 259 260 // Not all texture levels and layers are needed. Create new sub-texture. 261 const tcu::ConstPixelBufferAccess baseLevel = texture.getLevel(subresource.baseMipLevel); 262 tcu::TextureCubeArray textureView (texture.getFormat(), baseLevel.getWidth(), subresource.layerCount); 263 264 copySubresourceRange(textureView, texture, subresource); 265 266 program = MovePtr<Program>(new SamplerProgram<tcu::TextureCubeArray>(renderTargetFormat, textureView, sampler, samplerLod, lookupScale, lookupBias, componentMapping)); 267 } 268 else 269 { 270 // Use all array layers 271 program = MovePtr<Program>(new SamplerProgram<tcu::TextureCubeArray>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping)); 272 } 273 } 274 } 275 else 276 { 277 const tcu::Texture2DArray& texture = dynamic_cast<const TestTexture2DArray&>(testTexture).getTexture(); 278 279 if (subresource.baseMipLevel > 0 || subresource.layerCount < (deUint32)texture.getNumLayers()) 280 { 281 DE_ASSERT(subresource.baseArrayLayer + subresource.layerCount <= (deUint32)texture.getNumLayers()); 282 283 // Not all texture levels and layers are needed. Create new sub-texture. 284 const tcu::ConstPixelBufferAccess baseLevel = texture.getLevel(subresource.baseMipLevel); 285 tcu::Texture2DArray textureView (texture.getFormat(), baseLevel.getWidth(), baseLevel.getHeight(), subresource.layerCount); 286 287 copySubresourceRange(textureView, texture, subresource); 288 289 program = MovePtr<Program>(new SamplerProgram<tcu::Texture2DArray>(renderTargetFormat, textureView, sampler, samplerLod, lookupScale, lookupBias, componentMapping)); 290 } 291 else 292 { 293 // Use all array layers 294 program = MovePtr<Program>(new SamplerProgram<tcu::Texture2DArray>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping)); 295 } 296 } 297 } 298 break; 299 300 case VK_IMAGE_TYPE_3D: 301 { 302 const tcu::Texture3D& texture = dynamic_cast<const TestTexture3D&>(testTexture).getTexture(); 303 304 if (subresource.baseMipLevel > 0) 305 { 306 // Not all texture levels are needed. Create new sub-texture. 307 const tcu::ConstPixelBufferAccess baseLevel = texture.getLevel(subresource.baseMipLevel); 308 tcu::Texture3D textureView(texture.getFormat(), baseLevel.getWidth(), baseLevel.getHeight(), baseLevel.getDepth()); 309 310 copySubresourceRange(textureView, texture, subresource); 311 312 program = MovePtr<Program>(new SamplerProgram<tcu::Texture3D>(renderTargetFormat, textureView, sampler, samplerLod, lookupScale, lookupBias, componentMapping)); 313 } 314 else 315 { 316 program = MovePtr<Program>(new SamplerProgram<tcu::Texture3D>(renderTargetFormat, texture, sampler, samplerLod, lookupScale, lookupBias, componentMapping)); 317 } 318 } 319 break; 320 321 default: 322 DE_ASSERT(false); 323 } 324 325 return program; 326 } 327 328 } // anonymous 329 330 ImageSamplingInstance::ImageSamplingInstance (Context& context, 331 const tcu::UVec2& renderSize, 332 VkImageViewType imageViewType, 333 VkFormat imageFormat, 334 const tcu::IVec3& imageSize, 335 int layerCount, 336 const VkComponentMapping& componentMapping, 337 const VkImageSubresourceRange& subresourceRange, 338 const VkSamplerCreateInfo& samplerParams, 339 float samplerLod, 340 const std::vector<Vertex4Tex4>& vertices) 341 : vkt::TestInstance (context) 342 , m_imageViewType (imageViewType) 343 , m_imageFormat (imageFormat) 344 , m_imageSize (imageSize) 345 , m_layerCount (layerCount) 346 , m_componentMapping (componentMapping) 347 , m_subresourceRange (subresourceRange) 348 , m_samplerParams (samplerParams) 349 , m_samplerLod (samplerLod) 350 , m_renderSize (renderSize) 351 , m_colorFormat (VK_FORMAT_R8G8B8A8_UNORM) 352 , m_vertices (vertices) 353 { 354 const DeviceInterface& vk = context.getDeviceInterface(); 355 const VkDevice vkDevice = context.getDevice(); 356 const VkQueue queue = context.getUniversalQueue(); 357 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 358 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice())); 359 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; 360 361 if (!isSupportedSamplableFormat(context.getInstanceInterface(), context.getPhysicalDevice(), imageFormat)) 362 throw tcu::NotSupportedError(std::string("Unsupported format for sampling: ") + getFormatName(imageFormat)); 363 364 if ((samplerParams.minFilter == VK_FILTER_LINEAR || 365 samplerParams.magFilter == VK_FILTER_LINEAR || 366 samplerParams.mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR) && 367 !isLinearFilteringSupported(context.getInstanceInterface(), context.getPhysicalDevice(), imageFormat, VK_IMAGE_TILING_OPTIMAL)) 368 throw tcu::NotSupportedError(std::string("Unsupported format for linear filtering: ") + getFormatName(imageFormat)); 369 370 if (isCompressedFormat(imageFormat) && imageViewType == VK_IMAGE_VIEW_TYPE_3D) 371 { 372 // \todo [2016-01-22 pyry] Mandate VK_ERROR_FORMAT_NOT_SUPPORTED 373 try 374 { 375 const VkImageFormatProperties formatProperties = getPhysicalDeviceImageFormatProperties(context.getInstanceInterface(), 376 context.getPhysicalDevice(), 377 imageFormat, 378 VK_IMAGE_TYPE_3D, 379 VK_IMAGE_TILING_OPTIMAL, 380 VK_IMAGE_USAGE_SAMPLED_BIT, 381 (VkImageCreateFlags)0); 382 383 if (formatProperties.maxExtent.width == 0 && 384 formatProperties.maxExtent.height == 0 && 385 formatProperties.maxExtent.depth == 0) 386 TCU_THROW(NotSupportedError, "3D compressed format not supported"); 387 } 388 catch (const Error&) 389 { 390 TCU_THROW(NotSupportedError, "3D compressed format not supported"); 391 } 392 } 393 394 // Create texture image, view and sampler 395 { 396 VkImageCreateFlags imageFlags = 0u; 397 398 if (m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE || m_imageViewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 399 imageFlags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; 400 401 // Initialize texture data 402 if (isCompressedFormat(imageFormat)) 403 m_texture = createTestTexture(mapVkCompressedFormat(imageFormat), imageViewType, imageSize, layerCount); 404 else 405 m_texture = createTestTexture(mapVkFormat(imageFormat), imageViewType, imageSize, layerCount); 406 407 const VkImageCreateInfo imageParams = 408 { 409 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 410 DE_NULL, // const void* pNext; 411 imageFlags, // VkImageCreateFlags flags; 412 getCompatibleImageType(m_imageViewType), // VkImageType imageType; 413 imageFormat, // VkFormat format; 414 { // VkExtent3D extent; 415 (deUint32)m_imageSize.x(), 416 (deUint32)m_imageSize.y(), 417 (deUint32)m_imageSize.z() 418 }, 419 (deUint32)m_texture->getNumLevels(), // deUint32 mipLevels; 420 (deUint32)m_layerCount, // deUint32 arrayLayers; 421 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 422 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 423 VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; 424 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 425 1u, // deUint32 queueFamilyIndexCount; 426 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 427 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; 428 }; 429 430 m_image = createImage(vk, vkDevice, &imageParams); 431 m_imageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_image), MemoryRequirement::Any); 432 VK_CHECK(vk.bindImageMemory(vkDevice, *m_image, m_imageAlloc->getMemory(), m_imageAlloc->getOffset())); 433 434 // Upload texture data 435 uploadTestTexture(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_texture, *m_image); 436 437 // Create image view and sampler 438 const VkImageViewCreateInfo imageViewParams = 439 { 440 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 441 DE_NULL, // const void* pNext; 442 0u, // VkImageViewCreateFlags flags; 443 *m_image, // VkImage image; 444 m_imageViewType, // VkImageViewType viewType; 445 imageFormat, // VkFormat format; 446 m_componentMapping, // VkComponentMapping components; 447 m_subresourceRange, // VkImageSubresourceRange subresourceRange; 448 }; 449 450 m_imageView = createImageView(vk, vkDevice, &imageViewParams); 451 m_sampler = createSampler(vk, vkDevice, &m_samplerParams); 452 } 453 454 // Create descriptor set for combined image and sampler 455 { 456 DescriptorPoolBuilder descriptorPoolBuilder; 457 descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u); 458 m_descriptorPool = descriptorPoolBuilder.build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 459 460 DescriptorSetLayoutBuilder setLayoutBuilder; 461 setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT); 462 m_descriptorSetLayout = setLayoutBuilder.build(vk, vkDevice); 463 464 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo = 465 { 466 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType; 467 DE_NULL, // const void* pNext; 468 *m_descriptorPool, // VkDescriptorPool descriptorPool; 469 1u, // deUint32 setLayoutCount; 470 &m_descriptorSetLayout.get() // const VkDescriptorSetLayout* pSetLayouts; 471 }; 472 473 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo); 474 475 const VkDescriptorImageInfo descriptorImageInfo = 476 { 477 *m_sampler, // VkSampler sampler; 478 *m_imageView, // VkImageView imageView; 479 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout; 480 }; 481 482 DescriptorSetUpdateBuilder setUpdateBuilder; 483 setUpdateBuilder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfo); 484 setUpdateBuilder.update(vk, vkDevice); 485 } 486 487 // Create color image and view 488 { 489 const VkImageCreateInfo colorImageParams = 490 { 491 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 492 DE_NULL, // const void* pNext; 493 0u, // VkImageCreateFlags flags; 494 VK_IMAGE_TYPE_2D, // VkImageType imageType; 495 m_colorFormat, // VkFormat format; 496 { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y(), 1u }, // VkExtent3D extent; 497 1u, // deUint32 mipLevels; 498 1u, // deUint32 arrayLayers; 499 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 500 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 501 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; 502 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 503 1u, // deUint32 queueFamilyIndexCount; 504 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices; 505 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout; 506 }; 507 508 m_colorImage = createImage(vk, vkDevice, &colorImageParams); 509 m_colorImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any); 510 VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset())); 511 512 const VkImageViewCreateInfo colorAttachmentViewParams = 513 { 514 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 515 DE_NULL, // const void* pNext; 516 0u, // VkImageViewCreateFlags flags; 517 *m_colorImage, // VkImage image; 518 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 519 m_colorFormat, // VkFormat format; 520 componentMappingRGBA, // VkComponentMapping components; 521 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 522 }; 523 524 m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams); 525 } 526 527 // Create render pass 528 { 529 const VkAttachmentDescription colorAttachmentDescription = 530 { 531 0u, // VkAttachmentDescriptionFlags flags; 532 m_colorFormat, // VkFormat format; 533 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 534 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; 535 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; 536 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; 537 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; 538 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; 539 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; 540 }; 541 542 const VkAttachmentReference colorAttachmentReference = 543 { 544 0u, // deUint32 attachment; 545 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; 546 }; 547 548 const VkSubpassDescription subpassDescription = 549 { 550 0u, // VkSubpassDescriptionFlags flags; 551 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; 552 0u, // deUint32 inputAttachmentCount; 553 DE_NULL, // const VkAttachmentReference* pInputAttachments; 554 1u, // deUint32 colorAttachmentCount; 555 &colorAttachmentReference, // const VkAttachmentReference* pColorAttachments; 556 DE_NULL, // const VkAttachmentReference* pResolveAttachments; 557 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment; 558 0u, // deUint32 preserveAttachmentCount; 559 DE_NULL // const VkAttachmentReference* pPreserveAttachments; 560 }; 561 562 const VkRenderPassCreateInfo renderPassParams = 563 { 564 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; 565 DE_NULL, // const void* pNext; 566 0u, // VkRenderPassCreateFlags flags; 567 1u, // deUint32 attachmentCount; 568 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments; 569 1u, // deUint32 subpassCount; 570 &subpassDescription, // const VkSubpassDescription* pSubpasses; 571 0u, // deUint32 dependencyCount; 572 DE_NULL // const VkSubpassDependency* pDependencies; 573 }; 574 575 m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams); 576 } 577 578 // Create framebuffer 579 { 580 const VkFramebufferCreateInfo framebufferParams = 581 { 582 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; 583 DE_NULL, // const void* pNext; 584 0u, // VkFramebufferCreateFlags flags; 585 *m_renderPass, // VkRenderPass renderPass; 586 1u, // deUint32 attachmentCount; 587 &m_colorAttachmentView.get(), // const VkImageView* pAttachments; 588 (deUint32)m_renderSize.x(), // deUint32 width; 589 (deUint32)m_renderSize.y(), // deUint32 height; 590 1u // deUint32 layers; 591 }; 592 593 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams); 594 } 595 596 // Create pipeline layout 597 { 598 const VkPipelineLayoutCreateInfo pipelineLayoutParams = 599 { 600 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType; 601 DE_NULL, // const void* pNext; 602 0u, // VkPipelineLayoutCreateFlags flags; 603 1u, // deUint32 setLayoutCount; 604 &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts; 605 0u, // deUint32 pushConstantRangeCount; 606 DE_NULL // const VkPushConstantRange* pPushConstantRanges; 607 }; 608 609 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams); 610 } 611 612 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_vert"), 0); 613 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("tex_frag"), 0); 614 615 // Create pipeline 616 { 617 const VkPipelineShaderStageCreateInfo shaderStages[2] = 618 { 619 { 620 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 621 DE_NULL, // const void* pNext; 622 0u, // VkPipelineShaderStageCreateFlags flags; 623 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage; 624 *m_vertexShaderModule, // VkShaderModule module; 625 "main", // const char* pName; 626 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 627 }, 628 { 629 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType; 630 DE_NULL, // const void* pNext; 631 0u, // VkPipelineShaderStageCreateFlags flags; 632 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage; 633 *m_fragmentShaderModule, // VkShaderModule module; 634 "main", // const char* pName; 635 DE_NULL // const VkSpecializationInfo* pSpecializationInfo; 636 } 637 }; 638 639 const VkVertexInputBindingDescription vertexInputBindingDescription = 640 { 641 0u, // deUint32 binding; 642 sizeof(Vertex4Tex4), // deUint32 strideInBytes; 643 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate; 644 }; 645 646 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = 647 { 648 { 649 0u, // deUint32 location; 650 0u, // deUint32 binding; 651 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 652 0u // deUint32 offset; 653 }, 654 { 655 1u, // deUint32 location; 656 0u, // deUint32 binding; 657 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format; 658 DE_OFFSET_OF(Vertex4Tex4, texCoord), // deUint32 offset; 659 } 660 }; 661 662 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams = 663 { 664 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType; 665 DE_NULL, // const void* pNext; 666 0u, // VkPipelineVertexInputStateCreateFlags flags; 667 1u, // deUint32 vertexBindingDescriptionCount; 668 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions; 669 2u, // deUint32 vertexAttributeDescriptionCount; 670 vertexInputAttributeDescriptions // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions; 671 }; 672 673 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams = 674 { 675 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType; 676 DE_NULL, // const void* pNext; 677 0u, // VkPipelineInputAssemblyStateCreateFlags flags; 678 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology; 679 false // VkBool32 primitiveRestartEnable; 680 }; 681 682 const VkViewport viewport = 683 { 684 0.0f, // float x; 685 0.0f, // float y; 686 (float)m_renderSize.x(), // float width; 687 (float)m_renderSize.y(), // float height; 688 0.0f, // float minDepth; 689 1.0f // float maxDepth; 690 }; 691 692 const VkRect2D scissor = { { 0, 0 }, { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() } }; 693 694 const VkPipelineViewportStateCreateInfo viewportStateParams = 695 { 696 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType; 697 DE_NULL, // const void* pNext; 698 0u, // VkPipelineViewportStateCreateFlags flags; 699 1u, // deUint32 viewportCount; 700 &viewport, // const VkViewport* pViewports; 701 1u, // deUint32 scissorCount; 702 &scissor // const VkRect2D* pScissors; 703 }; 704 705 const VkPipelineRasterizationStateCreateInfo rasterStateParams = 706 { 707 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType; 708 DE_NULL, // const void* pNext; 709 0u, // VkPipelineRasterizationStateCreateFlags flags; 710 false, // VkBool32 depthClampEnable; 711 false, // VkBool32 rasterizerDiscardEnable; 712 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode; 713 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode; 714 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace; 715 false, // VkBool32 depthBiasEnable; 716 0.0f, // float depthBiasConstantFactor; 717 0.0f, // float depthBiasClamp; 718 0.0f, // float depthBiasSlopeFactor; 719 1.0f // float lineWidth; 720 }; 721 722 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState = 723 { 724 false, // VkBool32 blendEnable; 725 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor; 726 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstColorBlendFactor; 727 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp; 728 VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor; 729 VK_BLEND_FACTOR_ZERO, // VkBlendFactor dstAlphaBlendFactor; 730 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp; 731 VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | // VkColorComponentFlags colorWriteMask; 732 VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT 733 }; 734 735 const VkPipelineColorBlendStateCreateInfo colorBlendStateParams = 736 { 737 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 738 DE_NULL, // const void* pNext; 739 0u, // VkPipelineColorBlendStateCreateFlags flags; 740 false, // VkBool32 logicOpEnable; 741 VK_LOGIC_OP_COPY, // VkLogicOp logicOp; 742 1u, // deUint32 attachmentCount; 743 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 744 { 0.0f, 0.0f, 0.0f, 0.0f } // float blendConstants[4]; 745 }; 746 747 const VkPipelineMultisampleStateCreateInfo multisampleStateParams = 748 { 749 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType; 750 DE_NULL, // const void* pNext; 751 0u, // VkPipelineMultisampleStateCreateFlags flags; 752 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits rasterizationSamples; 753 false, // VkBool32 sampleShadingEnable; 754 0.0f, // float minSampleShading; 755 DE_NULL, // const VkSampleMask* pSampleMask; 756 false, // VkBool32 alphaToCoverageEnable; 757 false // VkBool32 alphaToOneEnable; 758 }; 759 760 VkPipelineDepthStencilStateCreateInfo depthStencilStateParams = 761 { 762 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType; 763 DE_NULL, // const void* pNext; 764 0u, // VkPipelineDepthStencilStateCreateFlags flags; 765 false, // VkBool32 depthTestEnable; 766 false, // VkBool32 depthWriteEnable; 767 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp; 768 false, // VkBool32 depthBoundsTestEnable; 769 false, // VkBool32 stencilTestEnable; 770 { // VkStencilOpState front; 771 VK_STENCIL_OP_ZERO, // VkStencilOp failOp; 772 VK_STENCIL_OP_ZERO, // VkStencilOp passOp; 773 VK_STENCIL_OP_ZERO, // VkStencilOp depthFailOp; 774 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 775 0u, // deUint32 compareMask; 776 0u, // deUint32 writeMask; 777 0u // deUint32 reference; 778 }, 779 { // VkStencilOpState back; 780 VK_STENCIL_OP_ZERO, // VkStencilOp failOp; 781 VK_STENCIL_OP_ZERO, // VkStencilOp passOp; 782 VK_STENCIL_OP_ZERO, // VkStencilOp depthFailOp; 783 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 784 0u, // deUint32 compareMask; 785 0u, // deUint32 writeMask; 786 0u // deUint32 reference; 787 }, 788 0.0f, // float minDepthBounds; 789 1.0f // float maxDepthBounds; 790 }; 791 792 const VkGraphicsPipelineCreateInfo graphicsPipelineParams = 793 { 794 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType; 795 DE_NULL, // const void* pNext; 796 0u, // VkPipelineCreateFlags flags; 797 2u, // deUint32 stageCount; 798 shaderStages, // const VkPipelineShaderStageCreateInfo* pStages; 799 &vertexInputStateParams, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState; 800 &inputAssemblyStateParams, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState; 801 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState; 802 &viewportStateParams, // const VkPipelineViewportStateCreateInfo* pViewportState; 803 &rasterStateParams, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState; 804 &multisampleStateParams, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState; 805 &depthStencilStateParams, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState; 806 &colorBlendStateParams, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState; 807 (const VkPipelineDynamicStateCreateInfo*)DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState; 808 *m_pipelineLayout, // VkPipelineLayout layout; 809 *m_renderPass, // VkRenderPass renderPass; 810 0u, // deUint32 subpass; 811 0u, // VkPipeline basePipelineHandle; 812 0u // deInt32 basePipelineIndex; 813 }; 814 815 m_graphicsPipeline = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams); 816 } 817 818 // Create vertex buffer 819 { 820 const VkDeviceSize vertexBufferSize = (VkDeviceSize)(m_vertices.size() * sizeof(Vertex4Tex4)); 821 const VkBufferCreateInfo vertexBufferParams = 822 { 823 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; 824 DE_NULL, // const void* pNext; 825 0u, // VkBufferCreateFlags flags; 826 vertexBufferSize, // VkDeviceSize size; 827 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage; 828 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 829 1u, // deUint32 queueFamilyIndexCount; 830 &queueFamilyIndex // const deUint32* pQueueFamilyIndices; 831 }; 832 833 DE_ASSERT(vertexBufferSize > 0); 834 835 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams); 836 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible); 837 838 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset())); 839 840 // Load vertices into vertex buffer 841 deMemcpy(m_vertexBufferAlloc->getHostPtr(), &m_vertices[0], (size_t)vertexBufferSize); 842 flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size); 843 } 844 845 // Create command pool 846 { 847 const VkCommandPoolCreateInfo cmdPoolParams = 848 { 849 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; 850 DE_NULL, // const void* pNext; 851 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags; 852 queueFamilyIndex // deUint32 queueFamilyIndex; 853 }; 854 855 m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams); 856 } 857 858 // Create command buffer 859 { 860 const VkCommandBufferAllocateInfo cmdBufferAllocateInfo = 861 { 862 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType; 863 DE_NULL, // const void* pNext; 864 *m_cmdPool, // VkCommandPool commandPool; 865 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level; 866 1u, // deUint32 bufferCount; 867 }; 868 869 const VkCommandBufferBeginInfo cmdBufferBeginInfo = 870 { 871 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType; 872 DE_NULL, // const void* pNext; 873 0u, // VkCommandBufferUsageFlags flags; 874 (const VkCommandBufferInheritanceInfo*)DE_NULL, 875 }; 876 877 const VkClearValue attachmentClearValue = defaultClearValue(m_colorFormat); 878 879 const VkRenderPassBeginInfo renderPassBeginInfo = 880 { 881 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType; 882 DE_NULL, // const void* pNext; 883 *m_renderPass, // VkRenderPass renderPass; 884 *m_framebuffer, // VkFramebuffer framebuffer; 885 { 886 { 0, 0 }, 887 { (deUint32)m_renderSize.x(), (deUint32)m_renderSize.y() } 888 }, // VkRect2D renderArea; 889 1, // deUint32 clearValueCount; 890 &attachmentClearValue // const VkClearValue* pClearValues; 891 }; 892 893 const VkImageMemoryBarrier preAttachmentBarrier = 894 { 895 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType; 896 DE_NULL, // const void* pNext; 897 0u, // VkAccessFlags srcAccessMask; 898 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // VkAccessFlags dstAccessMask; 899 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout; 900 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout newLayout; 901 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex; 902 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex; 903 *m_colorImage, // VkImage image; 904 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange; 905 }; 906 907 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo); 908 909 VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo)); 910 911 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 912 0u, DE_NULL, 0u, DE_NULL, 1u, &preAttachmentBarrier); 913 914 vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); 915 916 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline); 917 918 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &m_descriptorSet.get(), 0, DE_NULL); 919 920 const VkDeviceSize vertexBufferOffset = 0; 921 vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset); 922 vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0); 923 924 vk.cmdEndRenderPass(*m_cmdBuffer); 925 VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer)); 926 } 927 928 // Create fence 929 { 930 const VkFenceCreateInfo fenceParams = 931 { 932 VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, // VkStructureType sType; 933 DE_NULL, // const void* pNext; 934 0u // VkFenceCreateFlags flags; 935 }; 936 937 m_fence = createFence(vk, vkDevice, &fenceParams); 938 } 939 } 940 941 ImageSamplingInstance::~ImageSamplingInstance (void) 942 { 943 } 944 945 tcu::TestStatus ImageSamplingInstance::iterate (void) 946 { 947 const DeviceInterface& vk = m_context.getDeviceInterface(); 948 const VkDevice vkDevice = m_context.getDevice(); 949 const VkQueue queue = m_context.getUniversalQueue(); 950 const VkSubmitInfo submitInfo = 951 { 952 VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType; 953 DE_NULL, // const void* pNext; 954 0u, // deUint32 waitSemaphoreCount; 955 DE_NULL, // const VkSemaphore* pWaitSemaphores; 956 DE_NULL, 957 1u, // deUint32 commandBufferCount; 958 &m_cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers; 959 0u, // deUint32 signalSemaphoreCount; 960 DE_NULL // const VkSemaphore* pSignalSemaphores; 961 }; 962 963 VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get())); 964 VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence)); 965 VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity */)); 966 967 return verifyImage(); 968 } 969 970 tcu::TestStatus ImageSamplingInstance::verifyImage (void) 971 { 972 const tcu::TextureFormat colorFormat = mapVkFormat(m_colorFormat); 973 const tcu::TextureFormat depthStencilFormat = tcu::TextureFormat(); // Undefined depth/stencil format. 974 const tcu::Sampler sampler = mapVkSampler(m_samplerParams); 975 const tcu::UVec4 componentMapping = mapVkComponentMapping(m_componentMapping); 976 float samplerLod; 977 bool compareOk; 978 MovePtr<Program> program; 979 MovePtr<ReferenceRenderer> refRenderer; 980 981 // Set up LOD of reference sampler 982 samplerLod = de::max(m_samplerParams.minLod, de::min(m_samplerParams.maxLod, m_samplerParams.mipLodBias + m_samplerLod)); 983 984 // Create reference program that uses image subresource range 985 program = createRefProgram(colorFormat, sampler, samplerLod, componentMapping, *m_texture, m_imageViewType, m_layerCount, m_subresourceRange); 986 const rr::Program referenceProgram = program->getReferenceProgram(); 987 988 // Render reference image 989 refRenderer = MovePtr<ReferenceRenderer>(new ReferenceRenderer(m_renderSize.x(), m_renderSize.y(), 1, colorFormat, depthStencilFormat, &referenceProgram)); 990 const rr::RenderState renderState(refRenderer->getViewportState()); 991 refRenderer->draw(renderState, rr::PRIMITIVETYPE_TRIANGLES, m_vertices); 992 993 // Compare result with reference image 994 { 995 const DeviceInterface& vk = m_context.getDeviceInterface(); 996 const VkDevice vkDevice = m_context.getDevice(); 997 const VkQueue queue = m_context.getUniversalQueue(); 998 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); 999 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice())); 1000 MovePtr<tcu::TextureLevel> result = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, memAlloc, *m_colorImage, m_colorFormat, m_renderSize); 1001 tcu::UVec4 threshold = tcu::UVec4(4, 4, 4, 4); 1002 1003 if ((m_imageFormat == vk::VK_FORMAT_EAC_R11G11_SNORM_BLOCK) || (m_imageFormat == vk::VK_FORMAT_EAC_R11_SNORM_BLOCK)) 1004 threshold = tcu::UVec4(8, 8, 8, 8); 1005 1006 compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(), 1007 "IntImageCompare", 1008 "Image comparison", 1009 refRenderer->getAccess(), 1010 result->getAccess(), 1011 threshold, 1012 tcu::IVec3(1, 1, 0), 1013 true, 1014 tcu::COMPARE_LOG_RESULT); 1015 } 1016 1017 if (compareOk) 1018 return tcu::TestStatus::pass("Result image matches reference"); 1019 else 1020 return tcu::TestStatus::fail("Image mismatch"); 1021 } 1022 1023 } // pipeline 1024 } // vkt 1025