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