1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//* 20 * \file vktSparseResourcesShaderIntrinsicsBase.cpp 21 * \brief Sparse Resources Shader Intrinsics Base Classes 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktSparseResourcesShaderIntrinsicsBase.hpp" 25 #include "vkCmdUtil.hpp" 26 #include "vkBarrierUtil.hpp" 27 28 using namespace vk; 29 30 namespace vkt 31 { 32 namespace sparse 33 { 34 35 std::string getOpTypeImageComponent (const tcu::TextureFormat& format) 36 { 37 switch (tcu::getTextureChannelClass(format.type)) 38 { 39 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 40 return "OpTypeInt 32 0"; 41 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 42 return "OpTypeInt 32 1"; 43 default: 44 DE_ASSERT(0); 45 return ""; 46 } 47 } 48 49 std::string getImageComponentTypeName (const tcu::TextureFormat& format) 50 { 51 switch (tcu::getTextureChannelClass(format.type)) 52 { 53 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 54 return "%type_uint"; 55 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 56 return "%type_int"; 57 default: 58 DE_ASSERT(0); 59 return ""; 60 } 61 } 62 63 std::string getImageComponentVec4TypeName (const tcu::TextureFormat& format) 64 { 65 switch (tcu::getTextureChannelClass(format.type)) 66 { 67 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 68 return "%type_uvec4"; 69 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 70 return "%type_ivec4"; 71 default: 72 DE_ASSERT(0); 73 return ""; 74 } 75 } 76 77 std::string getOpTypeImageSparse (const ImageType imageType, 78 const tcu::TextureFormat& format, 79 const std::string& componentType, 80 const bool requiresSampler) 81 { 82 std::ostringstream src; 83 84 src << "OpTypeImage " << componentType << " "; 85 86 switch (imageType) 87 { 88 case IMAGE_TYPE_1D : 89 src << "1D 0 0 0 "; 90 break; 91 case IMAGE_TYPE_1D_ARRAY : 92 src << "1D 0 1 0 "; 93 break; 94 case IMAGE_TYPE_2D : 95 src << "2D 0 0 0 "; 96 break; 97 case IMAGE_TYPE_2D_ARRAY : 98 src << "2D 0 1 0 "; 99 break; 100 case IMAGE_TYPE_3D : 101 src << "3D 0 0 0 "; 102 break; 103 case IMAGE_TYPE_CUBE : 104 src << "Cube 0 0 0 "; 105 break; 106 case IMAGE_TYPE_CUBE_ARRAY : 107 src << "Cube 0 1 0 "; 108 break; 109 default : 110 DE_ASSERT(0); 111 break; 112 }; 113 114 if (requiresSampler) 115 src << "1 "; 116 else 117 src << "2 "; 118 119 switch (format.order) 120 { 121 case tcu::TextureFormat::R: 122 src << "R"; 123 break; 124 case tcu::TextureFormat::RG: 125 src << "Rg"; 126 break; 127 case tcu::TextureFormat::RGB: 128 src << "Rgb"; 129 break; 130 case tcu::TextureFormat::RGBA: 131 src << "Rgba"; 132 break; 133 default: 134 DE_ASSERT(0); 135 break; 136 } 137 138 switch (format.type) 139 { 140 case tcu::TextureFormat::SIGNED_INT8: 141 src << "8i"; 142 break; 143 case tcu::TextureFormat::SIGNED_INT16: 144 src << "16i"; 145 break; 146 case tcu::TextureFormat::SIGNED_INT32: 147 src << "32i"; 148 break; 149 case tcu::TextureFormat::UNSIGNED_INT8: 150 src << "8ui"; 151 break; 152 case tcu::TextureFormat::UNSIGNED_INT16: 153 src << "16ui"; 154 break; 155 case tcu::TextureFormat::UNSIGNED_INT32: 156 src << "32ui"; 157 break; 158 default: 159 DE_ASSERT(0); 160 break; 161 }; 162 163 return src.str(); 164 } 165 166 std::string getOpTypeImageResidency (const ImageType imageType) 167 { 168 std::ostringstream src; 169 170 src << "OpTypeImage %type_uint "; 171 172 switch (imageType) 173 { 174 case IMAGE_TYPE_1D : 175 src << "1D 0 0 0 2 R32ui"; 176 break; 177 case IMAGE_TYPE_1D_ARRAY : 178 src << "1D 0 1 0 2 R32ui"; 179 break; 180 case IMAGE_TYPE_2D : 181 src << "2D 0 0 0 2 R32ui"; 182 break; 183 case IMAGE_TYPE_2D_ARRAY : 184 src << "2D 0 1 0 2 R32ui"; 185 break; 186 case IMAGE_TYPE_3D : 187 src << "3D 0 0 0 2 R32ui"; 188 break; 189 case IMAGE_TYPE_CUBE : 190 src << "Cube 0 0 0 2 R32ui"; 191 break; 192 case IMAGE_TYPE_CUBE_ARRAY : 193 src << "Cube 0 1 0 2 R32ui"; 194 break; 195 default : 196 DE_ASSERT(0); 197 break; 198 }; 199 200 return src.str(); 201 } 202 203 tcu::TestStatus SparseShaderIntrinsicsInstanceBase::iterate (void) 204 { 205 const InstanceInterface& instance = m_context.getInstanceInterface(); 206 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); 207 VkImageCreateInfo imageSparseInfo; 208 VkImageCreateInfo imageTexelsInfo; 209 VkImageCreateInfo imageResidencyInfo; 210 VkSparseImageMemoryRequirements aspectRequirements; 211 std::vector <deUint32> residencyReferenceData; 212 std::vector<DeviceMemorySp> deviceMemUniquePtrVec; 213 214 // Check if image size does not exceed device limits 215 if (!isImageSizeSupported(instance, physicalDevice, m_imageType, m_imageSize)) 216 TCU_THROW(NotSupportedError, "Image size not supported for device"); 217 218 // Check if device supports sparse operations for image type 219 if (!checkSparseSupportForImageType(instance, physicalDevice, m_imageType)) 220 TCU_THROW(NotSupportedError, "Sparse residency for image type is not supported"); 221 222 if (!getPhysicalDeviceFeatures(instance, physicalDevice).shaderResourceResidency) 223 TCU_THROW(NotSupportedError, "Sparse resource residency information not supported in shader code."); 224 225 imageSparseInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 226 imageSparseInfo.pNext = DE_NULL; 227 imageSparseInfo.flags = VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_IMAGE_CREATE_SPARSE_BINDING_BIT; 228 imageSparseInfo.imageType = mapImageType(m_imageType); 229 imageSparseInfo.format = mapTextureFormat(m_format); 230 imageSparseInfo.extent = makeExtent3D(getLayerSize(m_imageType, m_imageSize)); 231 imageSparseInfo.arrayLayers = getNumLayers(m_imageType, m_imageSize); 232 imageSparseInfo.samples = VK_SAMPLE_COUNT_1_BIT; 233 imageSparseInfo.tiling = VK_IMAGE_TILING_OPTIMAL; 234 imageSparseInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 235 imageSparseInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | imageSparseUsageFlags(); 236 imageSparseInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 237 imageSparseInfo.queueFamilyIndexCount = 0u; 238 imageSparseInfo.pQueueFamilyIndices = DE_NULL; 239 240 if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY) 241 { 242 imageSparseInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; 243 } 244 245 { 246 // Assign maximum allowed mipmap levels to image 247 VkImageFormatProperties imageFormatProperties; 248 instance.getPhysicalDeviceImageFormatProperties(physicalDevice, 249 imageSparseInfo.format, 250 imageSparseInfo.imageType, 251 imageSparseInfo.tiling, 252 imageSparseInfo.usage, 253 imageSparseInfo.flags, 254 &imageFormatProperties); 255 256 imageSparseInfo.mipLevels = getImageMaxMipLevels(imageFormatProperties, imageSparseInfo.extent); 257 } 258 259 // Check if device supports sparse operations for image format 260 if (!checkSparseSupportForImageFormat(instance, physicalDevice, imageSparseInfo)) 261 TCU_THROW(NotSupportedError, "The image format does not support sparse operations"); 262 263 { 264 // Create logical device supporting both sparse and compute/graphics queues 265 QueueRequirementsVec queueRequirements; 266 queueRequirements.push_back(QueueRequirements(VK_QUEUE_SPARSE_BINDING_BIT, 1u)); 267 queueRequirements.push_back(QueueRequirements(getQueueFlags(), 1u)); 268 269 createDeviceSupportingQueues(queueRequirements); 270 } 271 272 const DeviceInterface& deviceInterface = getDeviceInterface(); 273 274 // Create queues supporting sparse binding operations and compute/graphics operations 275 const Queue& sparseQueue = getQueue(VK_QUEUE_SPARSE_BINDING_BIT, 0); 276 const Queue& extractQueue = getQueue(getQueueFlags(), 0); 277 278 // Create sparse image 279 const Unique<VkImage> imageSparse(createImage(deviceInterface, getDevice(), &imageSparseInfo)); 280 281 // Create sparse image memory bind semaphore 282 const Unique<VkSemaphore> memoryBindSemaphore(createSemaphore(deviceInterface, getDevice())); 283 284 const deUint32 imageSparseSizeInBytes = getImageSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, imageSparseInfo.mipLevels, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY); 285 const deUint32 imageSizeInPixels = getImageSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, imageSparseInfo.mipLevels) / tcu::getPixelSize(m_format); 286 287 residencyReferenceData.assign(imageSizeInPixels, MEMORY_BLOCK_NOT_BOUND_VALUE); 288 289 { 290 // Get sparse image general memory requirements 291 const VkMemoryRequirements imageMemoryRequirements = getImageMemoryRequirements(deviceInterface, getDevice(), *imageSparse); 292 293 // Check if required image memory size does not exceed device limits 294 if (imageMemoryRequirements.size > getPhysicalDeviceProperties(instance, physicalDevice).limits.sparseAddressSpaceSize) 295 TCU_THROW(NotSupportedError, "Required memory size for sparse resource exceeds device limits"); 296 297 DE_ASSERT((imageMemoryRequirements.size % imageMemoryRequirements.alignment) == 0); 298 299 // Get sparse image sparse memory requirements 300 const std::vector<VkSparseImageMemoryRequirements> sparseMemoryRequirements = getImageSparseMemoryRequirements(deviceInterface, getDevice(), *imageSparse); 301 302 DE_ASSERT(sparseMemoryRequirements.size() != 0); 303 304 const deUint32 colorAspectIndex = getSparseAspectRequirementsIndex(sparseMemoryRequirements, VK_IMAGE_ASPECT_COLOR_BIT); 305 const deUint32 metadataAspectIndex = getSparseAspectRequirementsIndex(sparseMemoryRequirements, VK_IMAGE_ASPECT_METADATA_BIT); 306 307 if (colorAspectIndex == NO_MATCH_FOUND) 308 TCU_THROW(NotSupportedError, "Not supported image aspect - the test supports currently only VK_IMAGE_ASPECT_COLOR_BIT"); 309 310 aspectRequirements = sparseMemoryRequirements[colorAspectIndex]; 311 312 DE_ASSERT((aspectRequirements.imageMipTailSize % imageMemoryRequirements.alignment) == 0); 313 314 const VkImageAspectFlags aspectMask = aspectRequirements.formatProperties.aspectMask; 315 const VkExtent3D imageGranularity = aspectRequirements.formatProperties.imageGranularity; 316 const deUint32 memoryType = findMatchingMemoryType(instance, physicalDevice, imageMemoryRequirements, MemoryRequirement::Any); 317 318 if (memoryType == NO_MATCH_FOUND) 319 return tcu::TestStatus::fail("No matching memory type found"); 320 321 deUint32 pixelOffset = 0u; 322 323 std::vector<VkSparseImageMemoryBind> imageResidencyMemoryBinds; 324 std::vector<VkSparseMemoryBind> imageMipTailBinds; 325 326 // Bind memory for each mipmap level 327 for (deUint32 mipLevelNdx = 0; mipLevelNdx < aspectRequirements.imageMipTailFirstLod; ++mipLevelNdx) 328 { 329 const deUint32 mipLevelSizeInPixels = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, mipLevelNdx) / tcu::getPixelSize(m_format); 330 331 if (mipLevelNdx % MEMORY_BLOCK_TYPE_COUNT == MEMORY_BLOCK_NOT_BOUND) 332 { 333 pixelOffset += mipLevelSizeInPixels; 334 continue; 335 } 336 337 for (deUint32 pixelNdx = 0u; pixelNdx < mipLevelSizeInPixels; ++pixelNdx) 338 { 339 residencyReferenceData[pixelOffset + pixelNdx] = MEMORY_BLOCK_BOUND_VALUE; 340 } 341 342 pixelOffset += mipLevelSizeInPixels; 343 344 for (deUint32 layerNdx = 0; layerNdx < imageSparseInfo.arrayLayers; ++layerNdx) 345 { 346 const VkExtent3D mipExtent = mipLevelExtents(imageSparseInfo.extent, mipLevelNdx); 347 const tcu::UVec3 sparseBlocks = alignedDivide(mipExtent, imageGranularity); 348 const deUint32 numSparseBlocks = sparseBlocks.x() * sparseBlocks.y() * sparseBlocks.z(); 349 const VkImageSubresource subresource = { aspectMask, mipLevelNdx, layerNdx }; 350 351 const VkSparseImageMemoryBind imageMemoryBind = makeSparseImageMemoryBind(deviceInterface, getDevice(), 352 imageMemoryRequirements.alignment * numSparseBlocks, memoryType, subresource, makeOffset3D(0u, 0u, 0u), mipExtent); 353 354 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL)))); 355 356 imageResidencyMemoryBinds.push_back(imageMemoryBind); 357 } 358 } 359 360 if (aspectRequirements.imageMipTailFirstLod < imageSparseInfo.mipLevels) 361 { 362 if (aspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT) 363 { 364 const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(), 365 aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset); 366 367 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL)))); 368 369 imageMipTailBinds.push_back(imageMipTailMemoryBind); 370 } 371 else 372 { 373 for (deUint32 layerNdx = 0; layerNdx < imageSparseInfo.arrayLayers; ++layerNdx) 374 { 375 const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(), 376 aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset + layerNdx * aspectRequirements.imageMipTailStride); 377 378 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL)))); 379 380 imageMipTailBinds.push_back(imageMipTailMemoryBind); 381 } 382 } 383 384 for (deUint32 pixelNdx = pixelOffset; pixelNdx < residencyReferenceData.size(); ++pixelNdx) 385 { 386 residencyReferenceData[pixelNdx] = MEMORY_BLOCK_BOUND_VALUE; 387 } 388 } 389 390 // Metadata 391 if (metadataAspectIndex != NO_MATCH_FOUND) 392 { 393 const VkSparseImageMemoryRequirements metadataAspectRequirements = sparseMemoryRequirements[metadataAspectIndex]; 394 395 const deUint32 metadataBindCount = (metadataAspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT ? 1u : imageSparseInfo.arrayLayers); 396 for (deUint32 bindNdx = 0u; bindNdx < metadataBindCount; ++bindNdx) 397 { 398 const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(), 399 metadataAspectRequirements.imageMipTailSize, memoryType, 400 metadataAspectRequirements.imageMipTailOffset + bindNdx * metadataAspectRequirements.imageMipTailStride, 401 VK_SPARSE_MEMORY_BIND_METADATA_BIT); 402 403 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL)))); 404 405 imageMipTailBinds.push_back(imageMipTailMemoryBind); 406 } 407 } 408 409 VkBindSparseInfo bindSparseInfo = 410 { 411 VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, //VkStructureType sType; 412 DE_NULL, //const void* pNext; 413 0u, //deUint32 waitSemaphoreCount; 414 DE_NULL, //const VkSemaphore* pWaitSemaphores; 415 0u, //deUint32 bufferBindCount; 416 DE_NULL, //const VkSparseBufferMemoryBindInfo* pBufferBinds; 417 0u, //deUint32 imageOpaqueBindCount; 418 DE_NULL, //const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds; 419 0u, //deUint32 imageBindCount; 420 DE_NULL, //const VkSparseImageMemoryBindInfo* pImageBinds; 421 1u, //deUint32 signalSemaphoreCount; 422 &memoryBindSemaphore.get() //const VkSemaphore* pSignalSemaphores; 423 }; 424 425 VkSparseImageMemoryBindInfo imageResidencyBindInfo; 426 VkSparseImageOpaqueMemoryBindInfo imageMipTailBindInfo; 427 428 if (imageResidencyMemoryBinds.size() > 0) 429 { 430 imageResidencyBindInfo.image = *imageSparse; 431 imageResidencyBindInfo.bindCount = static_cast<deUint32>(imageResidencyMemoryBinds.size()); 432 imageResidencyBindInfo.pBinds = &imageResidencyMemoryBinds[0]; 433 434 bindSparseInfo.imageBindCount = 1u; 435 bindSparseInfo.pImageBinds = &imageResidencyBindInfo; 436 } 437 438 if (imageMipTailBinds.size() > 0) 439 { 440 imageMipTailBindInfo.image = *imageSparse; 441 imageMipTailBindInfo.bindCount = static_cast<deUint32>(imageMipTailBinds.size()); 442 imageMipTailBindInfo.pBinds = &imageMipTailBinds[0]; 443 444 bindSparseInfo.imageOpaqueBindCount = 1u; 445 bindSparseInfo.pImageOpaqueBinds = &imageMipTailBindInfo; 446 } 447 448 // Submit sparse bind commands for execution 449 VK_CHECK(deviceInterface.queueBindSparse(sparseQueue.queueHandle, 1u, &bindSparseInfo, DE_NULL)); 450 } 451 452 // Create image to store texels copied from sparse image 453 imageTexelsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; 454 imageTexelsInfo.pNext = DE_NULL; 455 imageTexelsInfo.flags = 0u; 456 imageTexelsInfo.imageType = imageSparseInfo.imageType; 457 imageTexelsInfo.format = imageSparseInfo.format; 458 imageTexelsInfo.extent = imageSparseInfo.extent; 459 imageTexelsInfo.arrayLayers = imageSparseInfo.arrayLayers; 460 imageTexelsInfo.mipLevels = imageSparseInfo.mipLevels; 461 imageTexelsInfo.samples = imageSparseInfo.samples; 462 imageTexelsInfo.tiling = VK_IMAGE_TILING_OPTIMAL; 463 imageTexelsInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; 464 imageTexelsInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | imageOutputUsageFlags(); 465 imageTexelsInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; 466 imageTexelsInfo.queueFamilyIndexCount = 0u; 467 imageTexelsInfo.pQueueFamilyIndices = DE_NULL; 468 469 if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY) 470 { 471 imageTexelsInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; 472 } 473 474 const Unique<VkImage> imageTexels (createImage(deviceInterface, getDevice(), &imageTexelsInfo)); 475 const de::UniquePtr<Allocation> imageTexelsAlloc (bindImage(deviceInterface, getDevice(), getAllocator(), *imageTexels, MemoryRequirement::Any)); 476 477 // Create image to store residency info copied from sparse image 478 imageResidencyInfo = imageTexelsInfo; 479 imageResidencyInfo.format = mapTextureFormat(m_residencyFormat); 480 481 const Unique<VkImage> imageResidency (createImage(deviceInterface, getDevice(), &imageResidencyInfo)); 482 const de::UniquePtr<Allocation> imageResidencyAlloc (bindImage(deviceInterface, getDevice(), getAllocator(), *imageResidency, MemoryRequirement::Any)); 483 484 // Create command buffer for compute and transfer oparations 485 const Unique<VkCommandPool> commandPool(makeCommandPool(deviceInterface, getDevice(), extractQueue.queueFamilyIndex)); 486 const Unique<VkCommandBuffer> commandBuffer(allocateCommandBuffer(deviceInterface, getDevice(), *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); 487 488 std::vector <VkBufferImageCopy> bufferImageSparseCopy(imageSparseInfo.mipLevels); 489 490 { 491 deUint32 bufferOffset = 0u; 492 for (deUint32 mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx) 493 { 494 bufferImageSparseCopy[mipLevelNdx] = makeBufferImageCopy(mipLevelExtents(imageSparseInfo.extent, mipLevelNdx), imageSparseInfo.arrayLayers, mipLevelNdx, static_cast<VkDeviceSize>(bufferOffset)); 495 bufferOffset += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, mipLevelNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY); 496 } 497 } 498 499 // Start recording commands 500 beginCommandBuffer(deviceInterface, *commandBuffer); 501 502 // Create input buffer 503 const VkBufferCreateInfo inputBufferCreateInfo = makeBufferCreateInfo(imageSparseSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); 504 const Unique<VkBuffer> inputBuffer (createBuffer(deviceInterface, getDevice(), &inputBufferCreateInfo)); 505 const de::UniquePtr<Allocation> inputBufferAlloc (bindBuffer(deviceInterface, getDevice(), getAllocator(), *inputBuffer, MemoryRequirement::HostVisible)); 506 507 // Fill input buffer with reference data 508 std::vector<deUint8> referenceData(imageSparseSizeInBytes); 509 510 for (deUint32 mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx) 511 { 512 const deUint32 mipLevelSizeinBytes = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, mipLevelNdx); 513 const deUint32 bufferOffset = static_cast<deUint32>(bufferImageSparseCopy[mipLevelNdx].bufferOffset); 514 515 for (deUint32 byteNdx = 0u; byteNdx < mipLevelSizeinBytes; ++byteNdx) 516 { 517 referenceData[bufferOffset + byteNdx] = (deUint8)(mipLevelNdx + byteNdx); 518 } 519 } 520 521 deMemcpy(inputBufferAlloc->getHostPtr(), &referenceData[0], imageSparseSizeInBytes); 522 flushAlloc(deviceInterface, getDevice(), *inputBufferAlloc); 523 524 { 525 // Prepare input buffer for data transfer operation 526 const VkBufferMemoryBarrier inputBufferBarrier = makeBufferMemoryBarrier 527 ( 528 VK_ACCESS_HOST_WRITE_BIT, 529 VK_ACCESS_TRANSFER_READ_BIT, 530 *inputBuffer, 531 0u, 532 imageSparseSizeInBytes 533 ); 534 535 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 1u, &inputBufferBarrier, 0u, DE_NULL); 536 } 537 538 const VkImageSubresourceRange fullImageSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers); 539 540 { 541 // Prepare sparse image for data transfer operation 542 const VkImageMemoryBarrier imageSparseTransferDstBarrier = makeImageMemoryBarrier 543 ( 544 0u, 545 VK_ACCESS_TRANSFER_WRITE_BIT, 546 VK_IMAGE_LAYOUT_UNDEFINED, 547 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 548 *imageSparse, 549 fullImageSubresourceRange, 550 sparseQueue.queueFamilyIndex != extractQueue.queueFamilyIndex ? sparseQueue.queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED, 551 sparseQueue.queueFamilyIndex != extractQueue.queueFamilyIndex ? extractQueue.queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED 552 ); 553 554 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageSparseTransferDstBarrier); 555 } 556 557 // Copy reference data from input buffer to sparse image 558 deviceInterface.cmdCopyBufferToImage(*commandBuffer, *inputBuffer, *imageSparse, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, static_cast<deUint32>(bufferImageSparseCopy.size()), &bufferImageSparseCopy[0]); 559 560 recordCommands(*commandBuffer, imageSparseInfo, *imageSparse, *imageTexels, *imageResidency); 561 562 const VkBufferCreateInfo bufferTexelsCreateInfo = makeBufferCreateInfo(imageSparseSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT); 563 const Unique<VkBuffer> bufferTexels (createBuffer(deviceInterface, getDevice(), &bufferTexelsCreateInfo)); 564 const de::UniquePtr<Allocation> bufferTexelsAlloc (bindBuffer(deviceInterface, getDevice(), getAllocator(), *bufferTexels, MemoryRequirement::HostVisible)); 565 566 // Copy data from texels image to buffer 567 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, *imageTexels, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *bufferTexels, static_cast<deUint32>(bufferImageSparseCopy.size()), &bufferImageSparseCopy[0]); 568 569 const deUint32 imageResidencySizeInBytes = getImageSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_residencyFormat, imageSparseInfo.mipLevels, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY); 570 571 const VkBufferCreateInfo bufferResidencyCreateInfo = makeBufferCreateInfo(imageResidencySizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT); 572 const Unique<VkBuffer> bufferResidency (createBuffer(deviceInterface, getDevice(), &bufferResidencyCreateInfo)); 573 const de::UniquePtr<Allocation> bufferResidencyAlloc (bindBuffer(deviceInterface, getDevice(), getAllocator(), *bufferResidency, MemoryRequirement::HostVisible)); 574 575 // Copy data from residency image to buffer 576 std::vector <VkBufferImageCopy> bufferImageResidencyCopy(imageSparseInfo.mipLevels); 577 578 { 579 deUint32 bufferOffset = 0u; 580 for (deUint32 mipLevelNdx = 0u; mipLevelNdx < imageSparseInfo.mipLevels; ++mipLevelNdx) 581 { 582 bufferImageResidencyCopy[mipLevelNdx] = makeBufferImageCopy(mipLevelExtents(imageSparseInfo.extent, mipLevelNdx), imageSparseInfo.arrayLayers, mipLevelNdx, static_cast<VkDeviceSize>(bufferOffset)); 583 bufferOffset += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_residencyFormat, mipLevelNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY); 584 } 585 } 586 587 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, *imageResidency, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *bufferResidency, static_cast<deUint32>(bufferImageResidencyCopy.size()), &bufferImageResidencyCopy[0]); 588 589 { 590 VkBufferMemoryBarrier bufferOutputHostReadBarriers[2]; 591 592 bufferOutputHostReadBarriers[0] = makeBufferMemoryBarrier 593 ( 594 VK_ACCESS_TRANSFER_WRITE_BIT, 595 VK_ACCESS_HOST_READ_BIT, 596 *bufferTexels, 597 0u, 598 imageSparseSizeInBytes 599 ); 600 601 bufferOutputHostReadBarriers[1] = makeBufferMemoryBarrier 602 ( 603 VK_ACCESS_TRANSFER_WRITE_BIT, 604 VK_ACCESS_HOST_READ_BIT, 605 *bufferResidency, 606 0u, 607 imageResidencySizeInBytes 608 ); 609 610 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 2u, bufferOutputHostReadBarriers, 0u, DE_NULL); 611 } 612 613 // End recording commands 614 endCommandBuffer(deviceInterface, *commandBuffer); 615 616 const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TRANSFER_BIT }; 617 618 // Submit commands for execution and wait for completion 619 submitCommandsAndWait(deviceInterface, getDevice(), extractQueue.queueHandle, *commandBuffer, 1u, &memoryBindSemaphore.get(), stageBits); 620 621 // Wait for sparse queue to become idle 622 deviceInterface.queueWaitIdle(sparseQueue.queueHandle); 623 624 // Retrieve data from residency buffer to host memory 625 invalidateAlloc(deviceInterface, getDevice(), *bufferResidencyAlloc); 626 627 const deUint32* bufferResidencyData = static_cast<const deUint32*>(bufferResidencyAlloc->getHostPtr()); 628 629 deUint32 pixelOffsetNotAligned = 0u; 630 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx) 631 { 632 const deUint32 mipLevelSizeInBytes = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_residencyFormat, mipmapNdx); 633 const deUint32 pixelOffsetAligned = static_cast<deUint32>(bufferImageResidencyCopy[mipmapNdx].bufferOffset) / tcu::getPixelSize(m_residencyFormat); 634 635 if (deMemCmp(&bufferResidencyData[pixelOffsetAligned], &residencyReferenceData[pixelOffsetNotAligned], mipLevelSizeInBytes) != 0) 636 return tcu::TestStatus::fail("Failed"); 637 638 pixelOffsetNotAligned += mipLevelSizeInBytes / tcu::getPixelSize(m_residencyFormat); 639 } 640 641 // Retrieve data from texels buffer to host memory 642 invalidateAlloc(deviceInterface, getDevice(), *bufferTexelsAlloc); 643 644 const deUint8* bufferTexelsData = static_cast<const deUint8*>(bufferTexelsAlloc->getHostPtr()); 645 646 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx) 647 { 648 const deUint32 mipLevelSizeInBytes = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_format, mipmapNdx); 649 const deUint32 bufferOffset = static_cast<deUint32>(bufferImageSparseCopy[mipmapNdx].bufferOffset); 650 651 if (mipmapNdx < aspectRequirements.imageMipTailFirstLod) 652 { 653 if (mipmapNdx % MEMORY_BLOCK_TYPE_COUNT == MEMORY_BLOCK_BOUND) 654 { 655 if (deMemCmp(&bufferTexelsData[bufferOffset], &referenceData[bufferOffset], mipLevelSizeInBytes) != 0) 656 return tcu::TestStatus::fail("Failed"); 657 } 658 else if (getPhysicalDeviceProperties(instance, physicalDevice).sparseProperties.residencyNonResidentStrict) 659 { 660 std::vector<deUint8> zeroData; 661 zeroData.assign(mipLevelSizeInBytes, 0u); 662 663 if (deMemCmp(&bufferTexelsData[bufferOffset], &zeroData[0], mipLevelSizeInBytes) != 0) 664 return tcu::TestStatus::fail("Failed"); 665 } 666 } 667 else 668 { 669 if (deMemCmp(&bufferTexelsData[bufferOffset], &referenceData[bufferOffset], mipLevelSizeInBytes) != 0) 670 return tcu::TestStatus::fail("Failed"); 671 } 672 } 673 674 return tcu::TestStatus::pass("Passed"); 675 } 676 677 } // sparse 678 } // vkt 679