154c1b244c3d914b7ebb6075c4e5e24f173cbbf2
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / memory / vktMemoryRequirementsTests.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
21  * \brief Buffer and image memory requirements tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktMemoryRequirementsTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vktTestGroupUtil.hpp"
27
28 #include "vkDefs.hpp"
29 #include "vkRef.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkStrUtil.hpp"
34 #include "vkTypeUtil.hpp"
35
36 #include "deUniquePtr.hpp"
37 #include "deStringUtil.hpp"
38
39 #include "tcuResultCollector.hpp"
40 #include "tcuTestLog.hpp"
41
42 namespace vkt
43 {
44 namespace memory
45 {
46 namespace
47 {
48 using namespace vk;
49 using de::MovePtr;
50
51 Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize size, const VkBufferCreateFlags flags, const VkBufferUsageFlags usage)
52 {
53         const VkBufferCreateInfo createInfo =
54         {
55                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,           // VkStructureType        sType;
56                 DE_NULL,                                                                        // const void*            pNext;
57                 flags,                                                                          // VkBufferCreateFlags    flags;
58                 size,                                                                           // VkDeviceSize           size;
59                 usage,                                                                          // VkBufferUsageFlags     usage;
60                 VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode          sharingMode;
61                 0u,                                                                                     // uint32_t               queueFamilyIndexCount;
62                 DE_NULL,                                                                        // const uint32_t*        pQueueFamilyIndices;
63         };
64         return createBuffer(vk, device, &createInfo);
65 }
66
67 //! Get an index of each set bit, starting from the least significant bit.
68 std::vector<deUint32> bitsToIndices (deUint32 bits)
69 {
70         std::vector<deUint32> indices;
71         for (deUint32 i = 0u; bits != 0u; ++i, bits >>= 1)
72         {
73                 if (bits & 1u)
74                         indices.push_back(i);
75         }
76         return indices;
77 }
78
79 VkMemoryRequirements getBufferMemoryRequirements (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize size, const VkBufferCreateFlags flags, const VkBufferUsageFlags usage)
80 {
81         const Unique<VkBuffer> buffer(makeBuffer(vk, device, size, flags, usage));
82         return getBufferMemoryRequirements(vk, device, *buffer);
83 }
84
85 template<typename T>
86 T nextEnum (T value)
87 {
88         return static_cast<T>(static_cast<deUint32>(value) + 1);
89 }
90
91 template<typename T>
92 T nextFlag (T value)
93 {
94         if (value)
95                 return static_cast<T>(static_cast<deUint32>(value) << 1);
96         else
97                 return static_cast<T>(1);
98 }
99
100 template<typename T>
101 T nextFlagExcluding (T value, T excludedFlags)
102 {
103         deUint32 tmp = static_cast<deUint32>(value);
104         while ((tmp = nextFlag(tmp)) & static_cast<deUint32>(excludedFlags));
105         return static_cast<T>(tmp);
106 }
107
108 void requireBufferSparseFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkBufferCreateFlags flags)
109 {
110         const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
111
112         if ((flags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && !features.sparseBinding)
113                 TCU_THROW(NotSupportedError, "Feature not supported: sparseBinding");
114
115         if ((flags & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && !features.sparseResidencyBuffer)
116                 TCU_THROW(NotSupportedError, "Feature not supported: sparseResidencyBuffer");
117
118         if ((flags & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && !features.sparseResidencyAliased)
119                 TCU_THROW(NotSupportedError, "Feature not supported: sparseResidencyAliased");
120 }
121
122 void verifyBufferRequirements (tcu::ResultCollector&                                    result,
123                                                            const VkPhysicalDeviceMemoryProperties&      deviceMemoryProperties,
124                                                            const VkMemoryRequirements&                          requirements,
125                                                            const VkMemoryRequirements&                          allUsageFlagsRequirements,
126                                                            const VkPhysicalDeviceLimits&                        limits,
127                                                            const VkBufferCreateFlags                            bufferFlags,
128                                                            const VkBufferUsageFlags                                     usage)
129 {
130         if (result.check(requirements.memoryTypeBits != 0, "VkMemoryRequirements memoryTypeBits has no bits set"))
131         {
132                 typedef std::vector<deUint32>::const_iterator   IndexIterator;
133                 const std::vector<deUint32>                                             usedMemoryTypeIndices                   = bitsToIndices(requirements.memoryTypeBits);
134                 bool                                                                                    deviceLocalMemoryFound                  = false;
135                 bool                                                                                    hostVisibleCoherentMemoryFound  = false;
136
137                 for (IndexIterator memoryTypeNdx = usedMemoryTypeIndices.begin(); memoryTypeNdx != usedMemoryTypeIndices.end(); ++memoryTypeNdx)
138                 {
139                         if (*memoryTypeNdx >= deviceMemoryProperties.memoryTypeCount)
140                         {
141                                 result.fail("VkMemoryRequirements memoryTypeBits contains bits for non-existing memory types");
142                                 continue;
143                         }
144
145                         const VkMemoryPropertyFlags     memoryPropertyFlags = deviceMemoryProperties.memoryTypes[*memoryTypeNdx].propertyFlags;
146
147                         if (memoryPropertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
148                                 deviceLocalMemoryFound = true;
149
150                         if (memoryPropertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
151                                 hostVisibleCoherentMemoryFound = true;
152
153                         result.check((memoryPropertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) == 0u,
154                                 "Memory type includes VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT");
155                 }
156
157                 result.check(deIsPowerOfTwo64(static_cast<deUint64>(requirements.alignment)) == DE_TRUE,
158                         "VkMemoryRequirements alignment isn't power of two");
159
160                 if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT))
161                 {
162                         result.check(requirements.alignment >= limits.minTexelBufferOffsetAlignment,
163                                 "VkMemoryRequirements alignment doesn't respect minTexelBufferOffsetAlignment");
164                 }
165
166                 if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)
167                 {
168                         result.check(requirements.alignment >= limits.minUniformBufferOffsetAlignment,
169                                 "VkMemoryRequirements alignment doesn't respect minUniformBufferOffsetAlignment");
170                 }
171
172                 if (usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
173                 {
174                         result.check(requirements.alignment >= limits.minStorageBufferOffsetAlignment,
175                                 "VkMemoryRequirements alignment doesn't respect minStorageBufferOffsetAlignment");
176                 }
177
178                 result.check(deviceLocalMemoryFound,
179                         "None of the required memory types included VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT");
180
181                 result.check((bufferFlags & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) || hostVisibleCoherentMemoryFound,
182                         "Required memory type doesn't include VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT");
183
184                 result.check((requirements.memoryTypeBits & allUsageFlagsRequirements.memoryTypeBits) == allUsageFlagsRequirements.memoryTypeBits,
185                         "Memory type bits aren't a superset of memory type bits for all usage flags combined");
186         }
187 }
188
189 tcu::TestStatus testBuffer (Context& context, const VkBufferCreateFlags bufferFlags)
190 {
191         const DeviceInterface&                                  vk                                                      = context.getDeviceInterface();
192         const InstanceInterface&                                vki                                                     = context.getInstanceInterface();
193         const VkDevice                                                  device                                          = context.getDevice();
194         const VkPhysicalDevice                                  physDevice                                      = context.getPhysicalDevice();
195
196         requireBufferSparseFeatures(vki, physDevice, bufferFlags);
197
198         const VkPhysicalDeviceMemoryProperties  memoryProperties                        = getPhysicalDeviceMemoryProperties(vki, physDevice);
199         const VkPhysicalDeviceLimits                    limits                                          = getPhysicalDeviceProperties(vki, physDevice).limits;
200         const VkBufferUsageFlags                                allUsageFlags                           = static_cast<VkBufferUsageFlags>((VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT << 1) - 1);
201         const VkMemoryRequirements                              allUsageFlagsRequirements       = getBufferMemoryRequirements(vk, device, 1024, bufferFlags, allUsageFlags); // doesn't depend on size
202         tcu::TestLog&                                                   log                                                     = context.getTestContext().getLog();
203         bool                                                                    allPass                                         = true;
204
205         const VkDeviceSize sizeCases[] =
206         {
207                 1        * 1024,
208                 8    * 1024,
209                 64   * 1024,
210                 1024 * 1024,
211         };
212
213         for (VkBufferUsageFlags usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; usage <= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; usage = nextFlag(usage))
214         {
215                 deUint32                previousMemoryTypeBits  = 0u;
216                 VkDeviceSize    previousAlignment               = 0u;
217
218                 log << tcu::TestLog::Message << "Verify a buffer with usage flags: " << de::toString(getBufferUsageFlagsStr(usage)) << tcu::TestLog::EndMessage;
219
220                 for (const VkDeviceSize* pSize = sizeCases; pSize < sizeCases + DE_LENGTH_OF_ARRAY(sizeCases); ++pSize)
221                 {
222                         log << tcu::TestLog::Message << "- size " << *pSize << " bytes" << tcu::TestLog::EndMessage;
223
224                         const VkMemoryRequirements      requirements    = getBufferMemoryRequirements(vk, device, *pSize, bufferFlags, usage);
225                         tcu::ResultCollector            result                  (log, "ERROR: ");
226
227                         // Check:
228                         // - requirements for a particular buffer usage
229                         // - memoryTypeBits are a subset of bits for requirements with all usage flags combined
230                         verifyBufferRequirements(result, memoryProperties, requirements, allUsageFlagsRequirements, limits, bufferFlags, usage);
231
232                         // Check that for the same usage and create flags:
233                         // - memoryTypeBits are the same
234                         // - alignment is the same
235                         if (pSize > sizeCases)
236                         {
237                                 result.check(requirements.memoryTypeBits == previousMemoryTypeBits,
238                                         "memoryTypeBits differ from the ones in the previous buffer size");
239
240                                 result.check(requirements.alignment == previousAlignment,
241                                         "alignment differs from the one in the previous buffer size");
242                         }
243
244                         if (result.getResult() != QP_TEST_RESULT_PASS)
245                                 allPass = false;
246
247                         previousMemoryTypeBits  = requirements.memoryTypeBits;
248                         previousAlignment               = requirements.alignment;
249                 }
250
251                 if (!allPass)
252                         break;
253         }
254
255         return allPass ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Some memory requirements were incorrect");
256 }
257
258 void requireImageSparseFeatures (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkImageCreateFlags createFlags)
259 {
260         const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
261
262         if ((createFlags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) && !features.sparseBinding)
263                 TCU_THROW(NotSupportedError, "Feature not supported: sparseBinding");
264
265         if ((createFlags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) && !(features.sparseResidencyImage2D || features.sparseResidencyImage3D))
266                 TCU_THROW(NotSupportedError, "Feature not supported: sparseResidencyImage (2D and 3D)");
267
268         if ((createFlags & VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) && !features.sparseResidencyAliased)
269                 TCU_THROW(NotSupportedError, "Feature not supported: sparseResidencyAliased");
270 }
271
272 bool imageUsageMatchesFormatFeatures (const VkImageUsageFlags usage, const VkFormatFeatureFlags featureFlags)
273 {
274         if ((usage & VK_IMAGE_USAGE_SAMPLED_BIT) && (featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT))
275                 return true;
276         if ((usage & VK_IMAGE_USAGE_STORAGE_BIT) && (featureFlags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
277                 return true;
278         if ((usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) && (featureFlags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
279                 return true;
280         if ((usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && (featureFlags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT))
281                 return true;
282
283         return false;
284 }
285
286 //! This catches both invalid as well as legal but unsupported combinations of image parameters
287 bool isImageSupported (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const VkImageCreateInfo& info)
288 {
289         DE_ASSERT(info.extent.width >= 1u && info.extent.height >= 1u && info.extent.depth >= 1u);
290
291         if (info.imageType == VK_IMAGE_TYPE_1D)
292         {
293                 DE_ASSERT(info.extent.height == 1u && info.extent.depth == 1u);
294         }
295         else if (info.imageType == VK_IMAGE_TYPE_2D)
296         {
297                 DE_ASSERT(info.extent.depth == 1u);
298
299                 if (info.flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
300                 {
301                         DE_ASSERT(info.extent.width == info.extent.height);
302                         DE_ASSERT(info.arrayLayers >= 6u && (info.arrayLayers % 6u) == 0u);
303                 }
304         }
305
306         if ((info.flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) && info.imageType != VK_IMAGE_TYPE_2D)
307                 return false;
308
309         if ((info.samples != VK_SAMPLE_COUNT_1_BIT) &&
310                 (info.imageType != VK_IMAGE_TYPE_2D || (info.flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) || info.tiling != VK_IMAGE_TILING_OPTIMAL || info.mipLevels > 1u))
311                 return false;
312
313         if ((info.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) &&
314                 (info.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) == 0u)
315                 return false;
316
317         const VkPhysicalDeviceFeatures features = getPhysicalDeviceFeatures(vki, physDevice);
318
319         if (info.flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT)
320         {
321                 DE_ASSERT(info.tiling == VK_IMAGE_TILING_OPTIMAL);
322
323                 if (info.imageType == VK_IMAGE_TYPE_2D && !features.sparseResidencyImage2D)
324                         return false;
325                 if (info.imageType == VK_IMAGE_TYPE_3D && !features.sparseResidencyImage3D)
326                         return false;
327                 if (info.samples == VK_SAMPLE_COUNT_2_BIT && !features.sparseResidency2Samples)
328                         return false;
329                 if (info.samples == VK_SAMPLE_COUNT_4_BIT && !features.sparseResidency4Samples)
330                         return false;
331                 if (info.samples == VK_SAMPLE_COUNT_8_BIT && !features.sparseResidency8Samples)
332                         return false;
333                 if (info.samples == VK_SAMPLE_COUNT_16_BIT && !features.sparseResidency16Samples)
334                         return false;
335                 if (info.samples == VK_SAMPLE_COUNT_32_BIT || info.samples == VK_SAMPLE_COUNT_64_BIT)
336                         return false;
337         }
338
339         if (info.samples != VK_SAMPLE_COUNT_1_BIT && (info.usage & VK_IMAGE_USAGE_STORAGE_BIT) && !features.shaderStorageImageMultisample)
340                 return false;
341
342         switch (info.format)
343         {
344                 case VK_FORMAT_BC1_RGB_UNORM_BLOCK:
345                 case VK_FORMAT_BC1_RGB_SRGB_BLOCK:
346                 case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
347                 case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
348                 case VK_FORMAT_BC2_UNORM_BLOCK:
349                 case VK_FORMAT_BC2_SRGB_BLOCK:
350                 case VK_FORMAT_BC3_UNORM_BLOCK:
351                 case VK_FORMAT_BC3_SRGB_BLOCK:
352                 case VK_FORMAT_BC4_UNORM_BLOCK:
353                 case VK_FORMAT_BC4_SNORM_BLOCK:
354                 case VK_FORMAT_BC5_UNORM_BLOCK:
355                 case VK_FORMAT_BC5_SNORM_BLOCK:
356                 case VK_FORMAT_BC6H_UFLOAT_BLOCK:
357                 case VK_FORMAT_BC6H_SFLOAT_BLOCK:
358                 case VK_FORMAT_BC7_UNORM_BLOCK:
359                 case VK_FORMAT_BC7_SRGB_BLOCK:
360                         if (!features.textureCompressionBC)
361                                 return false;
362                         break;
363
364                 case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
365                 case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
366                 case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
367                 case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
368                 case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
369                 case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
370                 case VK_FORMAT_EAC_R11_UNORM_BLOCK:
371                 case VK_FORMAT_EAC_R11_SNORM_BLOCK:
372                 case VK_FORMAT_EAC_R11G11_UNORM_BLOCK:
373                 case VK_FORMAT_EAC_R11G11_SNORM_BLOCK:
374                         if (!features.textureCompressionETC2)
375                                 return false;
376                         break;
377
378                 case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
379                 case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
380                 case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
381                 case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
382                 case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
383                 case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
384                 case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
385                 case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
386                 case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
387                 case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
388                 case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
389                 case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
390                 case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
391                 case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
392                 case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
393                 case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
394                 case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
395                 case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
396                 case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
397                 case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
398                 case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
399                 case VK_FORMAT_ASTC_10x8_SRGB_BLOCK:
400                 case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
401                 case VK_FORMAT_ASTC_10x10_SRGB_BLOCK:
402                 case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
403                 case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
404                 case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
405                 case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
406                         if (!features.textureCompressionASTC_LDR)
407                                 return false;
408                         break;
409
410                 default:
411                         break;
412         }
413
414         const VkFormatProperties        formatProperties        = getPhysicalDeviceFormatProperties(vki, physDevice, info.format);
415         const VkFormatFeatureFlags      formatFeatures          = (info.tiling == VK_IMAGE_TILING_LINEAR ? formatProperties.linearTilingFeatures
416                                                                                                                                                                                          : formatProperties.optimalTilingFeatures);
417
418         if (!imageUsageMatchesFormatFeatures(info.usage, formatFeatures))
419                 return false;
420
421         VkImageFormatProperties         imageFormatProperties;
422         const VkResult                          result                          = vki.getPhysicalDeviceImageFormatProperties(
423                                                                                                                 physDevice, info.format, info.imageType, info.tiling, info.usage, info.flags, &imageFormatProperties);
424
425         if (result == VK_SUCCESS)
426         {
427                 if (info.arrayLayers > imageFormatProperties.maxArrayLayers)
428                         return false;
429                 if (info.mipLevels > imageFormatProperties.maxMipLevels)
430                         return false;
431                 if ((info.samples & imageFormatProperties.sampleCounts) == 0u)
432                         return false;
433         }
434
435         return result == VK_SUCCESS;
436 }
437
438 VkExtent3D makeExtentForImage (const VkImageType imageType)
439 {
440         VkExtent3D extent = { 64u, 64u, 4u };
441
442         if (imageType == VK_IMAGE_TYPE_1D)
443                 extent.height = extent.depth = 1u;
444         else if (imageType == VK_IMAGE_TYPE_2D)
445                 extent.depth = 1u;
446
447         return extent;
448 }
449
450 bool isFormatMatchingAspect (const VkFormat format, const VkImageAspectFlags aspect)
451 {
452         DE_ASSERT(aspect == VK_IMAGE_ASPECT_COLOR_BIT || aspect == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
453
454         // D/S formats are laid out next to each other in the enum
455         const bool isDepthStencilFormat = (format >= VK_FORMAT_D16_UNORM && format <= VK_FORMAT_D32_SFLOAT_S8_UINT);
456
457         return (aspect == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == isDepthStencilFormat;
458 }
459
460 void verifyImageRequirements (tcu::ResultCollector&                                             result,
461                                                           const VkPhysicalDeviceMemoryProperties&       deviceMemoryProperties,
462                                                           const VkMemoryRequirements&                           requirements,
463                                                           const VkImageCreateInfo&                                      imageInfo)
464 {
465         if (result.check(requirements.memoryTypeBits != 0, "VkMemoryRequirements memoryTypeBits has no bits set"))
466         {
467                 typedef std::vector<deUint32>::const_iterator   IndexIterator;
468                 const std::vector<deUint32>                                             usedMemoryTypeIndices                   = bitsToIndices(requirements.memoryTypeBits);
469                 bool                                                                                    deviceLocalMemoryFound                  = false;
470                 bool                                                                                    hostVisibleCoherentMemoryFound  = false;
471
472                 for (IndexIterator memoryTypeNdx = usedMemoryTypeIndices.begin(); memoryTypeNdx != usedMemoryTypeIndices.end(); ++memoryTypeNdx)
473                 {
474                         if (*memoryTypeNdx >= deviceMemoryProperties.memoryTypeCount)
475                         {
476                                 result.fail("VkMemoryRequirements memoryTypeBits contains bits for non-existing memory types");
477                                 continue;
478                         }
479
480                         const VkMemoryPropertyFlags     memoryPropertyFlags = deviceMemoryProperties.memoryTypes[*memoryTypeNdx].propertyFlags;
481
482                         if (memoryPropertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
483                                 deviceLocalMemoryFound = true;
484
485                         if (memoryPropertyFlags & (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
486                                 hostVisibleCoherentMemoryFound = true;
487
488                         if (memoryPropertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
489                         {
490                                 result.check((imageInfo.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0u,
491                                         "Memory type includes VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT for a non-transient attachment image");
492                         }
493                 }
494
495                 result.check(deIsPowerOfTwo64(static_cast<deUint64>(requirements.alignment)) == DE_TRUE,
496                         "VkMemoryRequirements alignment isn't power of two");
497
498                 result.check(deviceLocalMemoryFound,
499                         "None of the required memory types included VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT");
500
501                 result.check(imageInfo.tiling == VK_IMAGE_TILING_OPTIMAL || hostVisibleCoherentMemoryFound,
502                         "Required memory type doesn't include VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT and VK_MEMORY_PROPERTY_HOST_COHERENT_BIT");
503         }
504 }
505
506 std::string getImageInfoString (const VkImageCreateInfo& imageInfo)
507 {
508         std::ostringstream str;
509
510         switch (imageInfo.imageType)
511         {
512                 case VK_IMAGE_TYPE_1D:                  str << "1D "; break;
513                 case VK_IMAGE_TYPE_2D:                  str << "2D "; break;
514                 case VK_IMAGE_TYPE_3D:                  str << "3D "; break;
515                 default:                                                break;
516         }
517
518         switch (imageInfo.tiling)
519         {
520                 case VK_IMAGE_TILING_OPTIMAL:   str << "(optimal) "; break;
521                 case VK_IMAGE_TILING_LINEAR:    str << "(linear) "; break;
522                 default:                                                break;
523         }
524
525         str << "extent:[" << imageInfo.extent.width << ", " << imageInfo.extent.height << ", " << imageInfo.extent.depth << "] ";
526         str << imageInfo.format << " ";
527         str << "samples:" << static_cast<deUint32>(imageInfo.samples) << " ";
528         str << "flags:" << static_cast<deUint32>(imageInfo.flags) << " ";
529         str << "usage:" << static_cast<deUint32>(imageInfo.usage) << " ";
530
531         return str.str();
532 }
533
534 struct ImageParams
535 {
536         VkImageCreateFlags              flags;
537         VkImageTiling                   tiling;
538         bool                                    transient;
539 };
540
541 tcu::TestStatus testImage (Context& context, const ImageParams params)
542 {
543         const DeviceInterface&          vk                              = context.getDeviceInterface();
544         const InstanceInterface&        vki                             = context.getInstanceInterface();
545         const VkDevice                          device                  = context.getDevice();
546         const VkPhysicalDevice          physDevice              = context.getPhysicalDevice();
547         const VkImageCreateFlags        sparseFlags             = VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT;
548         const VkImageUsageFlags         transientFlags  = VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
549
550         requireImageSparseFeatures(vki, physDevice, params.flags);
551
552         const VkPhysicalDeviceMemoryProperties  memoryProperties                = getPhysicalDeviceMemoryProperties(vki, physDevice);
553         const deUint32                                                  notInitializedBits              = ~0u;
554         const VkImageAspectFlags                                colorAspect                             = VK_IMAGE_ASPECT_COLOR_BIT;
555         const VkImageAspectFlags                                depthStencilAspect              = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
556         const VkImageAspectFlags                                allAspects[2]                   = { colorAspect, depthStencilAspect };
557         tcu::TestLog&                                                   log                                             = context.getTestContext().getLog();
558         bool                                                                    allPass                                 = true;
559         deUint32                                                                numCheckedImages                = 0u;
560
561         log << tcu::TestLog::Message << "Verify memory requirements for the following parameter combinations:" << tcu::TestLog::EndMessage;
562
563         for (deUint32 loopAspectNdx = 0u; loopAspectNdx < DE_LENGTH_OF_ARRAY(allAspects); ++loopAspectNdx)
564         {
565                 const VkImageAspectFlags        aspect                                  = allAspects[loopAspectNdx];
566                 deUint32                                        previousMemoryTypeBits  = notInitializedBits;
567
568                 for (VkFormat loopFormat = VK_FORMAT_R4G4_UNORM_PACK8; loopFormat <= VK_FORMAT_ASTC_12x12_SRGB_BLOCK; loopFormat = nextEnum(loopFormat))
569                 if  (isFormatMatchingAspect(loopFormat, aspect))
570                 {
571                         // memoryTypeBits may differ between depth/stencil formats
572                         if (aspect == depthStencilAspect)
573                                 previousMemoryTypeBits = notInitializedBits;
574
575                         for (VkImageType                        loopImageType   = VK_IMAGE_TYPE_1D;                                     loopImageType   != VK_IMAGE_TYPE_LAST;                                  loopImageType   = nextEnum(loopImageType))
576                         for (VkImageCreateFlags         loopCreateFlags = (VkImageCreateFlags)0;                        loopCreateFlags <= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; loopCreateFlags = nextFlagExcluding(loopCreateFlags, sparseFlags))
577                         for (VkImageUsageFlags          loopUsageFlags  = VK_IMAGE_USAGE_TRANSFER_SRC_BIT;      loopUsageFlags  <= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; loopUsageFlags  = nextFlagExcluding(loopUsageFlags, transientFlags))
578                         for (VkSampleCountFlagBits      loopSampleCount = VK_SAMPLE_COUNT_1_BIT;                        loopSampleCount <= VK_SAMPLE_COUNT_16_BIT;                              loopSampleCount = nextFlag(loopSampleCount))
579                         {
580                                 const VkImageCreateFlags        actualCreateFlags       = loopCreateFlags | params.flags;
581                                 const VkImageUsageFlags         actualUsageFlags        = loopUsageFlags  | (params.transient ? VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT : (VkImageUsageFlagBits)0);
582                                 const bool                                      isCube                          = (actualCreateFlags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) != 0u;
583                                 const VkImageCreateInfo         imageInfo                       =
584                                 {
585                                         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,            // VkStructureType          sType;
586                                         DE_NULL,                                                                        // const void*              pNext;
587                                         actualCreateFlags,                                                      // VkImageCreateFlags       flags;
588                                         loopImageType,                                                          // VkImageType              imageType;
589                                         loopFormat,                                                                     // VkFormat                 format;
590                                         makeExtentForImage(loopImageType),                      // VkExtent3D               extent;
591                                         1u,                                                                                     // uint32_t                 mipLevels;
592                                         (isCube ? 6u : 1u),                                                     // uint32_t                 arrayLayers;
593                                         loopSampleCount,                                                        // VkSampleCountFlagBits    samples;
594                                         params.tiling,                                                          // VkImageTiling            tiling;
595                                         actualUsageFlags,                                                       // VkImageUsageFlags        usage;
596                                         VK_SHARING_MODE_EXCLUSIVE,                                      // VkSharingMode            sharingMode;
597                                         0u,                                                                                     // uint32_t                 queueFamilyIndexCount;
598                                         DE_NULL,                                                                        // const uint32_t*          pQueueFamilyIndices;
599                                         VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout            initialLayout;
600                                 };
601
602                                 if (!isImageSupported(vki, physDevice, imageInfo))
603                                         continue;
604
605                                 log << tcu::TestLog::Message << "- " << getImageInfoString(imageInfo) << tcu::TestLog::EndMessage;
606                                 ++numCheckedImages;
607
608                                 const Unique<VkImage>           image                   (createImage(vk, device, &imageInfo));
609                                 const VkMemoryRequirements      requirements    = getImageMemoryRequirements(vk, device, *image);
610                                 tcu::ResultCollector            result                  (log, "ERROR: ");
611
612                                 verifyImageRequirements(result, memoryProperties, requirements, imageInfo);
613
614                                 // For the same tiling, transient usage, and sparse flags, (and format, if D/S) memoryTypeBits must be the same for all images
615                                 result.check((previousMemoryTypeBits == notInitializedBits) || (requirements.memoryTypeBits == previousMemoryTypeBits),
616                                                                 "memoryTypeBits differ from the ones in the previous image configuration");
617
618                                 if (result.getResult() != QP_TEST_RESULT_PASS)
619                                         allPass = false;
620
621                                 previousMemoryTypeBits = requirements.memoryTypeBits;
622                         }
623                 }
624         }
625
626         if (numCheckedImages == 0u)
627                 log << tcu::TestLog::Message << "NOTE: No supported image configurations -- nothing to check" << tcu::TestLog::EndMessage;
628
629         return allPass ? tcu::TestStatus::pass("Pass") : tcu::TestStatus::fail("Some memory requirements were incorrect");
630 }
631
632 void populateTestGroup (tcu::TestCaseGroup* group)
633 {
634         // Buffers
635         {
636                 const struct
637                 {
638                         VkBufferCreateFlags             flags;
639                         const char* const               name;
640                 } bufferCases[] =
641                 {
642                         { (VkBufferCreateFlags)0,                                                                                                                                                                                               "regular"                                       },
643                         { VK_BUFFER_CREATE_SPARSE_BINDING_BIT,                                                                                                                                                                  "sparse"                                        },
644                         { VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,                                                                                  "sparse_residency"                      },
645                         { VK_BUFFER_CREATE_SPARSE_BINDING_BIT                                                                                   | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,  "sparse_aliased"                        },
646                         { VK_BUFFER_CREATE_SPARSE_BINDING_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT   | VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,  "sparse_residency_aliased"      },
647                 };
648
649                 de::MovePtr<tcu::TestCaseGroup> bufferGroup(new tcu::TestCaseGroup(group->getTestContext(), "buffer", ""));
650
651                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bufferCases); ++ndx)
652                         addFunctionCase(bufferGroup.get(), bufferCases[ndx].name, "", testBuffer, bufferCases[ndx].flags);
653
654                 group->addChild(bufferGroup.release());
655         }
656
657         // Images
658         {
659                 const struct
660                 {
661                         VkImageCreateFlags              flags;
662                         bool                                    transient;
663                         const char* const               name;
664                 } imageFlagsCases[] =
665                 {
666                         { (VkImageCreateFlags)0,                                                                                                                                                                                                false,  "regular"                                       },
667                         { (VkImageCreateFlags)0,                                                                                                                                                                                                true,   "transient"                                     },
668                         { VK_IMAGE_CREATE_SPARSE_BINDING_BIT,                                                                                                                                                                   false,  "sparse"                                        },
669                         { VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT,                                                                                    false,  "sparse_residency"                      },
670                         { VK_IMAGE_CREATE_SPARSE_BINDING_BIT                                                                                    | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,   false,  "sparse_aliased"                        },
671                         { VK_IMAGE_CREATE_SPARSE_BINDING_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT             | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT,   false,  "sparse_residency_aliased"      },
672                 };
673
674                 de::MovePtr<tcu::TestCaseGroup> imageGroup(new tcu::TestCaseGroup(group->getTestContext(), "image", ""));
675
676                 for (int flagsNdx = 0; flagsNdx < DE_LENGTH_OF_ARRAY(imageFlagsCases); ++flagsNdx)
677                 for (int tilingNdx = 0; tilingNdx <= 1; ++tilingNdx)
678                 {
679                         ImageParams                     params;
680                         std::ostringstream      caseName;
681
682                         params.flags            =  imageFlagsCases[flagsNdx].flags;
683                         params.transient        =  imageFlagsCases[flagsNdx].transient;
684                         caseName                        << imageFlagsCases[flagsNdx].name;
685
686                         if (tilingNdx != 0)
687                         {
688                                 params.tiling =  VK_IMAGE_TILING_OPTIMAL;
689                                 caseName      << "_tiling_optimal";
690                         }
691                         else
692                         {
693                                 params.tiling =  VK_IMAGE_TILING_LINEAR;
694                                 caseName      << "_tiling_linear";
695                         }
696
697                         if ((params.flags & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) && (params.tiling == VK_IMAGE_TILING_LINEAR))
698                                 continue;
699
700                         addFunctionCase(imageGroup.get(), caseName.str(), "", testImage, params);
701                 }
702
703                 group->addChild(imageGroup.release());
704         }
705 }
706
707 } // anonymous
708
709 tcu::TestCaseGroup* createRequirementsTests (tcu::TestContext& testCtx)
710 {
711         return createTestGroup(testCtx, "requirements", "Buffer and image memory requirements", populateTestGroup);
712 }
713
714 } // memory
715 } // vkt