1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * \file vktSparseResourcesShaderIntrinsicsBase.cpp
21 * \brief Sparse Resources Shader Intrinsics Base Classes
22 *//*--------------------------------------------------------------------*/
24 #include "vktSparseResourcesShaderIntrinsicsBase.hpp"
25 #include "vkCmdUtil.hpp"
26 #include "vkBarrierUtil.hpp"
35 std::string getOpTypeImageComponent (const tcu::TextureFormat& format)
37 switch (tcu::getTextureChannelClass(format.type))
39 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
40 return "OpTypeInt 32 0";
41 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
42 return "OpTypeInt 32 1";
43 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
44 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
45 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
46 return "OpTypeFloat 32";
48 DE_FATAL("Unexpected channel type");
53 std::string getOpTypeImageComponent (const vk::PlanarFormatDescription& description)
55 switch (description.channels[0].type)
57 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
58 return "OpTypeInt 32 0";
59 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
60 return "OpTypeInt 32 1";
61 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
62 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
63 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
64 return "OpTypeFloat 32";
66 DE_FATAL("Unexpected channel type");
71 std::string getImageComponentTypeName (const tcu::TextureFormat& format)
73 switch (tcu::getTextureChannelClass(format.type))
75 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
77 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
79 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
80 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
81 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
84 DE_FATAL("Unexpected channel type");
89 std::string getImageComponentTypeName (const vk::PlanarFormatDescription& description)
91 switch (description.channels[0].type)
93 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
94 return (formatIsR64(description.planes[0].planeCompatibleFormat) ? "%type_uint64" : "%type_uint");
95 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
96 return (formatIsR64(description.planes[0].planeCompatibleFormat) ? "%type_int64" : "%type_int");
97 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
98 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
99 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
100 return "%type_float";
102 DE_FATAL("Unexpected channel type");
107 std::string getImageComponentVec4TypeName (const tcu::TextureFormat& format)
109 switch (tcu::getTextureChannelClass(format.type))
111 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
112 return "%type_uvec4";
113 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
114 return "%type_ivec4";
115 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
116 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
117 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
120 DE_FATAL("Unexpected channel type");
125 std::string getImageComponentVec4TypeName (const vk::PlanarFormatDescription& description)
128 switch (description.channels[0].type)
130 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
131 return (formatIsR64(description.planes[0].planeCompatibleFormat) ? "%type_u64vec4" : "%type_uvec4");
132 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
133 return (formatIsR64(description.planes[0].planeCompatibleFormat) ? "%type_i64vec4" : "%type_ivec4");
134 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
135 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
136 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
139 DE_FATAL("Unexpected channel type");
144 std::string getOpTypeImageSparse (const ImageType imageType,
145 const tcu::TextureFormat& format,
146 const std::string& componentType,
147 const bool requiresSampler)
149 std::ostringstream src;
151 src << "OpTypeImage " << componentType << " ";
158 case IMAGE_TYPE_1D_ARRAY :
164 case IMAGE_TYPE_2D_ARRAY :
170 case IMAGE_TYPE_CUBE :
171 src << "Cube 0 0 0 ";
173 case IMAGE_TYPE_CUBE_ARRAY :
174 src << "Cube 0 1 0 ";
177 DE_FATAL("Unexpected image type");
186 switch (format.order)
188 case tcu::TextureFormat::R:
191 case tcu::TextureFormat::RG:
194 case tcu::TextureFormat::RGB:
197 case tcu::TextureFormat::RGBA:
201 DE_FATAL("Unexpected channel order");
207 case tcu::TextureFormat::SIGNED_INT8:
210 case tcu::TextureFormat::SIGNED_INT16:
213 case tcu::TextureFormat::SIGNED_INT32:
216 case tcu::TextureFormat::UNSIGNED_INT8:
219 case tcu::TextureFormat::UNSIGNED_INT16:
222 case tcu::TextureFormat::UNSIGNED_INT32:
225 case tcu::TextureFormat::SNORM_INT8:
228 case tcu::TextureFormat::SNORM_INT16:
231 case tcu::TextureFormat::SNORM_INT32:
234 case tcu::TextureFormat::UNORM_INT8:
237 case tcu::TextureFormat::UNORM_INT16:
240 case tcu::TextureFormat::UNORM_INT32:
244 DE_FATAL("Unexpected channel type");
251 std::string getOpTypeImageSparse (const ImageType imageType,
252 const VkFormat format,
253 const std::string& componentType,
254 const bool requiresSampler)
256 std::ostringstream src;
258 src << "OpTypeImage " << componentType << " ";
265 case IMAGE_TYPE_1D_ARRAY :
271 case IMAGE_TYPE_2D_ARRAY :
277 case IMAGE_TYPE_CUBE :
278 src << "Cube 0 0 0 ";
280 case IMAGE_TYPE_CUBE_ARRAY :
281 src << "Cube 0 1 0 ";
284 DE_FATAL("Unexpected image type");
295 case VK_FORMAT_R8_SINT: src << "R8i"; break;
296 case VK_FORMAT_R16_SINT: src << "R16i"; break;
297 case VK_FORMAT_R32_SINT: src << "R32i"; break;
298 case VK_FORMAT_R64_SINT: src << "R64i"; break;
299 case VK_FORMAT_R8_UINT: src << "R8ui"; break;
300 case VK_FORMAT_R16_UINT: src << "R16ui"; break;
301 case VK_FORMAT_R32_UINT: src << "R32ui"; break;
302 case VK_FORMAT_R64_UINT: src << "R64ui"; break;
303 case VK_FORMAT_R8_SNORM: src << "R8Snorm"; break;
304 case VK_FORMAT_R16_SNORM: src << "R16Snorm"; break;
305 case VK_FORMAT_R8_UNORM: src << "R8"; break;
306 case VK_FORMAT_R16_UNORM: src << "R16"; break;
308 case VK_FORMAT_R8G8_SINT: src << "Rg8i"; break;
309 case VK_FORMAT_R16G16_SINT: src << "Rg16i"; break;
310 case VK_FORMAT_R32G32_SINT: src << "Rg32i"; break;
311 case VK_FORMAT_R8G8_UINT: src << "Rg8ui"; break;
312 case VK_FORMAT_R16G16_UINT: src << "Rg16ui"; break;
313 case VK_FORMAT_R32G32_UINT: src << "Rg32ui"; break;
314 case VK_FORMAT_R8G8_SNORM: src << "Rg8Snorm"; break;
315 case VK_FORMAT_R16G16_SNORM: src << "Rg16Snorm"; break;
316 case VK_FORMAT_R8G8_UNORM: src << "Rg8"; break;
317 case VK_FORMAT_R16G16_UNORM: src << "Rg16"; break;
319 case VK_FORMAT_R8G8B8A8_SINT: src << "Rgba8i"; break;
320 case VK_FORMAT_R16G16B16A16_SINT: src << "Rgba16i"; break;
321 case VK_FORMAT_R32G32B32A32_SINT: src << "Rgba32i"; break;
322 case VK_FORMAT_R8G8B8A8_UINT: src << "Rgba8ui"; break;
323 case VK_FORMAT_R16G16B16A16_UINT: src << "Rgba16ui"; break;
324 case VK_FORMAT_R32G32B32A32_UINT: src << "Rgba32ui"; break;
325 case VK_FORMAT_R8G8B8A8_SNORM: src << "Rgba8Snorm"; break;
326 case VK_FORMAT_R16G16B16A16_SNORM: src << "Rgba16Snorm"; break;
327 case VK_FORMAT_R8G8B8A8_UNORM: src << "Rgba8"; break;
328 case VK_FORMAT_R16G16B16A16_UNORM: src << "Rgba16"; break;
330 case VK_FORMAT_G8B8G8R8_422_UNORM: src << "Rgba8"; break;
331 case VK_FORMAT_B8G8R8G8_422_UNORM: src << "Rgba8"; break;
332 case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: src << "Rgba8"; break;
333 case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: src << "Rgba8"; break;
334 case VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM: src << "Rgba8"; break;
335 case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: src << "Rgba8"; break;
336 case VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM: src << "Rgba8"; break;
337 case VK_FORMAT_R10X6_UNORM_PACK16: src << "R16"; break;
338 case VK_FORMAT_R10X6G10X6_UNORM_2PACK16: src << "Rg16"; break;
339 case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: src << "Rgba16"; break;
340 case VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16: src << "Rgba16"; break;
341 case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: src << "Rgba16"; break;
342 case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16: src << "Rgba16"; break;
343 case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16: src << "Rgba16"; break;
344 case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16: src << "Rgba16"; break;
345 case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16: src << "Rgba16"; break;
346 case VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16: src << "Rgba16"; break;
347 case VK_FORMAT_R12X4_UNORM_PACK16: src << "R16"; break;
348 case VK_FORMAT_R12X4G12X4_UNORM_2PACK16: src << "Rg16"; break;
349 case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16: src << "Rgba16"; break;
350 case VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16: src << "Rgba16"; break;
351 case VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16: src << "Rgba16"; break;
352 case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16: src << "Rgba16"; break;
353 case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16: src << "Rgba16"; break;
354 case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16: src << "Rgba16"; break;
355 case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16: src << "Rgba16"; break;
356 case VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16: src << "Rgba16"; break;
357 case VK_FORMAT_G16B16G16R16_422_UNORM: src << "Rgba16"; break;
358 case VK_FORMAT_B16G16R16G16_422_UNORM: src << "Rgba16"; break;
359 case VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM: src << "Rgba16"; break;
360 case VK_FORMAT_G16_B16R16_2PLANE_420_UNORM: src << "Rgba16"; break;
361 case VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM: src << "Rgba16"; break;
362 case VK_FORMAT_G16_B16R16_2PLANE_422_UNORM: src << "Rgba16"; break;
363 case VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM: src << "Rgba16"; break;
364 case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT: src << "Rgba8"; break;
365 case VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT:src << "Rgba16"; break;
366 case VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT:src << "Rgba16"; break;
367 case VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT: src << "Rgba16"; break;
370 DE_FATAL("Unexpected texture format");
377 std::string getOpTypeImageResidency (const ImageType imageType)
379 std::ostringstream src;
381 src << "OpTypeImage %type_uint ";
386 src << "1D 0 0 0 2 R32ui";
388 case IMAGE_TYPE_1D_ARRAY :
389 src << "1D 0 1 0 2 R32ui";
392 src << "2D 0 0 0 2 R32ui";
394 case IMAGE_TYPE_2D_ARRAY :
395 src << "2D 0 1 0 2 R32ui";
398 src << "3D 0 0 0 2 R32ui";
400 case IMAGE_TYPE_CUBE :
401 src << "Cube 0 0 0 2 R32ui";
403 case IMAGE_TYPE_CUBE_ARRAY :
404 src << "Cube 0 1 0 2 R32ui";
407 DE_FATAL("Unexpected image type");
414 tcu::TestStatus SparseShaderIntrinsicsInstanceBase::iterate (void)
416 const InstanceInterface& instance = m_context.getInstanceInterface();
417 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
418 VkImageCreateInfo imageSparseInfo;
419 VkImageCreateInfo imageTexelsInfo;
420 VkImageCreateInfo imageResidencyInfo;
421 std::vector <deUint32> residencyReferenceData;
422 std::vector<DeviceMemorySp> deviceMemUniquePtrVec;
423 const PlanarFormatDescription formatDescription = getPlanarFormatDescription(m_format);
425 imageSparseInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
426 imageSparseInfo.pNext = DE_NULL;
427 imageSparseInfo.flags = VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
428 imageSparseInfo.imageType = mapImageType(m_imageType);
429 imageSparseInfo.format = m_format;
430 imageSparseInfo.extent = makeExtent3D(getLayerSize(m_imageType, m_imageSize));
431 imageSparseInfo.arrayLayers = getNumLayers(m_imageType, m_imageSize);
432 imageSparseInfo.samples = VK_SAMPLE_COUNT_1_BIT;
433 imageSparseInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
434 imageSparseInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
435 imageSparseInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | imageSparseUsageFlags();
436 imageSparseInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
437 imageSparseInfo.queueFamilyIndexCount = 0u;
438 imageSparseInfo.pQueueFamilyIndices = DE_NULL;
440 if (formatIsR64(m_format))
442 m_context.requireDeviceFunctionality("VK_EXT_shader_image_atomic_int64");
444 if (m_context.getShaderImageAtomicInt64FeaturesEXT().shaderImageInt64Atomics == VK_FALSE)
446 TCU_THROW(NotSupportedError, "shaderImageInt64Atomics is not supported");
449 if (m_context.getShaderImageAtomicInt64FeaturesEXT().sparseImageInt64Atomics == VK_FALSE)
451 TCU_THROW(NotSupportedError, "sparseImageInt64Atomics is not supported for device");
455 if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
457 imageSparseInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
460 // Check if device supports sparse operations for image format
461 if (!checkSparseSupportForImageFormat(instance, physicalDevice, imageSparseInfo))
462 TCU_THROW(NotSupportedError, "The image format does not support sparse operations");
465 // Assign maximum allowed mipmap levels to image
466 VkImageFormatProperties imageFormatProperties;
467 if (instance.getPhysicalDeviceImageFormatProperties(physicalDevice,
468 imageSparseInfo.format,
469 imageSparseInfo.imageType,
470 imageSparseInfo.tiling,
471 imageSparseInfo.usage,
472 imageSparseInfo.flags,
473 &imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
475 TCU_THROW(NotSupportedError, "Image format does not support sparse operations");
478 imageSparseInfo.mipLevels = getMipmapCount(m_format, formatDescription, imageFormatProperties, imageSparseInfo.extent);
482 // Create logical device supporting both sparse and compute/graphics queues
483 QueueRequirementsVec queueRequirements;
484 queueRequirements.push_back(QueueRequirements(VK_QUEUE_SPARSE_BINDING_BIT, 1u));
485 queueRequirements.push_back(QueueRequirements(getQueueFlags(), 1u));
487 createDeviceSupportingQueues(queueRequirements);
490 // Create queues supporting sparse binding operations and compute/graphics operations
491 const DeviceInterface& deviceInterface = getDeviceInterface();
492 const Queue& sparseQueue = getQueue(VK_QUEUE_SPARSE_BINDING_BIT, 0);
493 const Queue& extractQueue = getQueue(getQueueFlags(), 0);
495 // Create sparse image
496 const Unique<VkImage> imageSparse(createImage(deviceInterface, getDevice(), &imageSparseInfo));
498 // Create sparse image memory bind semaphore
499 const Unique<VkSemaphore> memoryBindSemaphore(createSemaphore(deviceInterface, getDevice()));
501 std::vector<VkSparseImageMemoryRequirements> sparseMemoryRequirements;
503 deUint32 imageSparseSizeInBytes = 0;
504 deUint32 imageSizeInPixels = 0;
506 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
508 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
510 imageSparseSizeInBytes += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
511 imageSizeInPixels += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx) / formatDescription.planes[planeNdx].elementSizeBytes;
515 residencyReferenceData.assign(imageSizeInPixels, MEMORY_BLOCK_NOT_BOUND_VALUE);
518 // Get sparse image general memory requirements
519 const VkMemoryRequirements imageMemoryRequirements = getImageMemoryRequirements(deviceInterface, getDevice(), *imageSparse);
521 // Check if required image memory size does not exceed device limits
522 if (imageMemoryRequirements.size > getPhysicalDeviceProperties(instance, physicalDevice).limits.sparseAddressSpaceSize)
523 TCU_THROW(NotSupportedError, "Required memory size for sparse resource exceeds device limits");
525 DE_ASSERT((imageMemoryRequirements.size % imageMemoryRequirements.alignment) == 0);
527 const deUint32 memoryType = findMatchingMemoryType(instance, physicalDevice, imageMemoryRequirements, MemoryRequirement::Any);
529 if (memoryType == NO_MATCH_FOUND)
530 return tcu::TestStatus::fail("No matching memory type found");
532 // Get sparse image sparse memory requirements
533 sparseMemoryRequirements = getImageSparseMemoryRequirements(deviceInterface, getDevice(), *imageSparse);
535 DE_ASSERT(sparseMemoryRequirements.size() != 0);
537 const deUint32 metadataAspectIndex = getSparseAspectRequirementsIndex(sparseMemoryRequirements, VK_IMAGE_ASPECT_METADATA_BIT);
538 deUint32 pixelOffset = 0u;
539 std::vector<VkSparseImageMemoryBind> imageResidencyMemoryBinds;
540 std::vector<VkSparseMemoryBind> imageMipTailBinds;
542 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
544 const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
545 const deUint32 aspectIndex = getSparseAspectRequirementsIndex(sparseMemoryRequirements, aspect);
547 if (aspectIndex == NO_MATCH_FOUND)
548 TCU_THROW(NotSupportedError, "Not supported image aspect");
550 VkSparseImageMemoryRequirements aspectRequirements = sparseMemoryRequirements[aspectIndex];
552 DE_ASSERT((aspectRequirements.imageMipTailSize % imageMemoryRequirements.alignment) == 0);
554 VkExtent3D imageGranularity = aspectRequirements.formatProperties.imageGranularity;
556 // Bind memory for each mipmap level
557 for (deUint32 mipmapNdx = 0; mipmapNdx < aspectRequirements.imageMipTailFirstLod; ++mipmapNdx)
559 const deUint32 mipLevelSizeInPixels = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx) / formatDescription.planes[planeNdx].elementSizeBytes;
561 if (mipmapNdx % MEMORY_BLOCK_TYPE_COUNT == MEMORY_BLOCK_NOT_BOUND)
563 pixelOffset += mipLevelSizeInPixels;
567 for (deUint32 pixelNdx = 0u; pixelNdx < mipLevelSizeInPixels; ++pixelNdx)
569 residencyReferenceData[pixelOffset + pixelNdx] = MEMORY_BLOCK_BOUND_VALUE;
572 pixelOffset += mipLevelSizeInPixels;
574 for (deUint32 layerNdx = 0; layerNdx < imageSparseInfo.arrayLayers; ++layerNdx)
576 const VkExtent3D mipExtent = getPlaneExtent(formatDescription, imageSparseInfo.extent, planeNdx, mipmapNdx);
577 const tcu::UVec3 sparseBlocks = alignedDivide(mipExtent, imageGranularity);
578 const deUint32 numSparseBlocks = sparseBlocks.x() * sparseBlocks.y() * sparseBlocks.z();
579 const VkImageSubresource subresource = { aspect, mipmapNdx, layerNdx };
581 const VkSparseImageMemoryBind imageMemoryBind = makeSparseImageMemoryBind(deviceInterface, getDevice(),
582 imageMemoryRequirements.alignment * numSparseBlocks, memoryType, subresource, makeOffset3D(0u, 0u, 0u), mipExtent);
584 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
586 imageResidencyMemoryBinds.push_back(imageMemoryBind);
590 if (aspectRequirements.imageMipTailFirstLod < imageSparseInfo.mipLevels)
592 if (aspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT)
594 const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
595 aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset);
597 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
599 imageMipTailBinds.push_back(imageMipTailMemoryBind);
603 for (deUint32 layerNdx = 0; layerNdx < imageSparseInfo.arrayLayers; ++layerNdx)
605 const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
606 aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset + layerNdx * aspectRequirements.imageMipTailStride);
608 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
610 imageMipTailBinds.push_back(imageMipTailMemoryBind);
614 for (deUint32 pixelNdx = pixelOffset; pixelNdx < residencyReferenceData.size(); ++pixelNdx)
616 residencyReferenceData[pixelNdx] = MEMORY_BLOCK_BOUND_VALUE;
622 if (metadataAspectIndex != NO_MATCH_FOUND)
624 const VkSparseImageMemoryRequirements metadataAspectRequirements = sparseMemoryRequirements[metadataAspectIndex];
626 const deUint32 metadataBindCount = (metadataAspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT ? 1u : imageSparseInfo.arrayLayers);
627 for (deUint32 bindNdx = 0u; bindNdx < metadataBindCount; ++bindNdx)
629 const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
630 metadataAspectRequirements.imageMipTailSize, memoryType,
631 metadataAspectRequirements.imageMipTailOffset + bindNdx * metadataAspectRequirements.imageMipTailStride,
632 VK_SPARSE_MEMORY_BIND_METADATA_BIT);
634 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
636 imageMipTailBinds.push_back(imageMipTailMemoryBind);
640 VkBindSparseInfo bindSparseInfo =
642 VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, //VkStructureType sType;
643 DE_NULL, //const void* pNext;
644 0u, //deUint32 waitSemaphoreCount;
645 DE_NULL, //const VkSemaphore* pWaitSemaphores;
646 0u, //deUint32 bufferBindCount;
647 DE_NULL, //const VkSparseBufferMemoryBindInfo* pBufferBinds;
648 0u, //deUint32 imageOpaqueBindCount;
649 DE_NULL, //const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds;
650 0u, //deUint32 imageBindCount;
651 DE_NULL, //const VkSparseImageMemoryBindInfo* pImageBinds;
652 1u, //deUint32 signalSemaphoreCount;
653 &memoryBindSemaphore.get() //const VkSemaphore* pSignalSemaphores;
656 VkSparseImageMemoryBindInfo imageResidencyBindInfo;
657 VkSparseImageOpaqueMemoryBindInfo imageMipTailBindInfo;
659 if (imageResidencyMemoryBinds.size() > 0)
661 imageResidencyBindInfo.image = *imageSparse;
662 imageResidencyBindInfo.bindCount = static_cast<deUint32>(imageResidencyMemoryBinds.size());
663 imageResidencyBindInfo.pBinds = imageResidencyMemoryBinds.data();
665 bindSparseInfo.imageBindCount = 1u;
666 bindSparseInfo.pImageBinds = &imageResidencyBindInfo;
669 if (imageMipTailBinds.size() > 0)
671 imageMipTailBindInfo.image = *imageSparse;
672 imageMipTailBindInfo.bindCount = static_cast<deUint32>(imageMipTailBinds.size());
673 imageMipTailBindInfo.pBinds = imageMipTailBinds.data();
675 bindSparseInfo.imageOpaqueBindCount = 1u;
676 bindSparseInfo.pImageOpaqueBinds = &imageMipTailBindInfo;
679 // Submit sparse bind commands for execution
680 VK_CHECK(deviceInterface.queueBindSparse(sparseQueue.queueHandle, 1u, &bindSparseInfo, DE_NULL));
683 // Create image to store texels copied from sparse image
684 imageTexelsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
685 imageTexelsInfo.pNext = DE_NULL;
686 imageTexelsInfo.flags = 0u;
687 imageTexelsInfo.imageType = imageSparseInfo.imageType;
688 imageTexelsInfo.format = imageSparseInfo.format;
689 imageTexelsInfo.extent = imageSparseInfo.extent;
690 imageTexelsInfo.arrayLayers = imageSparseInfo.arrayLayers;
691 imageTexelsInfo.mipLevels = imageSparseInfo.mipLevels;
692 imageTexelsInfo.samples = imageSparseInfo.samples;
693 imageTexelsInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
694 imageTexelsInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
695 imageTexelsInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | imageOutputUsageFlags();
696 imageTexelsInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
697 imageTexelsInfo.queueFamilyIndexCount = 0u;
698 imageTexelsInfo.pQueueFamilyIndices = DE_NULL;
700 if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
702 imageTexelsInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
705 const Unique<VkImage> imageTexels (createImage(deviceInterface, getDevice(), &imageTexelsInfo));
706 const de::UniquePtr<Allocation> imageTexelsAlloc (bindImage(deviceInterface, getDevice(), getAllocator(), *imageTexels, MemoryRequirement::Any));
708 // Create image to store residency info copied from sparse image
709 imageResidencyInfo = imageTexelsInfo;
710 imageResidencyInfo.format = mapTextureFormat(m_residencyFormat);
712 const Unique<VkImage> imageResidency (createImage(deviceInterface, getDevice(), &imageResidencyInfo));
713 const de::UniquePtr<Allocation> imageResidencyAlloc (bindImage(deviceInterface, getDevice(), getAllocator(), *imageResidency, MemoryRequirement::Any));
715 std::vector <VkBufferImageCopy> bufferImageSparseCopy(formatDescription.numPlanes * imageSparseInfo.mipLevels);
718 deUint32 bufferOffset = 0u;
719 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
721 const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
723 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
725 bufferImageSparseCopy[planeNdx*imageSparseInfo.mipLevels + mipmapNdx] =
727 bufferOffset, // VkDeviceSize bufferOffset;
728 0u, // deUint32 bufferRowLength;
729 0u, // deUint32 bufferImageHeight;
730 makeImageSubresourceLayers(aspect, mipmapNdx, 0u, imageSparseInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource;
731 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
732 vk::getPlaneExtent(formatDescription, imageSparseInfo.extent, planeNdx, mipmapNdx) // VkExtent3D imageExtent;
734 bufferOffset += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
739 // Create command buffer for compute and transfer operations
740 const Unique<VkCommandPool> commandPool(makeCommandPool(deviceInterface, getDevice(), extractQueue.queueFamilyIndex));
741 const Unique<VkCommandBuffer> commandBuffer(allocateCommandBuffer(deviceInterface, getDevice(), *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
743 // Start recording commands
744 beginCommandBuffer(deviceInterface, *commandBuffer);
746 // Create input buffer
747 const VkBufferCreateInfo inputBufferCreateInfo = makeBufferCreateInfo(imageSparseSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
748 const Unique<VkBuffer> inputBuffer (createBuffer(deviceInterface, getDevice(), &inputBufferCreateInfo));
749 const de::UniquePtr<Allocation> inputBufferAlloc (bindBuffer(deviceInterface, getDevice(), getAllocator(), *inputBuffer, MemoryRequirement::HostVisible));
751 // Fill input buffer with reference data
752 std::vector<deUint8> referenceData(imageSparseSizeInBytes);
754 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
756 for (deUint32 mipmapNdx = 0u; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
758 const deUint32 mipLevelSizeinBytes = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx);
759 const deUint32 bufferOffset = static_cast<deUint32>(bufferImageSparseCopy[mipmapNdx].bufferOffset);
761 if (formatIsR64(m_format) &&
762 (m_function == SPARSE_SAMPLE_EXPLICIT_LOD || m_function == SPARSE_SAMPLE_IMPLICIT_LOD || m_function == SPARSE_GATHER))
764 for (deUint32 byteNdx = 0u; byteNdx < mipLevelSizeinBytes/8; byteNdx += 8)
766 void* prtData = &referenceData[bufferOffset + byteNdx];
767 *(static_cast<deUint64*>(prtData)) = (deUint64)((mipmapNdx + byteNdx) % 0x0FFFFFFF);
772 for (deUint32 byteNdx = 0u; byteNdx < mipLevelSizeinBytes; ++byteNdx)
774 referenceData[bufferOffset + byteNdx] = (deUint8)( (mipmapNdx + byteNdx) % 127u );
780 deMemcpy(inputBufferAlloc->getHostPtr(), referenceData.data(), imageSparseSizeInBytes);
781 flushAlloc(deviceInterface, getDevice(), *inputBufferAlloc);
784 // Prepare input buffer for data transfer operation
785 const VkBufferMemoryBarrier inputBufferBarrier = makeBufferMemoryBarrier
787 VK_ACCESS_HOST_WRITE_BIT,
788 VK_ACCESS_TRANSFER_READ_BIT,
791 imageSparseSizeInBytes
794 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 1u, &inputBufferBarrier, 0u, DE_NULL);
798 // Prepare sparse image for data transfer operation
799 std::vector<VkImageMemoryBarrier> imageSparseTransferDstBarriers;
800 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
802 const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
804 imageSparseTransferDstBarriers.emplace_back(makeImageMemoryBarrier
807 VK_ACCESS_TRANSFER_WRITE_BIT,
808 VK_IMAGE_LAYOUT_UNDEFINED,
809 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
811 makeImageSubresourceRange(aspect, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers),
812 sparseQueue.queueFamilyIndex != extractQueue.queueFamilyIndex ? sparseQueue.queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED,
813 sparseQueue.queueFamilyIndex != extractQueue.queueFamilyIndex ? extractQueue.queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED
816 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, static_cast<deUint32>(imageSparseTransferDstBarriers.size()), imageSparseTransferDstBarriers.data());
819 // Copy reference data from input buffer to sparse image
820 deviceInterface.cmdCopyBufferToImage(*commandBuffer, *inputBuffer, *imageSparse, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, static_cast<deUint32>(bufferImageSparseCopy.size()), bufferImageSparseCopy.data());
822 recordCommands(*commandBuffer, imageSparseInfo, *imageSparse, *imageTexels, *imageResidency);
824 const VkBufferCreateInfo bufferTexelsCreateInfo = makeBufferCreateInfo(imageSparseSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
825 const Unique<VkBuffer> bufferTexels (createBuffer(deviceInterface, getDevice(), &bufferTexelsCreateInfo));
826 const de::UniquePtr<Allocation> bufferTexelsAlloc (bindBuffer(deviceInterface, getDevice(), getAllocator(), *bufferTexels, MemoryRequirement::HostVisible));
828 // Copy data from texels image to buffer
829 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, *imageTexels, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *bufferTexels, static_cast<deUint32>(bufferImageSparseCopy.size()), bufferImageSparseCopy.data());
831 const deUint32 imageResidencySizeInBytes = getImageSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_residencyFormat, imageSparseInfo.mipLevels, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
833 const VkBufferCreateInfo bufferResidencyCreateInfo = makeBufferCreateInfo(imageResidencySizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
834 const Unique<VkBuffer> bufferResidency (createBuffer(deviceInterface, getDevice(), &bufferResidencyCreateInfo));
835 const de::UniquePtr<Allocation> bufferResidencyAlloc (bindBuffer(deviceInterface, getDevice(), getAllocator(), *bufferResidency, MemoryRequirement::HostVisible));
837 // Copy data from residency image to buffer
838 std::vector <VkBufferImageCopy> bufferImageResidencyCopy(formatDescription.numPlanes * imageSparseInfo.mipLevels);
841 deUint32 bufferOffset = 0u;
842 for (deUint32 planeNdx = 0u; planeNdx < formatDescription.numPlanes; ++planeNdx)
844 const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
846 for (deUint32 mipmapNdx = 0u; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
848 bufferImageResidencyCopy[planeNdx * imageSparseInfo.mipLevels + mipmapNdx] =
850 bufferOffset, // VkDeviceSize bufferOffset;
851 0u, // deUint32 bufferRowLength;
852 0u, // deUint32 bufferImageHeight;
853 makeImageSubresourceLayers(aspect, mipmapNdx, 0u, imageSparseInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource;
854 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
855 vk::getPlaneExtent(formatDescription, imageSparseInfo.extent, planeNdx, mipmapNdx) // VkExtent3D imageExtent;
857 bufferOffset += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_residencyFormat, mipmapNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
862 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, *imageResidency, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *bufferResidency, static_cast<deUint32>(bufferImageResidencyCopy.size()), bufferImageResidencyCopy.data());
865 VkBufferMemoryBarrier bufferOutputHostReadBarriers[2];
867 bufferOutputHostReadBarriers[0] = makeBufferMemoryBarrier
869 VK_ACCESS_TRANSFER_WRITE_BIT,
870 VK_ACCESS_HOST_READ_BIT,
873 imageSparseSizeInBytes
876 bufferOutputHostReadBarriers[1] = makeBufferMemoryBarrier
878 VK_ACCESS_TRANSFER_WRITE_BIT,
879 VK_ACCESS_HOST_READ_BIT,
882 imageResidencySizeInBytes
885 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 2u, bufferOutputHostReadBarriers, 0u, DE_NULL);
888 // End recording commands
889 endCommandBuffer(deviceInterface, *commandBuffer);
891 const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TRANSFER_BIT };
893 // Submit commands for execution and wait for completion
894 submitCommandsAndWait(deviceInterface, getDevice(), extractQueue.queueHandle, *commandBuffer, 1u, &memoryBindSemaphore.get(), stageBits);
896 // Wait for sparse queue to become idle
897 deviceInterface.queueWaitIdle(sparseQueue.queueHandle);
899 // Retrieve data from residency buffer to host memory
900 invalidateAlloc(deviceInterface, getDevice(), *bufferResidencyAlloc);
902 const deUint32* bufferResidencyData = static_cast<const deUint32*>(bufferResidencyAlloc->getHostPtr());
904 deUint32 pixelOffsetNotAligned = 0u;
905 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
907 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
909 const deUint32 mipLevelSizeInBytes = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_residencyFormat, mipmapNdx);
910 const deUint32 pixelOffsetAligned = static_cast<deUint32>(bufferImageResidencyCopy[planeNdx * imageSparseInfo.mipLevels + mipmapNdx].bufferOffset) / tcu::getPixelSize(m_residencyFormat);
912 if (deMemCmp(&bufferResidencyData[pixelOffsetAligned], &residencyReferenceData[pixelOffsetNotAligned], mipLevelSizeInBytes) != 0)
913 return tcu::TestStatus::fail("Failed");
915 pixelOffsetNotAligned += mipLevelSizeInBytes / tcu::getPixelSize(m_residencyFormat);
918 // Retrieve data from texels buffer to host memory
919 invalidateAlloc(deviceInterface, getDevice(), *bufferTexelsAlloc);
921 const deUint8* bufferTexelsData = static_cast<const deUint8*>(bufferTexelsAlloc->getHostPtr());
923 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
925 const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
926 const deUint32 aspectIndex = getSparseAspectRequirementsIndex(sparseMemoryRequirements, aspect);
928 if (aspectIndex == NO_MATCH_FOUND)
929 TCU_THROW(NotSupportedError, "Not supported image aspect");
931 VkSparseImageMemoryRequirements aspectRequirements = sparseMemoryRequirements[aspectIndex];
933 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
935 const deUint32 mipLevelSizeInBytes = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription,planeNdx, mipmapNdx);
936 const deUint32 bufferOffset = static_cast<deUint32>(bufferImageSparseCopy[planeNdx * imageSparseInfo.mipLevels + mipmapNdx].bufferOffset);
938 if (mipmapNdx < aspectRequirements.imageMipTailFirstLod)
940 if (mipmapNdx % MEMORY_BLOCK_TYPE_COUNT == MEMORY_BLOCK_BOUND)
942 if (deMemCmp(&bufferTexelsData[bufferOffset], &referenceData[bufferOffset], mipLevelSizeInBytes) != 0)
943 return tcu::TestStatus::fail("Failed");
945 else if (getPhysicalDeviceProperties(instance, physicalDevice).sparseProperties.residencyNonResidentStrict)
947 std::vector<deUint8> zeroData;
948 zeroData.assign(mipLevelSizeInBytes, 0u);
950 if (deMemCmp(&bufferTexelsData[bufferOffset], zeroData.data(), mipLevelSizeInBytes) != 0)
951 return tcu::TestStatus::fail("Failed");
956 if (deMemCmp(&bufferTexelsData[bufferOffset], &referenceData[bufferOffset], mipLevelSizeInBytes) != 0)
957 return tcu::TestStatus::fail("Failed");
962 return tcu::TestStatus::pass("Passed");