Test behaviour of color write enable with colorWriteMask
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / sparse_resources / vktSparseResourcesShaderIntrinsicsBase.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*
20  * \file  vktSparseResourcesShaderIntrinsicsBase.cpp
21  * \brief Sparse Resources Shader Intrinsics Base Classes
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktSparseResourcesShaderIntrinsicsBase.hpp"
25 #include "vkCmdUtil.hpp"
26 #include "vkBarrierUtil.hpp"
27
28 using namespace vk;
29
30 namespace vkt
31 {
32 namespace sparse
33 {
34
35 std::string getOpTypeImageComponent (const tcu::TextureFormat& format)
36 {
37         switch (tcu::getTextureChannelClass(format.type))
38         {
39                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
40                         return "OpTypeInt 32 0";
41                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
42                         return "OpTypeInt 32 1";
43                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
44                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
45                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
46                         return "OpTypeFloat 32";
47                 default:
48                         DE_FATAL("Unexpected channel type");
49                         return "";
50         }
51 }
52
53 std::string getOpTypeImageComponent (const vk::PlanarFormatDescription& description)
54 {
55         switch (description.channels[0].type)
56         {
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";
65                 default:
66                         DE_FATAL("Unexpected channel type");
67                         return "";
68         }
69 }
70
71 std::string getImageComponentTypeName (const tcu::TextureFormat& format)
72 {
73         switch (tcu::getTextureChannelClass(format.type))
74         {
75                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
76                         return "%type_uint";
77                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
78                         return "%type_int";
79                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
80                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
81                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
82                         return "%type_float";
83                 default:
84                         DE_FATAL("Unexpected channel type");
85                         return "";
86         }
87 }
88
89 std::string getImageComponentTypeName (const vk::PlanarFormatDescription& description)
90 {
91         switch (description.channels[0].type)
92         {
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";
101                 default:
102                         DE_FATAL("Unexpected channel type");
103                         return "";
104         }
105 }
106
107 std::string getImageComponentVec4TypeName (const tcu::TextureFormat& format)
108 {
109         switch (tcu::getTextureChannelClass(format.type))
110         {
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:
118                         return "%type_vec4";
119                 default:
120                         DE_FATAL("Unexpected channel type");
121                         return "";
122         }
123 }
124
125 std::string getImageComponentVec4TypeName (const vk::PlanarFormatDescription& description)
126 {
127
128         switch (description.channels[0].type)
129         {
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:
137                         return "%type_vec4";
138                 default:
139                         DE_FATAL("Unexpected channel type");
140                         return "";
141         }
142 }
143
144 std::string getOpTypeImageSparse (const ImageType                       imageType,
145                                                                   const tcu::TextureFormat&     format,
146                                                                   const std::string&            componentType,
147                                                                   const bool                            requiresSampler)
148 {
149         std::ostringstream      src;
150
151         src << "OpTypeImage " << componentType << " ";
152
153         switch (imageType)
154         {
155                 case IMAGE_TYPE_1D :
156                         src << "1D 0 0 0 ";
157                 break;
158                 case IMAGE_TYPE_1D_ARRAY :
159                         src << "1D 0 1 0 ";
160                 break;
161                 case IMAGE_TYPE_2D :
162                         src << "2D 0 0 0 ";
163                 break;
164                 case IMAGE_TYPE_2D_ARRAY :
165                         src << "2D 0 1 0 ";
166                 break;
167                 case IMAGE_TYPE_3D :
168                         src << "3D 0 0 0 ";
169                 break;
170                 case IMAGE_TYPE_CUBE :
171                         src << "Cube 0 0 0 ";
172                 break;
173                 case IMAGE_TYPE_CUBE_ARRAY :
174                         src << "Cube 0 1 0 ";
175                 break;
176                 default :
177                         DE_FATAL("Unexpected image type");
178                 break;
179         };
180
181         if (requiresSampler)
182                 src << "1 ";
183         else
184                 src << "2 ";
185
186         switch (format.order)
187         {
188                 case tcu::TextureFormat::R:
189                         src << "R";
190                 break;
191                 case tcu::TextureFormat::RG:
192                         src << "Rg";
193                         break;
194                 case tcu::TextureFormat::RGB:
195                         src << "Rgb";
196                         break;
197                 case tcu::TextureFormat::RGBA:
198                         src << "Rgba";
199                 break;
200                 default:
201                         DE_FATAL("Unexpected channel order");
202                 break;
203         }
204
205         switch (format.type)
206         {
207                 case tcu::TextureFormat::SIGNED_INT8:
208                         src << "8i";
209                 break;
210                 case tcu::TextureFormat::SIGNED_INT16:
211                         src << "16i";
212                 break;
213                 case tcu::TextureFormat::SIGNED_INT32:
214                         src << "32i";
215                 break;
216                 case tcu::TextureFormat::UNSIGNED_INT8:
217                         src << "8ui";
218                 break;
219                 case tcu::TextureFormat::UNSIGNED_INT16:
220                         src << "16ui";
221                 break;
222                 case tcu::TextureFormat::UNSIGNED_INT32:
223                         src << "32ui";
224                 break;
225                 case tcu::TextureFormat::SNORM_INT8:
226                         src << "8Snorm";
227                 break;
228                 case tcu::TextureFormat::SNORM_INT16:
229                         src << "16Snorm";
230                 break;
231                 case tcu::TextureFormat::SNORM_INT32:
232                         src << "32Snorm";
233                 break;
234                 case tcu::TextureFormat::UNORM_INT8:
235                         src << "8";
236                 break;
237                 case tcu::TextureFormat::UNORM_INT16:
238                         src << "16";
239                 break;
240                 case tcu::TextureFormat::UNORM_INT32:
241                         src << "32";
242                 break;
243                 default:
244                         DE_FATAL("Unexpected channel type");
245                 break;
246         };
247
248         return src.str();
249 }
250
251 std::string getOpTypeImageSparse (const ImageType               imageType,
252                                                                   const VkFormat                format,
253                                                                   const std::string&    componentType,
254                                                                   const bool                    requiresSampler)
255 {
256         std::ostringstream      src;
257
258         src << "OpTypeImage " << componentType << " ";
259
260         switch (imageType)
261         {
262                 case IMAGE_TYPE_1D :
263                         src << "1D 0 0 0 ";
264                 break;
265                 case IMAGE_TYPE_1D_ARRAY :
266                         src << "1D 0 1 0 ";
267                 break;
268                 case IMAGE_TYPE_2D :
269                         src << "2D 0 0 0 ";
270                 break;
271                 case IMAGE_TYPE_2D_ARRAY :
272                         src << "2D 0 1 0 ";
273                 break;
274                 case IMAGE_TYPE_3D :
275                         src << "3D 0 0 0 ";
276                 break;
277                 case IMAGE_TYPE_CUBE :
278                         src << "Cube 0 0 0 ";
279                 break;
280                 case IMAGE_TYPE_CUBE_ARRAY :
281                         src << "Cube 0 1 0 ";
282                 break;
283                 default :
284                         DE_FATAL("Unexpected image type");
285                 break;
286         };
287
288         if (requiresSampler)
289                 src << "1 ";
290         else
291                 src << "2 ";
292
293         switch (format)
294         {
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;
307
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;
318
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;
329
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;
368
369                 default:
370                         DE_FATAL("Unexpected texture format");
371                         break;
372         }
373         return src.str();
374 }
375
376
377 std::string getOpTypeImageResidency (const ImageType imageType)
378 {
379         std::ostringstream      src;
380
381         src << "OpTypeImage %type_uint ";
382
383         switch (imageType)
384         {
385                 case IMAGE_TYPE_1D :
386                         src << "1D 0 0 0 2 R32ui";
387                 break;
388                 case IMAGE_TYPE_1D_ARRAY :
389                         src << "1D 0 1 0 2 R32ui";
390                 break;
391                 case IMAGE_TYPE_2D :
392                         src << "2D 0 0 0 2 R32ui";
393                 break;
394                 case IMAGE_TYPE_2D_ARRAY :
395                         src << "2D 0 1 0 2 R32ui";
396                 break;
397                 case IMAGE_TYPE_3D :
398                         src << "3D 0 0 0 2 R32ui";
399                 break;
400                 case IMAGE_TYPE_CUBE :
401                         src << "Cube 0 0 0 2 R32ui";
402                 break;
403                 case IMAGE_TYPE_CUBE_ARRAY :
404                         src << "Cube 0 1 0 2 R32ui";
405                 break;
406                 default :
407                         DE_FATAL("Unexpected image type");
408                 break;
409         };
410
411         return src.str();
412 }
413
414 tcu::TestStatus SparseShaderIntrinsicsInstanceBase::iterate (void)
415 {
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);
424
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;
439
440         if (formatIsR64(m_format))
441         {
442                 m_context.requireDeviceFunctionality("VK_EXT_shader_image_atomic_int64");
443
444                 if (m_context.getShaderImageAtomicInt64FeaturesEXT().shaderImageInt64Atomics == VK_FALSE)
445                 {
446                         TCU_THROW(NotSupportedError, "shaderImageInt64Atomics is not supported");
447                 }
448
449                 if (m_context.getShaderImageAtomicInt64FeaturesEXT().sparseImageInt64Atomics == VK_FALSE)
450                 {
451                         TCU_THROW(NotSupportedError, "sparseImageInt64Atomics is not supported for device");
452                 }
453         }
454
455         if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
456         {
457                 imageSparseInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
458         }
459
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");
463
464         {
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)
474                 {
475                         TCU_THROW(NotSupportedError, "Image format does not support sparse operations");
476                 }
477
478                 imageSparseInfo.mipLevels = getMipmapCount(m_format, formatDescription, imageFormatProperties, imageSparseInfo.extent);
479         }
480
481         {
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));
486
487                 createDeviceSupportingQueues(queueRequirements);
488         }
489
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);
494
495         // Create sparse image
496         const Unique<VkImage> imageSparse(createImage(deviceInterface, getDevice(), &imageSparseInfo));
497
498         // Create sparse image memory bind semaphore
499         const Unique<VkSemaphore> memoryBindSemaphore(createSemaphore(deviceInterface, getDevice()));
500
501         std::vector<VkSparseImageMemoryRequirements> sparseMemoryRequirements;
502
503         deUint32        imageSparseSizeInBytes  = 0;
504         deUint32        imageSizeInPixels               = 0;
505
506         for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
507         {
508                 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
509                 {
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;
512                 }
513         }
514
515         residencyReferenceData.assign(imageSizeInPixels, MEMORY_BLOCK_NOT_BOUND_VALUE);
516
517         {
518                 // Get sparse image general memory requirements
519                 const VkMemoryRequirements                              imageMemoryRequirements = getImageMemoryRequirements(deviceInterface, getDevice(), *imageSparse);
520
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");
524
525                 DE_ASSERT((imageMemoryRequirements.size % imageMemoryRequirements.alignment) == 0);
526
527                 const deUint32                                                  memoryType                              = findMatchingMemoryType(instance, physicalDevice, imageMemoryRequirements, MemoryRequirement::Any);
528
529                 if (memoryType == NO_MATCH_FOUND)
530                         return tcu::TestStatus::fail("No matching memory type found");
531
532                 // Get sparse image sparse memory requirements
533                 sparseMemoryRequirements = getImageSparseMemoryRequirements(deviceInterface, getDevice(), *imageSparse);
534
535                 DE_ASSERT(sparseMemoryRequirements.size() != 0);
536
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;
541
542                 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
543                 {
544                         const VkImageAspectFlags                aspect                          = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
545                         const deUint32                                  aspectIndex                     = getSparseAspectRequirementsIndex(sparseMemoryRequirements, aspect);
546
547                         if (aspectIndex == NO_MATCH_FOUND)
548                                 TCU_THROW(NotSupportedError, "Not supported image aspect");
549
550                         VkSparseImageMemoryRequirements aspectRequirements      = sparseMemoryRequirements[aspectIndex];
551
552                         DE_ASSERT((aspectRequirements.imageMipTailSize % imageMemoryRequirements.alignment) == 0);
553
554                         VkExtent3D                                              imageGranularity        = aspectRequirements.formatProperties.imageGranularity;
555
556                         // Bind memory for each mipmap level
557                         for (deUint32 mipmapNdx = 0; mipmapNdx < aspectRequirements.imageMipTailFirstLod; ++mipmapNdx)
558                         {
559                                 const deUint32 mipLevelSizeInPixels = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx) / formatDescription.planes[planeNdx].elementSizeBytes;
560
561                                 if (mipmapNdx % MEMORY_BLOCK_TYPE_COUNT == MEMORY_BLOCK_NOT_BOUND)
562                                 {
563                                         pixelOffset += mipLevelSizeInPixels;
564                                         continue;
565                                 }
566
567                                 for (deUint32 pixelNdx = 0u; pixelNdx < mipLevelSizeInPixels; ++pixelNdx)
568                                 {
569                                         residencyReferenceData[pixelOffset + pixelNdx] = MEMORY_BLOCK_BOUND_VALUE;
570                                 }
571
572                                 pixelOffset += mipLevelSizeInPixels;
573
574                                 for (deUint32 layerNdx = 0; layerNdx < imageSparseInfo.arrayLayers; ++layerNdx)
575                                 {
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 };
580
581                                         const VkSparseImageMemoryBind imageMemoryBind = makeSparseImageMemoryBind(deviceInterface, getDevice(),
582                                                 imageMemoryRequirements.alignment * numSparseBlocks, memoryType, subresource, makeOffset3D(0u, 0u, 0u), mipExtent);
583
584                                         deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
585
586                                         imageResidencyMemoryBinds.push_back(imageMemoryBind);
587                                 }
588                         }
589
590                         if (aspectRequirements.imageMipTailFirstLod < imageSparseInfo.mipLevels)
591                         {
592                                 if (aspectRequirements.formatProperties.flags & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT)
593                                 {
594                                         const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
595                                                 aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset);
596
597                                         deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
598
599                                         imageMipTailBinds.push_back(imageMipTailMemoryBind);
600                                 }
601                                 else
602                                 {
603                                         for (deUint32 layerNdx = 0; layerNdx < imageSparseInfo.arrayLayers; ++layerNdx)
604                                         {
605                                                 const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
606                                                         aspectRequirements.imageMipTailSize, memoryType, aspectRequirements.imageMipTailOffset + layerNdx * aspectRequirements.imageMipTailStride);
607
608                                                 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
609
610                                                 imageMipTailBinds.push_back(imageMipTailMemoryBind);
611                                         }
612                                 }
613
614                                 for (deUint32 pixelNdx = pixelOffset; pixelNdx < residencyReferenceData.size(); ++pixelNdx)
615                                 {
616                                         residencyReferenceData[pixelNdx] = MEMORY_BLOCK_BOUND_VALUE;
617                                 }
618                         }
619                 }
620
621                 // Metadata
622                 if (metadataAspectIndex != NO_MATCH_FOUND)
623                 {
624                         const VkSparseImageMemoryRequirements metadataAspectRequirements = sparseMemoryRequirements[metadataAspectIndex];
625
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)
628                         {
629                                 const VkSparseMemoryBind imageMipTailMemoryBind = makeSparseMemoryBind(deviceInterface, getDevice(),
630                                         metadataAspectRequirements.imageMipTailSize, memoryType,
631                                         metadataAspectRequirements.imageMipTailOffset + bindNdx * metadataAspectRequirements.imageMipTailStride,
632                                         VK_SPARSE_MEMORY_BIND_METADATA_BIT);
633
634                                 deviceMemUniquePtrVec.push_back(makeVkSharedPtr(Move<VkDeviceMemory>(check<VkDeviceMemory>(imageMipTailMemoryBind.memory), Deleter<VkDeviceMemory>(deviceInterface, getDevice(), DE_NULL))));
635
636                                 imageMipTailBinds.push_back(imageMipTailMemoryBind);
637                         }
638                 }
639
640                 VkBindSparseInfo bindSparseInfo =
641                 {
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;
654                 };
655
656                 VkSparseImageMemoryBindInfo                     imageResidencyBindInfo;
657                 VkSparseImageOpaqueMemoryBindInfo       imageMipTailBindInfo;
658
659                 if (imageResidencyMemoryBinds.size() > 0)
660                 {
661                         imageResidencyBindInfo.image            = *imageSparse;
662                         imageResidencyBindInfo.bindCount        = static_cast<deUint32>(imageResidencyMemoryBinds.size());
663                         imageResidencyBindInfo.pBinds           = imageResidencyMemoryBinds.data();
664
665                         bindSparseInfo.imageBindCount           = 1u;
666                         bindSparseInfo.pImageBinds                      = &imageResidencyBindInfo;
667                 }
668
669                 if (imageMipTailBinds.size() > 0)
670                 {
671                         imageMipTailBindInfo.image                      = *imageSparse;
672                         imageMipTailBindInfo.bindCount          = static_cast<deUint32>(imageMipTailBinds.size());
673                         imageMipTailBindInfo.pBinds                     = imageMipTailBinds.data();
674
675                         bindSparseInfo.imageOpaqueBindCount = 1u;
676                         bindSparseInfo.pImageOpaqueBinds        = &imageMipTailBindInfo;
677                 }
678
679                 // Submit sparse bind commands for execution
680                 VK_CHECK(deviceInterface.queueBindSparse(sparseQueue.queueHandle, 1u, &bindSparseInfo, DE_NULL));
681         }
682
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;
699
700         if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
701         {
702                 imageTexelsInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
703         }
704
705         const Unique<VkImage>                   imageTexels                     (createImage(deviceInterface, getDevice(), &imageTexelsInfo));
706         const de::UniquePtr<Allocation> imageTexelsAlloc        (bindImage(deviceInterface, getDevice(), getAllocator(), *imageTexels, MemoryRequirement::Any));
707
708         // Create image to store residency info copied from sparse image
709         imageResidencyInfo                      = imageTexelsInfo;
710         imageResidencyInfo.format       = mapTextureFormat(m_residencyFormat);
711
712         const Unique<VkImage>                   imageResidency          (createImage(deviceInterface, getDevice(), &imageResidencyInfo));
713         const de::UniquePtr<Allocation> imageResidencyAlloc     (bindImage(deviceInterface, getDevice(), getAllocator(), *imageResidency, MemoryRequirement::Any));
714
715         std::vector <VkBufferImageCopy> bufferImageSparseCopy(formatDescription.numPlanes * imageSparseInfo.mipLevels);
716
717         {
718                 deUint32 bufferOffset = 0u;
719                 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
720                 {
721                         const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
722
723                         for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
724                         {
725                                 bufferImageSparseCopy[planeNdx*imageSparseInfo.mipLevels + mipmapNdx] =
726                                 {
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;
733                                 };
734                                 bufferOffset += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
735                         }
736                 }
737         }
738
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));
742
743         // Start recording commands
744         beginCommandBuffer(deviceInterface, *commandBuffer);
745
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));
750
751         // Fill input buffer with reference data
752         std::vector<deUint8> referenceData(imageSparseSizeInBytes);
753
754         for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
755         {
756                 for (deUint32 mipmapNdx = 0u; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
757                 {
758                         const deUint32 mipLevelSizeinBytes      = getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, formatDescription, planeNdx, mipmapNdx);
759                         const deUint32 bufferOffset                     = static_cast<deUint32>(bufferImageSparseCopy[mipmapNdx].bufferOffset);
760
761                         if (formatIsR64(m_format) &&
762                                 (m_function == SPARSE_SAMPLE_EXPLICIT_LOD || m_function == SPARSE_SAMPLE_IMPLICIT_LOD || m_function == SPARSE_GATHER))
763                         {
764                                 for (deUint32 byteNdx = 0u; byteNdx < mipLevelSizeinBytes/8; byteNdx += 8)
765                                 {
766                                         void* prtData = &referenceData[bufferOffset + byteNdx];
767                                         *(static_cast<deUint64*>(prtData)) = (deUint64)((mipmapNdx + byteNdx) % 0x0FFFFFFF);
768                                 }
769                         }
770                         else
771                         {
772                                 for (deUint32 byteNdx = 0u; byteNdx < mipLevelSizeinBytes; ++byteNdx)
773                                 {
774                                         referenceData[bufferOffset + byteNdx] = (deUint8)( (mipmapNdx + byteNdx) % 127u );
775                                 }
776                         }
777                 }
778         }
779
780         deMemcpy(inputBufferAlloc->getHostPtr(), referenceData.data(), imageSparseSizeInBytes);
781         flushAlloc(deviceInterface, getDevice(), *inputBufferAlloc);
782
783         {
784                 // Prepare input buffer for data transfer operation
785                 const VkBufferMemoryBarrier inputBufferBarrier = makeBufferMemoryBarrier
786                 (
787                         VK_ACCESS_HOST_WRITE_BIT,
788                         VK_ACCESS_TRANSFER_READ_BIT,
789                         *inputBuffer,
790                         0u,
791                         imageSparseSizeInBytes
792                 );
793
794                 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 1u, &inputBufferBarrier, 0u, DE_NULL);
795         }
796
797         {
798                 // Prepare sparse image for data transfer operation
799                 std::vector<VkImageMemoryBarrier> imageSparseTransferDstBarriers;
800                 for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
801                 {
802                         const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
803
804                         imageSparseTransferDstBarriers.emplace_back(makeImageMemoryBarrier
805                         (
806                                 0u,
807                                 VK_ACCESS_TRANSFER_WRITE_BIT,
808                                 VK_IMAGE_LAYOUT_UNDEFINED,
809                                 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
810                                 *imageSparse,
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
814                         ));
815                 }
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());
817         }
818
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());
821
822         recordCommands(*commandBuffer, imageSparseInfo, *imageSparse, *imageTexels, *imageResidency);
823
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));
827
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());
830
831         const deUint32                          imageResidencySizeInBytes = getImageSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_residencyFormat, imageSparseInfo.mipLevels, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
832
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));
836
837         // Copy data from residency image to buffer
838         std::vector <VkBufferImageCopy> bufferImageResidencyCopy(formatDescription.numPlanes * imageSparseInfo.mipLevels);
839
840         {
841                 deUint32 bufferOffset = 0u;
842                 for (deUint32 planeNdx = 0u; planeNdx < formatDescription.numPlanes; ++planeNdx)
843                 {
844                         const VkImageAspectFlags aspect = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
845
846                         for (deUint32 mipmapNdx = 0u; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
847                         {
848                                 bufferImageResidencyCopy[planeNdx * imageSparseInfo.mipLevels + mipmapNdx] =
849                                 {
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;
856                                 };
857                                 bufferOffset += getImageMipLevelSizeInBytes(imageSparseInfo.extent, imageSparseInfo.arrayLayers, m_residencyFormat, mipmapNdx, BUFFER_IMAGE_COPY_OFFSET_GRANULARITY);
858                         }
859                 }
860         }
861
862         deviceInterface.cmdCopyImageToBuffer(*commandBuffer, *imageResidency, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *bufferResidency, static_cast<deUint32>(bufferImageResidencyCopy.size()), bufferImageResidencyCopy.data());
863
864         {
865                 VkBufferMemoryBarrier bufferOutputHostReadBarriers[2];
866
867                 bufferOutputHostReadBarriers[0] = makeBufferMemoryBarrier
868                 (
869                         VK_ACCESS_TRANSFER_WRITE_BIT,
870                         VK_ACCESS_HOST_READ_BIT,
871                         *bufferTexels,
872                         0u,
873                         imageSparseSizeInBytes
874                 );
875
876                 bufferOutputHostReadBarriers[1] = makeBufferMemoryBarrier
877                 (
878                         VK_ACCESS_TRANSFER_WRITE_BIT,
879                         VK_ACCESS_HOST_READ_BIT,
880                         *bufferResidency,
881                         0u,
882                         imageResidencySizeInBytes
883                 );
884
885                 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 2u, bufferOutputHostReadBarriers, 0u, DE_NULL);
886         }
887
888         // End recording commands
889         endCommandBuffer(deviceInterface, *commandBuffer);
890
891         const VkPipelineStageFlags stageBits[] = { VK_PIPELINE_STAGE_TRANSFER_BIT };
892
893         // Submit commands for execution and wait for completion
894         submitCommandsAndWait(deviceInterface, getDevice(), extractQueue.queueHandle, *commandBuffer, 1u, &memoryBindSemaphore.get(), stageBits);
895
896         // Wait for sparse queue to become idle
897         deviceInterface.queueWaitIdle(sparseQueue.queueHandle);
898
899         // Retrieve data from residency buffer to host memory
900         invalidateAlloc(deviceInterface, getDevice(), *bufferResidencyAlloc);
901
902         const deUint32* bufferResidencyData = static_cast<const deUint32*>(bufferResidencyAlloc->getHostPtr());
903
904         deUint32 pixelOffsetNotAligned = 0u;
905         for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
906         {
907                 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
908                 {
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);
911
912                         if (deMemCmp(&bufferResidencyData[pixelOffsetAligned], &residencyReferenceData[pixelOffsetNotAligned], mipLevelSizeInBytes) != 0)
913                                 return tcu::TestStatus::fail("Failed");
914
915                         pixelOffsetNotAligned += mipLevelSizeInBytes / tcu::getPixelSize(m_residencyFormat);
916                 }
917 }
918         // Retrieve data from texels buffer to host memory
919         invalidateAlloc(deviceInterface, getDevice(), *bufferTexelsAlloc);
920
921         const deUint8* bufferTexelsData = static_cast<const deUint8*>(bufferTexelsAlloc->getHostPtr());
922
923         for (deUint32 planeNdx = 0; planeNdx < formatDescription.numPlanes; ++planeNdx)
924         {
925                 const VkImageAspectFlags        aspect          = (formatDescription.numPlanes > 1) ? getPlaneAspect(planeNdx) : VK_IMAGE_ASPECT_COLOR_BIT;
926                 const deUint32                          aspectIndex     = getSparseAspectRequirementsIndex(sparseMemoryRequirements, aspect);
927
928                 if (aspectIndex == NO_MATCH_FOUND)
929                         TCU_THROW(NotSupportedError, "Not supported image aspect");
930
931                 VkSparseImageMemoryRequirements aspectRequirements      = sparseMemoryRequirements[aspectIndex];
932
933                 for (deUint32 mipmapNdx = 0; mipmapNdx < imageSparseInfo.mipLevels; ++mipmapNdx)
934                 {
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);
937
938                         if (mipmapNdx < aspectRequirements.imageMipTailFirstLod)
939                         {
940                                 if (mipmapNdx % MEMORY_BLOCK_TYPE_COUNT == MEMORY_BLOCK_BOUND)
941                                 {
942                                         if (deMemCmp(&bufferTexelsData[bufferOffset], &referenceData[bufferOffset], mipLevelSizeInBytes) != 0)
943                                                 return tcu::TestStatus::fail("Failed");
944                                 }
945                                 else if (getPhysicalDeviceProperties(instance, physicalDevice).sparseProperties.residencyNonResidentStrict)
946                                 {
947                                         std::vector<deUint8> zeroData;
948                                         zeroData.assign(mipLevelSizeInBytes, 0u);
949
950                                         if (deMemCmp(&bufferTexelsData[bufferOffset], zeroData.data(), mipLevelSizeInBytes) != 0)
951                                                 return tcu::TestStatus::fail("Failed");
952                                 }
953                         }
954                         else
955                         {
956                                 if (deMemCmp(&bufferTexelsData[bufferOffset], &referenceData[bufferOffset], mipLevelSizeInBytes) != 0)
957                                         return tcu::TestStatus::fail("Failed");
958                         }
959                 }
960         }
961
962         return tcu::TestStatus::pass("Passed");
963 }
964
965 } // sparse
966 } // vkt