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