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 void SparseShaderIntrinsicsInstanceBase::checkSupport(VkImageCreateInfo imageSparseInfo) const
416 const InstanceInterface& instance = m_context.getInstanceInterface();
417 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
419 if (formatIsR64(m_format))
421 m_context.requireDeviceFunctionality("VK_EXT_shader_image_atomic_int64");
423 if (m_context.getShaderImageAtomicInt64FeaturesEXT().shaderImageInt64Atomics == VK_FALSE)
425 TCU_THROW(NotSupportedError, "shaderImageInt64Atomics is not supported");
428 if (m_context.getShaderImageAtomicInt64FeaturesEXT().sparseImageInt64Atomics == VK_FALSE)
430 TCU_THROW(NotSupportedError, "sparseImageInt64Atomics is not supported for device");
434 // Check if device supports sparse operations for image format
435 if (!checkSparseSupportForImageFormat(instance, physicalDevice, imageSparseInfo))
436 TCU_THROW(NotSupportedError, "The image format does not support sparse operations");
440 tcu::TestStatus SparseShaderIntrinsicsInstanceBase::iterate (void)
442 const InstanceInterface& instance = m_context.getInstanceInterface();
443 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
444 VkImageCreateInfo imageSparseInfo;
445 VkImageCreateInfo imageTexelsInfo;
446 VkImageCreateInfo imageResidencyInfo;
447 std::vector <deUint32> residencyReferenceData;
448 std::vector<DeviceMemorySp> deviceMemUniquePtrVec;
449 const PlanarFormatDescription formatDescription = getPlanarFormatDescription(m_format);
451 imageSparseInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
452 imageSparseInfo.pNext = DE_NULL;
453 imageSparseInfo.flags = VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_IMAGE_CREATE_SPARSE_BINDING_BIT;
454 imageSparseInfo.imageType = mapImageType(m_imageType);
455 imageSparseInfo.format = m_format;
456 imageSparseInfo.extent = makeExtent3D(getLayerSize(m_imageType, m_imageSize));
457 imageSparseInfo.arrayLayers = getNumLayers(m_imageType, m_imageSize);
458 imageSparseInfo.samples = VK_SAMPLE_COUNT_1_BIT;
459 imageSparseInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
460 imageSparseInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
461 imageSparseInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | imageSparseUsageFlags();
462 imageSparseInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
463 imageSparseInfo.queueFamilyIndexCount = 0u;
464 imageSparseInfo.pQueueFamilyIndices = DE_NULL;
466 if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
468 imageSparseInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
471 checkSupport(imageSparseInfo);
474 // Assign maximum allowed mipmap levels to image
475 VkImageFormatProperties imageFormatProperties;
476 if (instance.getPhysicalDeviceImageFormatProperties(physicalDevice,
477 imageSparseInfo.format,
478 imageSparseInfo.imageType,
479 imageSparseInfo.tiling,
480 imageSparseInfo.usage,
481 imageSparseInfo.flags,
482 &imageFormatProperties) == VK_ERROR_FORMAT_NOT_SUPPORTED)
484 TCU_THROW(NotSupportedError, "Image format does not support sparse operations");
487 imageSparseInfo.mipLevels = getMipmapCount(m_format, formatDescription, imageFormatProperties, imageSparseInfo.extent);
491 // Create logical device supporting both sparse and compute/graphics queues
492 QueueRequirementsVec queueRequirements;
493 queueRequirements.push_back(QueueRequirements(VK_QUEUE_SPARSE_BINDING_BIT, 1u));
494 queueRequirements.push_back(QueueRequirements(getQueueFlags(), 1u));
496 createDeviceSupportingQueues(queueRequirements);
499 // Create queues supporting sparse binding operations and compute/graphics operations
500 const DeviceInterface& deviceInterface = getDeviceInterface();
501 const Queue& sparseQueue = getQueue(VK_QUEUE_SPARSE_BINDING_BIT, 0);
502 const Queue& extractQueue = getQueue(getQueueFlags(), 0);
504 // Create sparse image
505 const Unique<VkImage> imageSparse(createImage(deviceInterface, getDevice(), &imageSparseInfo));
507 // Create sparse image memory bind semaphore
508 const Unique<VkSemaphore> memoryBindSemaphore(createSemaphore(deviceInterface, getDevice()));
510 std::vector<VkSparseImageMemoryRequirements> sparseMemoryRequirements;
512 deUint32 imageSparseSizeInBytes = 0;
513 deUint32 imageSizeInPixels = 0;
515 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
517 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
519 imageSparseSizeInBytes += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
520 imageSizeInPixels += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx) / formatDescription.planes[planeNdx].elementSizeBytes;
524 residencyReferenceData.assign(imageSizeInPixels, MEMORY_BLOCK_NOT_BOUND_VALUE);
527 // Get sparse image general memory requirements
528 const VkMemoryRequirements imageMemoryRequirements = getImageMemoryRequirements(deviceInterface, getDevice(), *imageSparse);
530 // Check if required image memory size does not exceed device limits
531 if (imageMemoryRequirements.size > getPhysicalDeviceProperties(instance, physicalDevice).limits.sparseAddressSpaceSize)
532 TCU_THROW(NotSupportedError, "Required memory size for sparse resource exceeds device limits");
534 DE_ASSERT((imageMemoryRequirements.size % imageMemoryRequirements.alignment) == 0);
536 const deUint32 memoryType = findMatchingMemoryType(instance, physicalDevice, imageMemoryRequirements, MemoryRequirement::Any);
538 if (memoryType == NO_MATCH_FOUND)
539 return tcu::TestStatus::fail("No matching memory type found");
541 // Get sparse image sparse memory requirements
542 sparseMemoryRequirements = getImageSparseMemoryRequirements(deviceInterface, getDevice(), *imageSparse);
544 DE_ASSERT(sparseMemoryRequirements.size() != 0);
546 const deUint32 metadataAspectIndex = getSparseAspectRequirementsIndex(sparseMemoryRequirements, VK_IMAGE_ASPECT_METADATA_BIT);
547 deUint32 pixelOffset = 0u;
548 std::vector<VkSparseImageMemoryBind> imageResidencyMemoryBinds;
549 std::vector<VkSparseMemoryBind> imageMipTailBinds;
551 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
553 const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
554 const deUint32 aspectIndex = getSparseAspectRequirementsIndex(sparseMemoryRequirements, aspect);
556 if (aspectIndex == NO_MATCH_FOUND)
557 TCU_THROW(NotSupportedError, "Not supported image aspect");
559 VkSparseImageMemoryRequirements aspectRequirements = sparseMemoryRequirements[aspectIndex];
561 DE_ASSERT((aspectRequirements.imageMipTailSize % imageMemoryRequirements.alignment) == 0);
563 VkExtent3D imageGranularity = aspectRequirements.formatProperties.imageGranularity;
565 // Bind memory for each mipmap level
566 for (deUint32 mipmapNdx = 0; mipmapNdx < aspectRequirements.imageMipTailFirstLod; ++mipmapNdx)
568 const deUint32 mipLevelSizeInPixels = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx) / formatDescription.planes[planeNdx].elementSizeBytes;
570 if (mipmapNdx % MEMORY_BLOCK_TYPE_COUNT == MEMORY_BLOCK_NOT_BOUND)
572 pixelOffset += mipLevelSizeInPixels;
576 for (deUint32 pixelNdx = 0u; pixelNdx < mipLevelSizeInPixels; ++pixelNdx)
578 residencyReferenceData[pixelOffset + pixelNdx] = MEMORY_BLOCK_BOUND_VALUE;
581 pixelOffset += mipLevelSizeInPixels;
583 for (deUint32 layerNdx = 0; layerNdx < imageSparseInfo.arrayLayers; ++layerNdx)
585 const VkExtent3D mipExtent = getPlaneExtent(formatDescription, imageSparseInfo.extent, planeNdx, mipmapNdx);
586 const tcu::UVec3 sparseBlocks = alignedDivide(mipExtent, imageGranularity);
587 const deUint32 numSparseBlocks = sparseBlocks.x() * sparseBlocks.y() * sparseBlocks.z();
588 const VkImageSubresource subresource = { aspect, mipmapNdx, layerNdx };
590 const VkSparseImageMemoryBind imageMemoryBind = makeSparseImageMemoryBind(deviceInterface, getDevice(),
591 imageMemoryRequirements.alignment * numSparseBlocks, memoryType, subresource, makeOffset3D(0u, 0u, 0u), mipExtent);
593 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
595 imageResidencyMemoryBinds.push_back(imageMemoryBind);
599 if (aspectRequirements.imageMipTailFirstLod < imageSparseInfo.mipLevels)
601 if (aspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT)
603 const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
604 aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset);
606 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
608 imageMipTailBinds.push_back(imageMipTailMemoryBind);
612 for (deUint32 layerNdx = 0; layerNdx < imageSparseInfo.arrayLayers; ++layerNdx)
614 const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
615 aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset + layerNdx * aspectRequirements.imageMipTailStride);
617 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
619 imageMipTailBinds.push_back(imageMipTailMemoryBind);
623 for (deUint32 pixelNdx = pixelOffset; pixelNdx < residencyReferenceData.size(); ++pixelNdx)
625 residencyReferenceData[pixelNdx] = MEMORY_BLOCK_BOUND_VALUE;
631 if (metadataAspectIndex != NO_MATCH_FOUND)
633 const VkSparseImageMemoryRequirements metadataAspectRequirements = sparseMemoryRequirements[metadataAspectIndex];
635 const deUint32 metadataBindCount = (metadataAspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT ? 1u : imageSparseInfo.arrayLayers);
636 for (deUint32 bindNdx = 0u; bindNdx < metadataBindCount; ++bindNdx)
638 const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
639 metadataAspectRequirements.imageMipTailSize, memoryType,
640 metadataAspectRequirements.imageMipTailOffset + bindNdx * metadataAspectRequirements.imageMipTailStride,
641 VK_SPARSE_MEMORY_BIND_METADATA_BIT);
643 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
645 imageMipTailBinds.push_back(imageMipTailMemoryBind);
649 VkBindSparseInfo bindSparseInfo =
651 VK_STRUCTURE_TYPE_BIND_SPARSE_INFO, //VkStructureType sType;
652 DE_NULL, //const void* pNext;
653 0u, //deUint32 waitSemaphoreCount;
654 DE_NULL, //const VkSemaphore* pWaitSemaphores;
655 0u, //deUint32 bufferBindCount;
656 DE_NULL, //const VkSparseBufferMemoryBindInfo* pBufferBinds;
657 0u, //deUint32 imageOpaqueBindCount;
658 DE_NULL, //const VkSparseImageOpaqueMemoryBindInfo* pImageOpaqueBinds;
659 0u, //deUint32 imageBindCount;
660 DE_NULL, //const VkSparseImageMemoryBindInfo* pImageBinds;
661 1u, //deUint32 signalSemaphoreCount;
662 &memoryBindSemaphore.get() //const VkSemaphore* pSignalSemaphores;
665 VkSparseImageMemoryBindInfo imageResidencyBindInfo;
666 VkSparseImageOpaqueMemoryBindInfo imageMipTailBindInfo;
668 if (imageResidencyMemoryBinds.size() > 0)
670 imageResidencyBindInfo.image = *imageSparse;
671 imageResidencyBindInfo.bindCount = static_cast<deUint32>(imageResidencyMemoryBinds.size());
672 imageResidencyBindInfo.pBinds = imageResidencyMemoryBinds.data();
674 bindSparseInfo.imageBindCount = 1u;
675 bindSparseInfo.pImageBinds = &imageResidencyBindInfo;
678 if (imageMipTailBinds.size() > 0)
680 imageMipTailBindInfo.image = *imageSparse;
681 imageMipTailBindInfo.bindCount = static_cast<deUint32>(imageMipTailBinds.size());
682 imageMipTailBindInfo.pBinds = imageMipTailBinds.data();
684 bindSparseInfo.imageOpaqueBindCount = 1u;
685 bindSparseInfo.pImageOpaqueBinds = &imageMipTailBindInfo;
688 // Submit sparse bind commands for execution
689 VK_CHECK(deviceInterface.queueBindSparse(sparseQueue.queueHandle, 1u, &bindSparseInfo, DE_NULL));
692 // Create image to store texels copied from sparse image
693 imageTexelsInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
694 imageTexelsInfo.pNext = DE_NULL;
695 imageTexelsInfo.flags = 0u;
696 imageTexelsInfo.imageType = imageSparseInfo.imageType;
697 imageTexelsInfo.format = imageSparseInfo.format;
698 imageTexelsInfo.extent = imageSparseInfo.extent;
699 imageTexelsInfo.arrayLayers = imageSparseInfo.arrayLayers;
700 imageTexelsInfo.mipLevels = imageSparseInfo.mipLevels;
701 imageTexelsInfo.samples = imageSparseInfo.samples;
702 imageTexelsInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
703 imageTexelsInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
704 imageTexelsInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | imageOutputUsageFlags();
705 imageTexelsInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
706 imageTexelsInfo.queueFamilyIndexCount = 0u;
707 imageTexelsInfo.pQueueFamilyIndices = DE_NULL;
709 if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
711 imageTexelsInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
714 const Unique<VkImage> imageTexels (createImage(deviceInterface, getDevice(), &imageTexelsInfo));
715 const de::UniquePtr<Allocation> imageTexelsAlloc (bindImage(deviceInterface, getDevice(), getAllocator(), *imageTexels, MemoryRequirement::Any));
717 // Create image to store residency info copied from sparse image
718 imageResidencyInfo = imageTexelsInfo;
719 imageResidencyInfo.format = mapTextureFormat(m_residencyFormat);
721 const Unique<VkImage> imageResidency (createImage(deviceInterface, getDevice(), &imageResidencyInfo));
722 const de::UniquePtr<Allocation> imageResidencyAlloc (bindImage(deviceInterface, getDevice(), getAllocator(), *imageResidency, MemoryRequirement::Any));
724 std::vector <VkBufferImageCopy> bufferImageSparseCopy(formatDescription.numPlanes * imageSparseInfo.mipLevels);
727 deUint32 bufferOffset = 0u;
728 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
730 const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
732 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
734 bufferImageSparseCopy[planeNdx*imageSparseInfo.mipLevels + mipmapNdx] =
736 bufferOffset, // VkDeviceSize bufferOffset;
737 0u, // deUint32 bufferRowLength;
738 0u, // deUint32 bufferImageHeight;
739 makeImageSubresourceLayers(aspect, mipmapNdx, 0u, imageSparseInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource;
740 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
741 vk::getPlaneExtent(formatDescription, imageSparseInfo.extent, planeNdx, mipmapNdx) // VkExtent3D imageExtent;
743 bufferOffset += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
748 // Create command buffer for compute and transfer operations
749 const Unique<VkCommandPool> commandPool(makeCommandPool(deviceInterface, getDevice(), extractQueue.queueFamilyIndex));
750 const Unique<VkCommandBuffer> commandBuffer(allocateCommandBuffer(deviceInterface, getDevice(), *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
752 // Start recording commands
753 beginCommandBuffer(deviceInterface, *commandBuffer);
755 // Create input buffer
756 const VkBufferCreateInfo inputBufferCreateInfo = makeBufferCreateInfo(imageSparseSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
757 const Unique<VkBuffer> inputBuffer (createBuffer(deviceInterface, getDevice(), &inputBufferCreateInfo));
758 const de::UniquePtr<Allocation> inputBufferAlloc (bindBuffer(deviceInterface, getDevice(), getAllocator(), *inputBuffer, MemoryRequirement::HostVisible));
760 // Fill input buffer with reference data
761 std::vector<deUint8> referenceData(imageSparseSizeInBytes);
763 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
765 for (deUint32 mipmapNdx = 0u; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
767 const deUint32 mipLevelSizeinBytes = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx);
768 const deUint32 bufferOffset = static_cast<deUint32>(bufferImageSparseCopy[mipmapNdx].bufferOffset);
770 if (formatIsR64(m_format) &&
771 (m_function == SPARSE_SAMPLE_EXPLICIT_LOD || m_function == SPARSE_SAMPLE_IMPLICIT_LOD || m_function == SPARSE_GATHER))
773 for (deUint32 byteNdx = 0u; byteNdx < mipLevelSizeinBytes/8; byteNdx += 8)
775 void* prtData = &referenceData[bufferOffset + byteNdx];
776 *(static_cast<deUint64*>(prtData)) = (deUint64)((mipmapNdx + byteNdx) % 0x0FFFFFFF);
781 for (deUint32 byteNdx = 0u; byteNdx < mipLevelSizeinBytes; ++byteNdx)
783 referenceData[bufferOffset + byteNdx] = (deUint8)( (mipmapNdx + byteNdx) % 127u );
789 deMemcpy(inputBufferAlloc->getHostPtr(), referenceData.data(), imageSparseSizeInBytes);
790 flushAlloc(deviceInterface, getDevice(), *inputBufferAlloc);
793 // Prepare input buffer for data transfer operation
794 const VkBufferMemoryBarrier inputBufferBarrier = makeBufferMemoryBarrier
796 VK_ACCESS_HOST_WRITE_BIT,
797 VK_ACCESS_TRANSFER_READ_BIT,
800 imageSparseSizeInBytes
803 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 1u, &inputBufferBarrier, 0u, DE_NULL);
807 // Prepare sparse image for data transfer operation
808 std::vector<VkImageMemoryBarrier> imageSparseTransferDstBarriers;
809 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
811 const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
813 imageSparseTransferDstBarriers.emplace_back(makeImageMemoryBarrier
816 VK_ACCESS_TRANSFER_WRITE_BIT,
817 VK_IMAGE_LAYOUT_UNDEFINED,
818 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
820 makeImageSubresourceRange(aspect, 0u, imageSparseInfo.mipLevels, 0u, imageSparseInfo.arrayLayers),
821 sparseQueue.queueFamilyIndex != extractQueue.queueFamilyIndex ? sparseQueue.queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED,
822 sparseQueue.queueFamilyIndex != extractQueue.queueFamilyIndex ? extractQueue.queueFamilyIndex : VK_QUEUE_FAMILY_IGNORED
825 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());
828 // Copy reference data from input buffer to sparse image
829 deviceInterface.cmdCopyBufferToImage(*commandBuffer, *inputBuffer, *imageSparse, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, static_cast<deUint32>(bufferImageSparseCopy.size()), bufferImageSparseCopy.data());
831 recordCommands(*commandBuffer, imageSparseInfo, *imageSparse, *imageTexels, *imageResidency);
833 const VkBufferCreateInfo bufferTexelsCreateInfo = makeBufferCreateInfo(imageSparseSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
834 const Unique<VkBuffer> bufferTexels (createBuffer(deviceInterface, getDevice(), &bufferTexelsCreateInfo));
835 const de::UniquePtr<Allocation> bufferTexelsAlloc (bindBuffer(deviceInterface, getDevice(), getAllocator(), *bufferTexels, MemoryRequirement::HostVisible));
837 // Copy data from texels image to buffer
838 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, *imageTexels, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *bufferTexels, static_cast<deUint32>(bufferImageSparseCopy.size()), bufferImageSparseCopy.data());
840 const deUint32 imageResidencySizeInBytes = getImageSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_residencyFormat, imageSparseInfo.mipLevels, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
842 const VkBufferCreateInfo bufferResidencyCreateInfo = makeBufferCreateInfo(imageResidencySizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
843 const Unique<VkBuffer> bufferResidency (createBuffer(deviceInterface, getDevice(), &bufferResidencyCreateInfo));
844 const de::UniquePtr<Allocation> bufferResidencyAlloc (bindBuffer(deviceInterface, getDevice(), getAllocator(), *bufferResidency, MemoryRequirement::HostVisible));
846 // Copy data from residency image to buffer
847 std::vector <VkBufferImageCopy> bufferImageResidencyCopy(formatDescription.numPlanes * imageSparseInfo.mipLevels);
850 deUint32 bufferOffset = 0u;
851 for (deUint32 planeNdx = 0u; planeNdx < formatDescription.numPlanes; ++planeNdx)
853 const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
855 for (deUint32 mipmapNdx = 0u; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
857 bufferImageResidencyCopy[planeNdx * imageSparseInfo.mipLevels + mipmapNdx] =
859 bufferOffset, // VkDeviceSize bufferOffset;
860 0u, // deUint32 bufferRowLength;
861 0u, // deUint32 bufferImageHeight;
862 makeImageSubresourceLayers(aspect, mipmapNdx, 0u, imageSparseInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource;
863 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
864 vk::getPlaneExtent(formatDescription, imageSparseInfo.extent, planeNdx, mipmapNdx) // VkExtent3D imageExtent;
866 bufferOffset += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_residencyFormat, mipmapNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
871 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, *imageResidency, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *bufferResidency, static_cast<deUint32>(bufferImageResidencyCopy.size()), bufferImageResidencyCopy.data());
874 VkBufferMemoryBarrier bufferOutputHostReadBarriers[2];
876 bufferOutputHostReadBarriers[0] = makeBufferMemoryBarrier
878 VK_ACCESS_TRANSFER_WRITE_BIT,
879 VK_ACCESS_HOST_READ_BIT,
882 imageSparseSizeInBytes
885 bufferOutputHostReadBarriers[1] = makeBufferMemoryBarrier
887 VK_ACCESS_TRANSFER_WRITE_BIT,
888 VK_ACCESS_HOST_READ_BIT,
891 imageResidencySizeInBytes
894 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 2u, bufferOutputHostReadBarriers, 0u, DE_NULL);
897 // End recording commands
898 endCommandBuffer(deviceInterface, *commandBuffer);
900 const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TRANSFER_BIT };
902 // Submit commands for execution and wait for completion
903 submitCommandsAndWait(deviceInterface, getDevice(), extractQueue.queueHandle, *commandBuffer, 1u, &memoryBindSemaphore.get(), stageBits);
905 // Wait for sparse queue to become idle
906 deviceInterface.queueWaitIdle(sparseQueue.queueHandle);
908 // Retrieve data from residency buffer to host memory
909 invalidateAlloc(deviceInterface, getDevice(), *bufferResidencyAlloc);
911 const deUint32* bufferResidencyData = static_cast<const deUint32*>(bufferResidencyAlloc->getHostPtr());
913 deUint32 pixelOffsetNotAligned = 0u;
914 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
916 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
918 const deUint32 mipLevelSizeInBytes = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_residencyFormat, mipmapNdx);
919 const deUint32 pixelOffsetAligned = static_cast<deUint32>(bufferImageResidencyCopy[planeNdx * imageSparseInfo.mipLevels + mipmapNdx].bufferOffset) / tcu::getPixelSize(m_residencyFormat);
921 if (deMemCmp(&bufferResidencyData[pixelOffsetAligned], &residencyReferenceData[pixelOffsetNotAligned], mipLevelSizeInBytes) != 0)
922 return tcu::TestStatus::fail("Failed");
924 pixelOffsetNotAligned += mipLevelSizeInBytes / tcu::getPixelSize(m_residencyFormat);
927 // Retrieve data from texels buffer to host memory
928 invalidateAlloc(deviceInterface, getDevice(), *bufferTexelsAlloc);
930 const deUint8* bufferTexelsData = static_cast<const deUint8*>(bufferTexelsAlloc->getHostPtr());
932 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
934 const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
935 const deUint32 aspectIndex = getSparseAspectRequirementsIndex(sparseMemoryRequirements, aspect);
937 if (aspectIndex == NO_MATCH_FOUND)
938 TCU_THROW(NotSupportedError, "Not supported image aspect");
940 VkSparseImageMemoryRequirements aspectRequirements = sparseMemoryRequirements[aspectIndex];
942 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
944 const deUint32 mipLevelSizeInBytes = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription,planeNdx, mipmapNdx);
945 const deUint32 bufferOffset = static_cast<deUint32>(bufferImageSparseCopy[planeNdx * imageSparseInfo.mipLevels + mipmapNdx].bufferOffset);
947 if (mipmapNdx < aspectRequirements.imageMipTailFirstLod)
949 if (mipmapNdx % MEMORY_BLOCK_TYPE_COUNT == MEMORY_BLOCK_BOUND)
951 if (deMemCmp(&bufferTexelsData[bufferOffset], &referenceData[bufferOffset], mipLevelSizeInBytes) != 0)
952 return tcu::TestStatus::fail("Failed");
954 else if (getPhysicalDeviceProperties(instance, physicalDevice).sparseProperties.residencyNonResidentStrict)
956 std::vector<deUint8> zeroData;
957 zeroData.assign(mipLevelSizeInBytes, 0u);
959 if (deMemCmp(&bufferTexelsData[bufferOffset], zeroData.data(), mipLevelSizeInBytes) != 0)
960 return tcu::TestStatus::fail("Failed");
965 if (deMemCmp(&bufferTexelsData[bufferOffset], &referenceData[bufferOffset], mipLevelSizeInBytes) != 0)
966 return tcu::TestStatus::fail("Failed");
971 return tcu::TestStatus::pass("Passed");