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