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