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