1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 Google Inc.
6  * Copyright (c) 2018 The Khronos Group Inc.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*--------------------------------------------------------------------*/
21 
22 #include "vktApiMemoryRequirementInvarianceTests.hpp"
23 #include "vktApiBufferAndImageAllocationUtil.hpp"
24 #include "deRandom.h"
25 #include "tcuTestLog.hpp"
26 #include "vkQueryUtil.hpp"
27 #include "vkMemUtil.hpp"
28 #include "vkRefUtil.hpp"
29 #include "vkImageUtil.hpp"
30 
31 namespace vkt
32 {
33 namespace api
34 {
35 
36 using namespace vk;
37 
38 // Number of items to allocate
39 #ifndef CTS_USES_VULKANSC
40 const unsigned int testCycles = 1000u;
41 #else
42 const unsigned int testCycles = 100u;
43 #endif // CTS_USES_VULKANSC
44 
45 // All legal memory combinations (spec chapter 10.2: Device Memory)
46 const unsigned int legalMemoryTypeCount                        = 11u;
47 const MemoryRequirement legalMemoryTypes[legalMemoryTypeCount] = {
48     MemoryRequirement::Any,
49     MemoryRequirement::HostVisible | MemoryRequirement::Coherent,
50     MemoryRequirement::HostVisible | MemoryRequirement::Cached,
51     MemoryRequirement::HostVisible | MemoryRequirement::Cached | MemoryRequirement::Coherent,
52     MemoryRequirement::Local,
53     MemoryRequirement::Local | MemoryRequirement::HostVisible | MemoryRequirement::Coherent,
54     MemoryRequirement::Local | MemoryRequirement::HostVisible | MemoryRequirement::Cached,
55     MemoryRequirement::Local | MemoryRequirement::HostVisible | MemoryRequirement::Cached | MemoryRequirement::Coherent,
56     MemoryRequirement::Local | MemoryRequirement::LazilyAllocated,
57     MemoryRequirement::Protected,
58     MemoryRequirement::Protected | MemoryRequirement::Local};
59 
60 class IObjectAllocator
61 {
62 public:
IObjectAllocator()63     IObjectAllocator()
64     {
65     }
~IObjectAllocator()66     virtual ~IObjectAllocator()
67     {
68     }
69     virtual void allocate(Context &context)   = 0;
70     virtual void deallocate(Context &context) = 0;
71     virtual size_t getSize(Context &context)  = 0;
72 };
73 
74 class BufferAllocator : public IObjectAllocator
75 {
76 public:
77     BufferAllocator(deRandom &random, bool dedicated, std::vector<int> &memoryTypes);
78     virtual ~BufferAllocator();
79     virtual void allocate(Context &context);
80     virtual void deallocate(Context &context);
81     virtual size_t getSize(Context &context);
82 
83 private:
84     bool m_dedicated;
85     Move<VkBuffer> m_buffer;
86     VkDeviceSize m_size;
87     VkBufferUsageFlags m_usage;
88     int m_memoryType;
89     de::MovePtr<Allocation> m_bufferAlloc;
90 };
91 
BufferAllocator(deRandom & random,bool dedicated,std::vector<int> & memoryTypes)92 BufferAllocator::BufferAllocator(deRandom &random, bool dedicated, std::vector<int> &memoryTypes)
93 {
94     // If dedicated allocation is supported, randomly pick it
95     m_dedicated = dedicated && deRandom_getBool(&random);
96     // Random buffer sizes to find potential issues caused by strange alignment
97     m_size = (deRandom_getUint32(&random) % 1024) + 7;
98     // Pick a random usage from the 9 VkBufferUsageFlags.
99     m_usage = 1 << (deRandom_getUint32(&random) % 9);
100     // Pick random memory type from the supported ones
101     m_memoryType = memoryTypes[deRandom_getUint32(&random) % memoryTypes.size()];
102 }
103 
~BufferAllocator()104 BufferAllocator::~BufferAllocator()
105 {
106 }
107 
allocate(Context & context)108 void BufferAllocator::allocate(Context &context)
109 {
110     const DeviceInterface &vk = context.getDeviceInterface();
111     VkDevice vkDevice         = context.getDevice();
112     uint32_t queueFamilyIndex = context.getUniversalQueueFamilyIndex();
113     Allocator &memAlloc       = context.getDefaultAllocator();
114     de::MovePtr<IBufferAllocator> allocator;
115     MemoryRequirement requirement = legalMemoryTypes[m_memoryType];
116 
117     if (m_dedicated)
118         allocator = de::MovePtr<IBufferAllocator>(new BufferDedicatedAllocation);
119     else
120         allocator = de::MovePtr<IBufferAllocator>(new BufferSuballocation);
121 
122     allocator->createTestBuffer(vk, vkDevice, queueFamilyIndex, m_size, m_usage, context, memAlloc, m_buffer,
123                                 requirement, m_bufferAlloc);
124 }
125 
deallocate(Context & context)126 void BufferAllocator::deallocate(Context &context)
127 {
128     const DeviceInterface &vk  = context.getDeviceInterface();
129     const vk::VkDevice &device = context.getDevice();
130 
131     vk.destroyBuffer(device, m_buffer.disown(), DE_NULL);
132     m_bufferAlloc.clear();
133 }
134 
getSize(Context & context)135 size_t BufferAllocator::getSize(Context &context)
136 {
137     const DeviceInterface &vk  = context.getDeviceInterface();
138     const vk::VkDevice &device = context.getDevice();
139     VkMemoryRequirements memReq;
140 
141     vk.getBufferMemoryRequirements(device, *m_buffer, &memReq);
142 
143     return (size_t)memReq.size;
144 }
145 
146 class ImageAllocator : public IObjectAllocator
147 {
148 public:
149     ImageAllocator(deRandom &random, bool dedicated, std::vector<int> &linearformats, std::vector<int> &optimalformats,
150                    std::vector<int> &memoryTypes);
151     virtual ~ImageAllocator();
152     virtual void allocate(Context &context);
153     virtual void deallocate(Context &context);
154     virtual size_t getSize(Context &context);
155 
156 private:
157     bool m_dedicated;
158     bool m_linear;
159     Move<vk::VkImage> m_image;
160     tcu::IVec2 m_size;
161     vk::VkFormat m_colorFormat;
162     de::MovePtr<Allocation> m_imageAlloc;
163     int m_memoryType;
164 };
165 
ImageAllocator(deRandom & random,bool dedicated,std::vector<int> & linearformats,std::vector<int> & optimalformats,std::vector<int> & memoryTypes)166 ImageAllocator::ImageAllocator(deRandom &random, bool dedicated, std::vector<int> &linearformats,
167                                std::vector<int> &optimalformats, std::vector<int> &memoryTypes)
168 {
169     // If dedicated allocation is supported, pick it randomly
170     m_dedicated = dedicated && deRandom_getBool(&random);
171     // If linear formats are supported, pick it randomly
172     m_linear = (linearformats.size() > 0) && deRandom_getBool(&random);
173 
174     if (m_linear)
175         m_colorFormat = (VkFormat)linearformats[deRandom_getUint32(&random) % linearformats.size()];
176     else
177         m_colorFormat = (VkFormat)optimalformats[deRandom_getUint32(&random) % optimalformats.size()];
178 
179     int widthAlignment  = (isYCbCr420Format(m_colorFormat) || isYCbCr422Format(m_colorFormat)) ? 2 : 1;
180     int heightAlignment = isYCbCr420Format(m_colorFormat) ? 2 : 1;
181 
182     // Random small size for causing potential alignment issues
183     m_size = tcu::IVec2((deRandom_getUint32(&random) % 16 + 3) & ~(widthAlignment - 1),
184                         (deRandom_getUint32(&random) % 16 + 3) & ~(heightAlignment - 1));
185     // Pick random memory type from the supported set
186     m_memoryType = memoryTypes[deRandom_getUint32(&random) % memoryTypes.size()];
187 }
188 
~ImageAllocator()189 ImageAllocator::~ImageAllocator()
190 {
191 }
192 
allocate(Context & context)193 void ImageAllocator::allocate(Context &context)
194 {
195     Allocator &memAlloc = context.getDefaultAllocator();
196     de::MovePtr<IImageAllocator> allocator;
197     MemoryRequirement requirement = legalMemoryTypes[m_memoryType];
198 
199     if (m_dedicated)
200         allocator = de::MovePtr<IImageAllocator>(new ImageDedicatedAllocation);
201     else
202         allocator = de::MovePtr<IImageAllocator>(new ImageSuballocation);
203 
204     allocator->createTestImage(m_size, m_colorFormat, context, memAlloc, m_image, requirement, m_imageAlloc,
205                                m_linear ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL);
206 }
207 
deallocate(Context & context)208 void ImageAllocator::deallocate(Context &context)
209 {
210     const DeviceInterface &vk = context.getDeviceInterface();
211     const VkDevice &device    = context.getDevice();
212 
213     vk.destroyImage(device, m_image.disown(), DE_NULL);
214     m_imageAlloc.clear();
215 }
216 
getSize(Context & context)217 size_t ImageAllocator::getSize(Context &context)
218 {
219     const DeviceInterface &vk = context.getDeviceInterface();
220     const VkDevice &device    = context.getDevice();
221     VkMemoryRequirements memReq;
222 
223     vk.getImageMemoryRequirements(device, *m_image, &memReq);
224 
225     return (size_t)memReq.size;
226 }
227 
228 class InvarianceInstance : public vkt::TestInstance
229 {
230 public:
231     InvarianceInstance(Context &context, const uint32_t seed);
232     virtual ~InvarianceInstance(void);
233     virtual tcu::TestStatus iterate(void);
234 
235 private:
236     deRandom m_random;
237 };
238 
InvarianceInstance(Context & context,const uint32_t seed)239 InvarianceInstance::InvarianceInstance(Context &context, const uint32_t seed) : vkt::TestInstance(context)
240 {
241     deRandom_init(&m_random, seed);
242 }
243 
~InvarianceInstance(void)244 InvarianceInstance::~InvarianceInstance(void)
245 {
246 }
247 
iterate(void)248 tcu::TestStatus InvarianceInstance::iterate(void)
249 {
250     de::MovePtr<IObjectAllocator> objs[testCycles];
251     size_t refSizes[testCycles];
252     unsigned int order[testCycles];
253     bool supported[testCycles];
254     bool allUnsupported                       = true;
255     bool success                              = true;
256     const bool isDedicatedAllocationSupported = m_context.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation");
257     const bool isYcbcrSupported          = m_context.isDeviceFunctionalitySupported("VK_KHR_sampler_ycbcr_conversion");
258     const bool isYcbcrExtensionSupported = m_context.isDeviceFunctionalitySupported("VK_EXT_ycbcr_2plane_444_formats");
259     const bool isPvrtcSupported          = m_context.isDeviceFunctionalitySupported("VK_IMG_format_pvrtc");
260 #ifndef CTS_USES_VULKANSC
261     const bool isMaintenance5Supported = m_context.isDeviceFunctionalitySupported("VK_KHR_maintenance5");
262 #endif // CTS_USES_VULKANSC
263     std::vector<int> optimalFormats;
264     std::vector<int> linearFormats;
265     std::vector<int> memoryTypes;
266     vk::VkPhysicalDeviceMemoryProperties memProperties;
267 
268     // List of all VkFormat enums
269     const unsigned int formatlist[] = {
270         VK_FORMAT_UNDEFINED,
271         VK_FORMAT_R4G4_UNORM_PACK8,
272         VK_FORMAT_R4G4B4A4_UNORM_PACK16,
273         VK_FORMAT_B4G4R4A4_UNORM_PACK16,
274         VK_FORMAT_R5G6B5_UNORM_PACK16,
275         VK_FORMAT_B5G6R5_UNORM_PACK16,
276         VK_FORMAT_R5G5B5A1_UNORM_PACK16,
277         VK_FORMAT_B5G5R5A1_UNORM_PACK16,
278         VK_FORMAT_A1R5G5B5_UNORM_PACK16,
279 #ifndef CTS_USES_VULKANSC
280         VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
281 #endif // CTS_USES_VULKANSC
282         VK_FORMAT_R8_UNORM,
283         VK_FORMAT_R8_SNORM,
284         VK_FORMAT_R8_USCALED,
285         VK_FORMAT_R8_SSCALED,
286         VK_FORMAT_R8_UINT,
287         VK_FORMAT_R8_SINT,
288         VK_FORMAT_R8_SRGB,
289 #ifndef CTS_USES_VULKANSC
290         VK_FORMAT_A8_UNORM_KHR,
291 #endif // CTS_USES_VULKANSC
292         VK_FORMAT_R8G8_UNORM,
293         VK_FORMAT_R8G8_SNORM,
294         VK_FORMAT_R8G8_USCALED,
295         VK_FORMAT_R8G8_SSCALED,
296         VK_FORMAT_R8G8_UINT,
297         VK_FORMAT_R8G8_SINT,
298         VK_FORMAT_R8G8_SRGB,
299         VK_FORMAT_R8G8B8_UNORM,
300         VK_FORMAT_R8G8B8_SNORM,
301         VK_FORMAT_R8G8B8_USCALED,
302         VK_FORMAT_R8G8B8_SSCALED,
303         VK_FORMAT_R8G8B8_UINT,
304         VK_FORMAT_R8G8B8_SINT,
305         VK_FORMAT_R8G8B8_SRGB,
306         VK_FORMAT_B8G8R8_UNORM,
307         VK_FORMAT_B8G8R8_SNORM,
308         VK_FORMAT_B8G8R8_USCALED,
309         VK_FORMAT_B8G8R8_SSCALED,
310         VK_FORMAT_B8G8R8_UINT,
311         VK_FORMAT_B8G8R8_SINT,
312         VK_FORMAT_B8G8R8_SRGB,
313         VK_FORMAT_R8G8B8A8_UNORM,
314         VK_FORMAT_R8G8B8A8_SNORM,
315         VK_FORMAT_R8G8B8A8_USCALED,
316         VK_FORMAT_R8G8B8A8_SSCALED,
317         VK_FORMAT_R8G8B8A8_UINT,
318         VK_FORMAT_R8G8B8A8_SINT,
319         VK_FORMAT_R8G8B8A8_SRGB,
320         VK_FORMAT_B8G8R8A8_UNORM,
321         VK_FORMAT_B8G8R8A8_SNORM,
322         VK_FORMAT_B8G8R8A8_USCALED,
323         VK_FORMAT_B8G8R8A8_SSCALED,
324         VK_FORMAT_B8G8R8A8_UINT,
325         VK_FORMAT_B8G8R8A8_SINT,
326         VK_FORMAT_B8G8R8A8_SRGB,
327         VK_FORMAT_A8B8G8R8_UNORM_PACK32,
328         VK_FORMAT_A8B8G8R8_SNORM_PACK32,
329         VK_FORMAT_A8B8G8R8_USCALED_PACK32,
330         VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
331         VK_FORMAT_A8B8G8R8_UINT_PACK32,
332         VK_FORMAT_A8B8G8R8_SINT_PACK32,
333         VK_FORMAT_A8B8G8R8_SRGB_PACK32,
334         VK_FORMAT_A2R10G10B10_UNORM_PACK32,
335         VK_FORMAT_A2R10G10B10_SNORM_PACK32,
336         VK_FORMAT_A2R10G10B10_USCALED_PACK32,
337         VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
338         VK_FORMAT_A2R10G10B10_UINT_PACK32,
339         VK_FORMAT_A2R10G10B10_SINT_PACK32,
340         VK_FORMAT_A2B10G10R10_UNORM_PACK32,
341         VK_FORMAT_A2B10G10R10_SNORM_PACK32,
342         VK_FORMAT_A2B10G10R10_USCALED_PACK32,
343         VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
344         VK_FORMAT_A2B10G10R10_UINT_PACK32,
345         VK_FORMAT_A2B10G10R10_SINT_PACK32,
346         VK_FORMAT_R16_UNORM,
347         VK_FORMAT_R16_SNORM,
348         VK_FORMAT_R16_USCALED,
349         VK_FORMAT_R16_SSCALED,
350         VK_FORMAT_R16_UINT,
351         VK_FORMAT_R16_SINT,
352         VK_FORMAT_R16_SFLOAT,
353         VK_FORMAT_R16G16_UNORM,
354         VK_FORMAT_R16G16_SNORM,
355         VK_FORMAT_R16G16_USCALED,
356         VK_FORMAT_R16G16_SSCALED,
357         VK_FORMAT_R16G16_UINT,
358         VK_FORMAT_R16G16_SINT,
359         VK_FORMAT_R16G16_SFLOAT,
360         VK_FORMAT_R16G16B16_UNORM,
361         VK_FORMAT_R16G16B16_SNORM,
362         VK_FORMAT_R16G16B16_USCALED,
363         VK_FORMAT_R16G16B16_SSCALED,
364         VK_FORMAT_R16G16B16_UINT,
365         VK_FORMAT_R16G16B16_SINT,
366         VK_FORMAT_R16G16B16_SFLOAT,
367         VK_FORMAT_R16G16B16A16_UNORM,
368         VK_FORMAT_R16G16B16A16_SNORM,
369         VK_FORMAT_R16G16B16A16_USCALED,
370         VK_FORMAT_R16G16B16A16_SSCALED,
371         VK_FORMAT_R16G16B16A16_UINT,
372         VK_FORMAT_R16G16B16A16_SINT,
373         VK_FORMAT_R16G16B16A16_SFLOAT,
374         VK_FORMAT_R32_UINT,
375         VK_FORMAT_R32_SINT,
376         VK_FORMAT_R32_SFLOAT,
377         VK_FORMAT_R32G32_UINT,
378         VK_FORMAT_R32G32_SINT,
379         VK_FORMAT_R32G32_SFLOAT,
380         VK_FORMAT_R32G32B32_UINT,
381         VK_FORMAT_R32G32B32_SINT,
382         VK_FORMAT_R32G32B32_SFLOAT,
383         VK_FORMAT_R32G32B32A32_UINT,
384         VK_FORMAT_R32G32B32A32_SINT,
385         VK_FORMAT_R32G32B32A32_SFLOAT,
386         VK_FORMAT_R64_UINT,
387         VK_FORMAT_R64_SINT,
388         VK_FORMAT_R64_SFLOAT,
389         VK_FORMAT_R64G64_UINT,
390         VK_FORMAT_R64G64_SINT,
391         VK_FORMAT_R64G64_SFLOAT,
392         VK_FORMAT_R64G64B64_UINT,
393         VK_FORMAT_R64G64B64_SINT,
394         VK_FORMAT_R64G64B64_SFLOAT,
395         VK_FORMAT_R64G64B64A64_UINT,
396         VK_FORMAT_R64G64B64A64_SINT,
397         VK_FORMAT_R64G64B64A64_SFLOAT,
398         VK_FORMAT_B10G11R11_UFLOAT_PACK32,
399         VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
400         VK_FORMAT_D16_UNORM,
401         VK_FORMAT_X8_D24_UNORM_PACK32,
402         VK_FORMAT_D32_SFLOAT,
403         VK_FORMAT_S8_UINT,
404         VK_FORMAT_D16_UNORM_S8_UINT,
405         VK_FORMAT_D24_UNORM_S8_UINT,
406         VK_FORMAT_D32_SFLOAT_S8_UINT,
407         VK_FORMAT_BC1_RGB_UNORM_BLOCK,
408         VK_FORMAT_BC1_RGB_SRGB_BLOCK,
409         VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
410         VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
411         VK_FORMAT_BC2_UNORM_BLOCK,
412         VK_FORMAT_BC2_SRGB_BLOCK,
413         VK_FORMAT_BC3_UNORM_BLOCK,
414         VK_FORMAT_BC3_SRGB_BLOCK,
415         VK_FORMAT_BC4_UNORM_BLOCK,
416         VK_FORMAT_BC4_SNORM_BLOCK,
417         VK_FORMAT_BC5_UNORM_BLOCK,
418         VK_FORMAT_BC5_SNORM_BLOCK,
419         VK_FORMAT_BC6H_UFLOAT_BLOCK,
420         VK_FORMAT_BC6H_SFLOAT_BLOCK,
421         VK_FORMAT_BC7_UNORM_BLOCK,
422         VK_FORMAT_BC7_SRGB_BLOCK,
423         VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
424         VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
425         VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
426         VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
427         VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
428         VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
429         VK_FORMAT_EAC_R11_UNORM_BLOCK,
430         VK_FORMAT_EAC_R11_SNORM_BLOCK,
431         VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
432         VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
433         VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
434         VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
435         VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
436         VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
437         VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
438         VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
439         VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
440         VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
441         VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
442         VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
443         VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
444         VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
445         VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
446         VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
447         VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
448         VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
449         VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
450         VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
451         VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
452         VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
453         VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
454         VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
455         VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
456         VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
457         VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
458         VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
459         VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
460         VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
461         VK_FORMAT_G8B8G8R8_422_UNORM,
462         VK_FORMAT_B8G8R8G8_422_UNORM,
463         VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
464         VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
465         VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
466         VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
467         VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
468         VK_FORMAT_R10X6_UNORM_PACK16,
469         VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
470         VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
471         VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
472         VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
473         VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
474         VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
475         VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
476         VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
477         VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
478         VK_FORMAT_R12X4_UNORM_PACK16,
479         VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
480         VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
481         VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
482         VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
483         VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
484         VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
485         VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
486         VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
487         VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
488         VK_FORMAT_G16B16G16R16_422_UNORM,
489         VK_FORMAT_B16G16R16G16_422_UNORM,
490         VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
491         VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
492         VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
493         VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
494         VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
495 #ifndef CTS_USES_VULKANSC
496         // Removed from Vulkan SC test set: VK_IMG_format_pvrtc extension does not exist in Vulkan SC
497         VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,
498         VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,
499         VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG,
500         VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG,
501         VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,
502         VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,
503         VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG,
504         VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG,
505         VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
506         VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
507         VK_FORMAT_G8_B8R8_2PLANE_444_UNORM_EXT,
508         VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16_EXT,
509         VK_FORMAT_G12X4_B12X4R12X4_2PLANE_444_UNORM_3PACK16_EXT,
510         VK_FORMAT_G16_B16R16_2PLANE_444_UNORM_EXT,
511 #endif
512     };
513     int formatCount = (int)(sizeof(formatlist) / sizeof(unsigned int));
514 
515     // Find supported image formats
516     for (int i = 0; i < formatCount; i++)
517     {
518         if (isYCbCrFormat((VkFormat)formatlist[i]) && !isYcbcrSupported)
519             continue;
520 
521         if (isYCbCrExtensionFormat((VkFormat)formatlist[i]) && !isYcbcrExtensionSupported)
522             continue;
523 
524         if (isPvrtcFormat((VkFormat)formatlist[i]) && !isPvrtcSupported)
525             continue;
526 
527 #ifndef CTS_USES_VULKANSC
528         if (!isMaintenance5Supported)
529         {
530             if (formatlist[i] == VK_FORMAT_A8_UNORM_KHR || formatlist[i] == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
531                 continue;
532         }
533 #endif // CTS_USES_VULKANSC
534 
535         vk::VkImageFormatProperties imageformatprops;
536 
537         // Check for support in linear tiling mode
538         if (m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(
539                 m_context.getPhysicalDevice(), (VkFormat)formatlist[i], VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_LINEAR,
540                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, 0, &imageformatprops) == VK_SUCCESS)
541             linearFormats.push_back(formatlist[i]);
542 
543         // Check for support in optimal tiling mode
544         if (m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(
545                 m_context.getPhysicalDevice(), (VkFormat)formatlist[i], VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
546                 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0,
547                 &imageformatprops) == VK_SUCCESS)
548             optimalFormats.push_back(formatlist[i]);
549     }
550 
551     // Check for supported heap types
552     m_context.getInstanceInterface().getPhysicalDeviceMemoryProperties(m_context.getPhysicalDevice(), &memProperties);
553 
554     for (unsigned int j = 0; j < legalMemoryTypeCount; j++)
555     {
556         bool found = false;
557         for (unsigned int i = 0; !found && i < memProperties.memoryTypeCount; i++)
558         {
559             if (legalMemoryTypes[j].matchesHeap(memProperties.memoryTypes[i].propertyFlags))
560             {
561                 memoryTypes.push_back(j);
562                 found = true;
563             }
564         }
565     }
566 
567     // Log the used image types and heap types
568     tcu::TestLog &log = m_context.getTestContext().getLog();
569 
570     {
571         std::ostringstream values;
572         for (unsigned int i = 0; i < linearFormats.size(); i++)
573             values << " " << linearFormats[i];
574         log << tcu::TestLog::Message << "Using linear formats:" << values.str() << tcu::TestLog::EndMessage;
575     }
576 
577     {
578         std::ostringstream values;
579         for (unsigned int i = 0; i < optimalFormats.size(); i++)
580             values << " " << optimalFormats[i];
581         log << tcu::TestLog::Message << "Using optimal formats:" << values.str() << tcu::TestLog::EndMessage;
582     }
583 
584     {
585         std::ostringstream values;
586         for (unsigned int i = 0; i < memoryTypes.size(); i++)
587             values << " " << memoryTypes[i];
588         log << tcu::TestLog::Message << "Using memory types:" << values.str() << tcu::TestLog::EndMessage;
589     }
590 
591     for (unsigned int i = 0; i < testCycles; i++)
592     {
593         if (deRandom_getBool(&m_random))
594             objs[i] = de::MovePtr<IObjectAllocator>(
595                 new BufferAllocator(m_random, isDedicatedAllocationSupported, memoryTypes));
596         else
597             objs[i] = de::MovePtr<IObjectAllocator>(new ImageAllocator(m_random, isDedicatedAllocationSupported,
598                                                                        linearFormats, optimalFormats, memoryTypes));
599         order[i] = i;
600     }
601 
602     // First get reference values for the object sizes
603     for (unsigned int i = 0; i < testCycles; i++)
604     {
605         try
606         {
607             objs[i]->allocate(m_context);
608             refSizes[i] = objs[i]->getSize(m_context);
609             objs[i]->deallocate(m_context);
610             supported[i]   = true;
611             allUnsupported = false;
612         }
613         catch (const tcu::NotSupportedError &)
614         {
615             supported[i] = false;
616         }
617     }
618 
619     if (allUnsupported)
620         TCU_THROW(NotSupportedError, "All allocations unsupported");
621 
622     // Shuffle order by swapping random pairs
623     for (unsigned int i = 0; i < testCycles; i++)
624     {
625         int a = deRandom_getUint32(&m_random) % testCycles;
626         int b = deRandom_getUint32(&m_random) % testCycles;
627         std::swap(order[a], order[b]);
628     }
629 
630     // Allocate objects in shuffled order
631     for (unsigned int i = 0; i < testCycles; i++)
632     {
633         if (supported[order[i]])
634             objs[order[i]]->allocate(m_context);
635     }
636 
637     // Check for size mismatches
638     for (unsigned int i = 0; i < testCycles; i++)
639     {
640         if (!supported[order[i]])
641             continue;
642 
643         size_t val = objs[order[i]]->getSize(m_context);
644 
645         if (val != refSizes[order[i]])
646         {
647             success = false;
648             log << tcu::TestLog::Message << "Object " << order[i] << " size mismatch (" << val
649                 << " != " << refSizes[order[i]] << ")" << tcu::TestLog::EndMessage;
650         }
651     }
652 
653     // Clean up
654     for (unsigned int i = 0; i < testCycles; i++)
655     {
656         if (supported[order[i]])
657             objs[order[i]]->deallocate(m_context);
658     }
659 
660     if (success)
661         return tcu::TestStatus::pass("Pass");
662 
663     return tcu::TestStatus::fail("One or more allocation is not invariant");
664 }
665 
666 class AlignmentMatchingInstance : public vkt::TestInstance
667 {
668 public:
669     AlignmentMatchingInstance(Context &context);
670     virtual ~AlignmentMatchingInstance(void) = default;
671     virtual tcu::TestStatus iterate(void);
672 };
673 
AlignmentMatchingInstance(Context & context)674 AlignmentMatchingInstance::AlignmentMatchingInstance(Context &context) : vkt::TestInstance(context)
675 {
676 }
677 
iterate(void)678 tcu::TestStatus AlignmentMatchingInstance::iterate(void)
679 {
680     const VkDevice device       = m_context.getDevice();
681     const DeviceInterface &vk   = m_context.getDeviceInterface();
682     const uint32_t objectsCount = 5;
683     tcu::TestLog &log           = m_context.getTestContext().getLog();
684     bool success                = true;
685     VkExtent3D baseExtent       = {32, 31, 1};
686     VkDeviceSize baseSize       = 1023;
687 
688     VkImageCreateInfo imageCreateInfo{
689         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
690         DE_NULL,                             // const void* pNext;
691         0u,                                  // VkImageCreateFlags flags;
692         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
693         VK_FORMAT_R8G8B8A8_UNORM,            // VkFormat format;
694         baseExtent,                          // VkExtent3D extent;
695         1u,                                  // uint32_t mipLevels;
696         1u,                                  // uint32_t arraySize;
697         VK_SAMPLE_COUNT_1_BIT,               // uint32_t samples;
698         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
699         VK_IMAGE_USAGE_TRANSFER_SRC_BIT,     // VkImageUsageFlags usage;
700         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
701         0u,                                  // uint32_t queueFamilyCount;
702         DE_NULL,                             // const uint32_t* pQueueFamilyIndices;
703         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
704     };
705 
706     VkBufferCreateInfo bufferCreateInfo{
707         VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType        sType
708         DE_NULL,                              // const void*            pNext
709         0u,                                   // VkBufferCreateFlags    flags
710         baseSize,                             // VkDeviceSize            size
711         VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags    usage
712         VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode        sharingMode
713         0u,                                   // uint32_t                queueFamilyIndexCount
714         DE_NULL                               // const uint32_t*        pQueueFamilyIndices
715     };
716 
717     Move<VkImage> baseImage   = createImage(vk, device, &imageCreateInfo);
718     Move<VkBuffer> baseBuffer = createBuffer(vk, device, &bufferCreateInfo);
719 
720     VkMemoryRequirements baseImageRequirements  = getImageMemoryRequirements(vk, device, *baseImage);
721     VkMemoryRequirements baseBufferRequirements = getBufferMemoryRequirements(vk, device, *baseBuffer);
722 
723     // Create a bunch of VkBuffer and VkImage objects with the same
724     // create infos and make sure their alignments all match.
725     {
726         std::vector<Move<VkImage>> images(objectsCount);
727         std::vector<Move<VkBuffer>> buffers(objectsCount);
728 
729         for (uint32_t idx = 0; idx < objectsCount; ++idx)
730         {
731             images[idx]  = createImage(vk, device, &imageCreateInfo);
732             buffers[idx] = createBuffer(vk, device, &bufferCreateInfo);
733 
734             VkMemoryRequirements imageRequirements   = getImageMemoryRequirements(vk, device, *images[idx]);
735             VkMemoryRequirements buffersRequirements = getBufferMemoryRequirements(vk, device, *buffers[idx]);
736 
737             if (baseImageRequirements.alignment != imageRequirements.alignment)
738             {
739                 success = false;
740                 log << tcu::TestLog::Message
741                     << "Alignments for all VkImage objects created with the same create infos should match\n"
742                     << tcu::TestLog::EndMessage;
743             }
744             if (baseBufferRequirements.alignment != buffersRequirements.alignment)
745             {
746                 success = false;
747                 log << tcu::TestLog::Message
748                     << "Alignments for all VkBuffer objects created with the same create infos should match\n"
749                     << tcu::TestLog::EndMessage;
750             }
751         }
752     }
753 
754     if (m_context.isDeviceFunctionalitySupported("VK_KHR_get_memory_requirements2"))
755     {
756 #ifndef CTS_USES_VULKANSC
757         VkBufferMemoryRequirementsInfo2 bufferMemoryRequirementsInfo{
758             VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2, // VkStructureType    sType
759             DE_NULL,                                             // const void*        pNext
760             *baseBuffer                                          // VkBuffer            buffer
761         };
762         VkImageMemoryRequirementsInfo2 imageMemoryRequirementsInfo{
763             VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2, // VkStructureType    sType
764             DE_NULL,                                            // const void*        pNext
765             *baseImage                                          // VkImage            image
766         };
767         std::vector<VkMemoryRequirements2> requirements2(
768             2,
769             {
770                 VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, // VkStructureType        sType
771                 DE_NULL,                                 // void*                pNext
772                 {0, 0, 0}                                // VkMemoryRequirements    memoryRequirements
773             });
774 
775         auto areRequirementsTheSame = [](VkMemoryRequirements2 &a, VkMemoryRequirements2 &b)
776         {
777             return ((a.memoryRequirements.size == b.memoryRequirements.size) &&
778                     (a.memoryRequirements.alignment == b.memoryRequirements.alignment) &&
779                     (a.memoryRequirements.memoryTypeBits == b.memoryRequirements.memoryTypeBits));
780         };
781 
782         // The memory requirements returned by vkGetBufferCreateInfoMemoryRequirementsKHR are identical to those that
783         // would be returned by vkGetBufferMemoryRequirements2 if it were called with a VkBuffer created with the same
784         // VkBufferCreateInfo values.
785         vk.getBufferMemoryRequirements2(device, &bufferMemoryRequirementsInfo, &requirements2[0]);
786         const VkDeviceBufferMemoryRequirementsKHR bufferMemInfo = {
787             VK_STRUCTURE_TYPE_DEVICE_BUFFER_MEMORY_REQUIREMENTS_KHR, DE_NULL, &bufferCreateInfo};
788         vk.getDeviceBufferMemoryRequirements(device, &bufferMemInfo, &requirements2[1]);
789 
790         if (!areRequirementsTheSame(requirements2[0], requirements2[1]))
791         {
792             success = false;
793             log << tcu::TestLog::Message
794                 << "vkGetDeviceBufferMemoryRequirements and vkGetBufferMemoryRequirements2\n"
795                    "report diferent memory requirements\n"
796                 << tcu::TestLog::EndMessage;
797         }
798 
799         // Similarly, vkGetImageCreateInfoMemoryRequirementsKHR will report the same memory requirements as
800         // vkGetImageMemoryRequirements2 would if called with a VkImage created with the supplied VkImageCreateInfo
801         vk.getImageMemoryRequirements2(device, &imageMemoryRequirementsInfo, &requirements2[0]);
802         const VkDeviceImageMemoryRequirementsKHR imageMemInfo = {VK_STRUCTURE_TYPE_DEVICE_IMAGE_MEMORY_REQUIREMENTS_KHR,
803                                                                  DE_NULL, &imageCreateInfo,
804                                                                  vk::VkImageAspectFlagBits(0)};
805         vk.getDeviceImageMemoryRequirements(device, &imageMemInfo, &requirements2[1]);
806 
807         if (!areRequirementsTheSame(requirements2[0], requirements2[1]))
808         {
809             success = false;
810             log << tcu::TestLog::Message
811                 << "vkGetDeviceImageMemoryRequirements and vkGetImageMemoryRequirements2\n"
812                    "report diferent memory requirements\n"
813                 << tcu::TestLog::EndMessage;
814         }
815 #endif // CTS_USES_VULKANSC
816     }
817 
818     // For a VkImage, the size memory requirement is never greater than that of another VkImage created with
819     // a greater or equal extent dimension specified in VkImageCreateInfo, all other creation parameters being identical.
820     // For a VkBuffer, the size memory requirement is never greater than that of another VkBuffer created with
821     // a greater or equal size specified in VkBufferCreateInfo, all other creation parameters being identical.
822     {
823         std::vector<Move<VkImage>> images(objectsCount);
824         std::vector<Move<VkBuffer>> buffers(objectsCount);
825 
826         for (uint32_t idx = 0; idx < objectsCount; ++idx)
827         {
828             imageCreateInfo.extent = {baseExtent.width + (idx % 2) * idx, baseExtent.height + idx, 1u};
829             bufferCreateInfo.size  = baseSize + idx;
830 
831             images[idx]  = createImage(vk, device, &imageCreateInfo);
832             buffers[idx] = createBuffer(vk, device, &bufferCreateInfo);
833 
834             VkMemoryRequirements imageRequirements   = getImageMemoryRequirements(vk, device, *images[idx]);
835             VkMemoryRequirements buffersRequirements = getBufferMemoryRequirements(vk, device, *buffers[idx]);
836 
837             if (baseImageRequirements.size > imageRequirements.size)
838             {
839                 success = false;
840                 log << tcu::TestLog::Message
841                     << "Size memory requiremen for VkImage should never be greater than that of another VkImage\n"
842                        "created with a greater or equal extent dimension specified in VkImageCreateInfo when all\n"
843                        "other creation parameters are identical\n"
844                     << tcu::TestLog::EndMessage;
845             }
846             if (baseBufferRequirements.size > buffersRequirements.size)
847             {
848                 success = false;
849                 log << tcu::TestLog::Message
850                     << "Size memory requiremen for VkBuffer should never be greater than that of another VkBuffer\n"
851                        "created with a greater or size specified in VkImageCreateInfo when all\n"
852                        "other creation parameters are identical\n"
853                     << tcu::TestLog::EndMessage;
854             }
855         }
856     }
857 
858     if (success)
859         return tcu::TestStatus::pass("Pass");
860 
861     return tcu::TestStatus::fail("Fail");
862 }
863 
864 enum TestType
865 {
866     TT_BASIC_INVARIANCE = 0,
867     TT_REQUIREMENTS_MATCHING
868 };
869 
870 class InvarianceCase : public vkt::TestCase
871 {
872 public:
873     InvarianceCase(tcu::TestContext &testCtx, const std::string &name, TestType testType);
874     virtual ~InvarianceCase(void) = default;
875 
876     virtual TestInstance *createInstance(Context &context) const;
877     virtual void checkSupport(Context &context) const;
878 
879 protected:
880     TestType m_testType;
881 };
882 
InvarianceCase(tcu::TestContext & testCtx,const std::string & name,TestType testType)883 InvarianceCase::InvarianceCase(tcu::TestContext &testCtx, const std::string &name, TestType testType)
884     : vkt::TestCase(testCtx, name)
885     , m_testType(testType)
886 {
887 }
888 
createInstance(Context & context) const889 TestInstance *InvarianceCase::createInstance(Context &context) const
890 {
891     if (TT_REQUIREMENTS_MATCHING == m_testType)
892         return new AlignmentMatchingInstance(context);
893 
894     return new InvarianceInstance(context, 0x600613);
895 }
896 
checkSupport(Context & context) const897 void InvarianceCase::checkSupport(Context &context) const
898 {
899     if (TT_REQUIREMENTS_MATCHING == m_testType)
900         context.requireDeviceFunctionality("VK_KHR_maintenance4");
901 }
902 
createMemoryRequirementInvarianceTests(tcu::TestContext & testCtx)903 tcu::TestCaseGroup *createMemoryRequirementInvarianceTests(tcu::TestContext &testCtx)
904 {
905     de::MovePtr<tcu::TestCaseGroup> invarianceTests(new tcu::TestCaseGroup(testCtx, "invariance"));
906 
907     invarianceTests->addChild(new InvarianceCase(testCtx, "random", TT_BASIC_INVARIANCE));
908     invarianceTests->addChild(new InvarianceCase(testCtx, "memory_requirements_matching", TT_REQUIREMENTS_MATCHING));
909 
910     return invarianceTests.release();
911 }
912 
913 } // namespace api
914 } // namespace vkt
915