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 const unsigned int		testCycles								= 1000u;
41 
42 // All legal memory combinations (spec chapter 10.2: Device Memory)
43 const unsigned int		legalMemoryTypeCount					= 11u;
44 const MemoryRequirement	legalMemoryTypes[legalMemoryTypeCount]	=
45 {
46 	MemoryRequirement::Any,
47 	MemoryRequirement::HostVisible	| MemoryRequirement::Coherent,
48 	MemoryRequirement::HostVisible	| MemoryRequirement::Cached,
49 	MemoryRequirement::HostVisible	| MemoryRequirement::Cached			| MemoryRequirement::Coherent,
50 	MemoryRequirement::Local,
51 	MemoryRequirement::Local		| MemoryRequirement::HostVisible	| MemoryRequirement::Coherent,
52 	MemoryRequirement::Local		| MemoryRequirement::HostVisible	| MemoryRequirement::Cached,
53 	MemoryRequirement::Local		| MemoryRequirement::HostVisible	| MemoryRequirement::Cached		| MemoryRequirement::Coherent,
54 	MemoryRequirement::Local		| MemoryRequirement::LazilyAllocated,
55 	MemoryRequirement::Protected,
56 	MemoryRequirement::Protected	| MemoryRequirement::Local
57 };
58 
59 class IObjectAllocator
60 {
61 public:
IObjectAllocator()62 					IObjectAllocator	()	{};
~IObjectAllocator()63 	virtual			~IObjectAllocator	()	{};
64 	virtual void	allocate			(Context&	context)	= 0;
65 	virtual void	deallocate			(Context&	context)	= 0;
66 	virtual	size_t	getSize				(Context&	context)	= 0;
67 };
68 
69 class BufferAllocator : public IObjectAllocator
70 {
71 public:
72 					BufferAllocator		(deRandom& random, deBool dedicated, std::vector<int>& memoryTypes);
73 	virtual			~BufferAllocator	();
74 	virtual void	allocate			(Context&	context);
75 	virtual void	deallocate			(Context&	context);
76 	virtual	size_t	getSize				(Context&	context);
77 private:
78 	bool					m_dedicated;
79 	Move<VkBuffer>			m_buffer;
80 	VkDeviceSize			m_size;
81 	VkBufferUsageFlags		m_usage;
82 	int						m_memoryType;
83 	de::MovePtr<Allocation>	m_bufferAlloc;
84 };
85 
BufferAllocator(deRandom & random,deBool dedicated,std::vector<int> & memoryTypes)86 BufferAllocator::BufferAllocator (deRandom& random, deBool dedicated, std::vector<int>& memoryTypes)
87 {
88 	// If dedicated allocation is supported, randomly pick it
89 	m_dedicated		= dedicated && deRandom_getBool(&random);
90 	// Random buffer sizes to find potential issues caused by strange alignment
91 	m_size			= (deRandom_getUint32(&random) % 1024) + 7;
92 	// Pick a random usage from the 9 VkBufferUsageFlags.
93 	m_usage			= 1 << (deRandom_getUint32(&random) % 9);
94 	// Pick random memory type from the supported ones
95 	m_memoryType	= memoryTypes[deRandom_getUint32(&random) % memoryTypes.size()];
96 }
97 
~BufferAllocator()98 BufferAllocator::~BufferAllocator ()
99 {
100 }
101 
allocate(Context & context)102 void BufferAllocator::allocate (Context& context)
103 {
104 	Allocator&			memAlloc	= context.getDefaultAllocator();
105 	IBufferAllocator*	allocator	= 0;
106 	MemoryRequirement	requirement	= legalMemoryTypes[m_memoryType];
107 
108 	if (m_dedicated)
109 		allocator = new BufferDedicatedAllocation;
110 	else
111 		allocator = new BufferSuballocation;
112 
113 	allocator->createTestBuffer(
114 		m_size,
115 		m_usage,
116 		context,
117 		memAlloc,
118 		m_buffer,
119 		requirement,
120 		m_bufferAlloc);
121 
122 	delete allocator;
123 }
124 
deallocate(Context & context)125 void BufferAllocator::deallocate (Context& context)
126 {
127 	const DeviceInterface&	vk		= context.getDeviceInterface();
128 	const vk::VkDevice&		device	= context.getDevice();
129 
130 	vk.destroyBuffer(device, m_buffer.disown(), DE_NULL);
131 	vk.freeMemory(device, m_bufferAlloc.get()->getMemory(), (const VkAllocationCallbacks*)DE_NULL);
132 	m_bufferAlloc.release();
133 }
134 
getSize(Context & context)135 size_t BufferAllocator::getSize (Context &context)
136 {
137 	const DeviceInterface&	vk		= context.getDeviceInterface();
138 	const vk::VkDevice&		device	= context.getDevice();
139 	VkMemoryRequirements	memReq;
140 
141 	vk.getBufferMemoryRequirements(device, *m_buffer, &memReq);
142 
143 	return (size_t)memReq.size;
144 }
145 
146 class ImageAllocator : public IObjectAllocator
147 {
148 public:
149 					ImageAllocator	(deRandom& random, deBool dedicated, std::vector<int>& linearformats, std::vector<int>& optimalformats, std::vector<int>& memoryTypes);
150 	virtual			~ImageAllocator	();
151 	virtual void	allocate		(Context&	context);
152 	virtual void	deallocate		(Context&	context);
153 	virtual	size_t	getSize			(Context&	context);
154 private:
155 	deBool					m_dedicated;
156 	deBool					m_linear;
157 	Move<vk::VkImage>		m_image;
158 	tcu::IVec2				m_size;
159 	vk::VkFormat			m_colorFormat;
160 	de::MovePtr<Allocation>	m_imageAlloc;
161 	int						m_memoryType;
162 };
163 
ImageAllocator(deRandom & random,deBool dedicated,std::vector<int> & linearformats,std::vector<int> & optimalformats,std::vector<int> & memoryTypes)164 ImageAllocator::ImageAllocator (deRandom& random, deBool dedicated, std::vector<int>& linearformats, std::vector<int>& optimalformats, std::vector<int>& memoryTypes)
165 {
166 	// If dedicated allocation is supported, pick it randomly
167 	m_dedicated		= dedicated && deRandom_getBool(&random);
168 	// If linear formats are supported, pick it randomly
169 	m_linear		= (linearformats.size() > 0) && deRandom_getBool(&random);
170 
171 	if (m_linear)
172 		m_colorFormat = (VkFormat)linearformats[deRandom_getUint32(&random) % linearformats.size()];
173 	else
174 		m_colorFormat = (VkFormat)optimalformats[deRandom_getUint32(&random) % optimalformats.size()];
175 
176 	int	widthAlignment	= (isYCbCr420Format(m_colorFormat) || isYCbCr422Format(m_colorFormat)) ? 2 : 1;
177 	int	heightAlignment	= isYCbCr420Format(m_colorFormat) ? 2 : 1;
178 
179 	// Random small size for causing potential alignment issues
180 	m_size			= tcu::IVec2((deRandom_getUint32(&random) % 16 + 3) & ~(widthAlignment - 1),
181 								 (deRandom_getUint32(&random) % 16 + 3) & ~(heightAlignment - 1));
182 	// Pick random memory type from the supported set
183 	m_memoryType	= memoryTypes[deRandom_getUint32(&random) % memoryTypes.size()];
184 }
185 
~ImageAllocator()186 ImageAllocator::~ImageAllocator ()
187 {
188 }
189 
allocate(Context & context)190 void ImageAllocator::allocate (Context& context)
191 {
192 	Allocator&			memAlloc	= context.getDefaultAllocator();
193 	IImageAllocator*	allocator	= 0;
194 	MemoryRequirement	requirement	= legalMemoryTypes[m_memoryType];
195 
196 	if (m_dedicated)
197 		allocator = new ImageDedicatedAllocation;
198 	else
199 		allocator = new ImageSuballocation;
200 
201 	allocator->createTestImage(
202 		m_size,
203 		m_colorFormat,
204 		context,
205 		memAlloc,
206 		m_image,
207 		requirement,
208 		m_imageAlloc,
209 		m_linear ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL);
210 
211 	delete allocator;
212 }
213 
deallocate(Context & context)214 void ImageAllocator::deallocate (Context& context)
215 {
216 	const DeviceInterface&	vk		= context.getDeviceInterface();
217 	const VkDevice&			device	= context.getDevice();
218 
219 	vk.destroyImage(device, m_image.disown(), DE_NULL);
220 	vk.freeMemory(device, m_imageAlloc.get()->getMemory(), (const VkAllocationCallbacks*)DE_NULL);
221 	m_imageAlloc.release();
222 }
223 
getSize(Context & context)224 size_t ImageAllocator::getSize (Context &context)
225 {
226 	const DeviceInterface&	vk		= context.getDeviceInterface();
227 	const VkDevice&			device	= context.getDevice();
228 	VkMemoryRequirements	memReq;
229 
230 	vk.getImageMemoryRequirements(device, *m_image, &memReq);
231 
232 	return (size_t)memReq.size;
233 }
234 
235 class InvarianceInstance : public vkt::TestInstance
236 {
237 public:
238 							InvarianceInstance			(Context&		context,
239 														 const deUint32	seed);
240 	virtual					~InvarianceInstance			(void);
241 	virtual	tcu::TestStatus	iterate						(void);
242 private:
243 	deRandom	m_random;
244 };
245 
InvarianceInstance(Context & context,const deUint32 seed)246 InvarianceInstance::InvarianceInstance	(Context&		context,
247 										 const deUint32	seed)
248 	: vkt::TestInstance	(context)
249 {
250 	deRandom_init(&m_random, seed);
251 }
252 
~InvarianceInstance(void)253 InvarianceInstance::~InvarianceInstance (void)
254 {
255 }
256 
iterate(void)257 tcu::TestStatus InvarianceInstance::iterate (void)
258 {
259 	IObjectAllocator*						objs[testCycles];
260 	size_t									refSizes[testCycles];
261 	unsigned int							order[testCycles];
262 	bool									success							= true;
263 	const std::vector<std::string>&			extensions						= m_context.getDeviceExtensions();
264 	const deBool							isDedicatedAllocationSupported	=
265 		isDeviceExtensionSupported(m_context.getUsedApiVersion(), extensions, "VK_KHR_dedicated_allocation");
266 	const deBool							isYcbcrSupported =
267 		isDeviceExtensionSupported(m_context.getUsedApiVersion(), extensions, "VK_KHR_sampler_ycbcr_conversion");
268 	std::vector<int>						optimalFormats;
269 	std::vector<int>						linearFormats;
270 	std::vector<int>						memoryTypes;
271 	vk::VkPhysicalDeviceMemoryProperties	memProperties;
272 
273 	// List of all VkFormat enums
274 	const unsigned int						formatlist[]					= {
275 		VK_FORMAT_UNDEFINED,
276 		VK_FORMAT_R4G4_UNORM_PACK8,
277 		VK_FORMAT_R4G4B4A4_UNORM_PACK16,
278 		VK_FORMAT_B4G4R4A4_UNORM_PACK16,
279 		VK_FORMAT_R5G6B5_UNORM_PACK16,
280 		VK_FORMAT_B5G6R5_UNORM_PACK16,
281 		VK_FORMAT_R5G5B5A1_UNORM_PACK16,
282 		VK_FORMAT_B5G5R5A1_UNORM_PACK16,
283 		VK_FORMAT_A1R5G5B5_UNORM_PACK16,
284 		VK_FORMAT_R8_UNORM,
285 		VK_FORMAT_R8_SNORM,
286 		VK_FORMAT_R8_USCALED,
287 		VK_FORMAT_R8_SSCALED,
288 		VK_FORMAT_R8_UINT,
289 		VK_FORMAT_R8_SINT,
290 		VK_FORMAT_R8_SRGB,
291 		VK_FORMAT_R8G8_UNORM,
292 		VK_FORMAT_R8G8_SNORM,
293 		VK_FORMAT_R8G8_USCALED,
294 		VK_FORMAT_R8G8_SSCALED,
295 		VK_FORMAT_R8G8_UINT,
296 		VK_FORMAT_R8G8_SINT,
297 		VK_FORMAT_R8G8_SRGB,
298 		VK_FORMAT_R8G8B8_UNORM,
299 		VK_FORMAT_R8G8B8_SNORM,
300 		VK_FORMAT_R8G8B8_USCALED,
301 		VK_FORMAT_R8G8B8_SSCALED,
302 		VK_FORMAT_R8G8B8_UINT,
303 		VK_FORMAT_R8G8B8_SINT,
304 		VK_FORMAT_R8G8B8_SRGB,
305 		VK_FORMAT_B8G8R8_UNORM,
306 		VK_FORMAT_B8G8R8_SNORM,
307 		VK_FORMAT_B8G8R8_USCALED,
308 		VK_FORMAT_B8G8R8_SSCALED,
309 		VK_FORMAT_B8G8R8_UINT,
310 		VK_FORMAT_B8G8R8_SINT,
311 		VK_FORMAT_B8G8R8_SRGB,
312 		VK_FORMAT_R8G8B8A8_UNORM,
313 		VK_FORMAT_R8G8B8A8_SNORM,
314 		VK_FORMAT_R8G8B8A8_USCALED,
315 		VK_FORMAT_R8G8B8A8_SSCALED,
316 		VK_FORMAT_R8G8B8A8_UINT,
317 		VK_FORMAT_R8G8B8A8_SINT,
318 		VK_FORMAT_R8G8B8A8_SRGB,
319 		VK_FORMAT_B8G8R8A8_UNORM,
320 		VK_FORMAT_B8G8R8A8_SNORM,
321 		VK_FORMAT_B8G8R8A8_USCALED,
322 		VK_FORMAT_B8G8R8A8_SSCALED,
323 		VK_FORMAT_B8G8R8A8_UINT,
324 		VK_FORMAT_B8G8R8A8_SINT,
325 		VK_FORMAT_B8G8R8A8_SRGB,
326 		VK_FORMAT_A8B8G8R8_UNORM_PACK32,
327 		VK_FORMAT_A8B8G8R8_SNORM_PACK32,
328 		VK_FORMAT_A8B8G8R8_USCALED_PACK32,
329 		VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
330 		VK_FORMAT_A8B8G8R8_UINT_PACK32,
331 		VK_FORMAT_A8B8G8R8_SINT_PACK32,
332 		VK_FORMAT_A8B8G8R8_SRGB_PACK32,
333 		VK_FORMAT_A2R10G10B10_UNORM_PACK32,
334 		VK_FORMAT_A2R10G10B10_SNORM_PACK32,
335 		VK_FORMAT_A2R10G10B10_USCALED_PACK32,
336 		VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
337 		VK_FORMAT_A2R10G10B10_UINT_PACK32,
338 		VK_FORMAT_A2R10G10B10_SINT_PACK32,
339 		VK_FORMAT_A2B10G10R10_UNORM_PACK32,
340 		VK_FORMAT_A2B10G10R10_SNORM_PACK32,
341 		VK_FORMAT_A2B10G10R10_USCALED_PACK32,
342 		VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
343 		VK_FORMAT_A2B10G10R10_UINT_PACK32,
344 		VK_FORMAT_A2B10G10R10_SINT_PACK32,
345 		VK_FORMAT_R16_UNORM,
346 		VK_FORMAT_R16_SNORM,
347 		VK_FORMAT_R16_USCALED,
348 		VK_FORMAT_R16_SSCALED,
349 		VK_FORMAT_R16_UINT,
350 		VK_FORMAT_R16_SINT,
351 		VK_FORMAT_R16_SFLOAT,
352 		VK_FORMAT_R16G16_UNORM,
353 		VK_FORMAT_R16G16_SNORM,
354 		VK_FORMAT_R16G16_USCALED,
355 		VK_FORMAT_R16G16_SSCALED,
356 		VK_FORMAT_R16G16_UINT,
357 		VK_FORMAT_R16G16_SINT,
358 		VK_FORMAT_R16G16_SFLOAT,
359 		VK_FORMAT_R16G16B16_UNORM,
360 		VK_FORMAT_R16G16B16_SNORM,
361 		VK_FORMAT_R16G16B16_USCALED,
362 		VK_FORMAT_R16G16B16_SSCALED,
363 		VK_FORMAT_R16G16B16_UINT,
364 		VK_FORMAT_R16G16B16_SINT,
365 		VK_FORMAT_R16G16B16_SFLOAT,
366 		VK_FORMAT_R16G16B16A16_UNORM,
367 		VK_FORMAT_R16G16B16A16_SNORM,
368 		VK_FORMAT_R16G16B16A16_USCALED,
369 		VK_FORMAT_R16G16B16A16_SSCALED,
370 		VK_FORMAT_R16G16B16A16_UINT,
371 		VK_FORMAT_R16G16B16A16_SINT,
372 		VK_FORMAT_R16G16B16A16_SFLOAT,
373 		VK_FORMAT_R32_UINT,
374 		VK_FORMAT_R32_SINT,
375 		VK_FORMAT_R32_SFLOAT,
376 		VK_FORMAT_R32G32_UINT,
377 		VK_FORMAT_R32G32_SINT,
378 		VK_FORMAT_R32G32_SFLOAT,
379 		VK_FORMAT_R32G32B32_UINT,
380 		VK_FORMAT_R32G32B32_SINT,
381 		VK_FORMAT_R32G32B32_SFLOAT,
382 		VK_FORMAT_R32G32B32A32_UINT,
383 		VK_FORMAT_R32G32B32A32_SINT,
384 		VK_FORMAT_R32G32B32A32_SFLOAT,
385 		VK_FORMAT_R64_UINT,
386 		VK_FORMAT_R64_SINT,
387 		VK_FORMAT_R64_SFLOAT,
388 		VK_FORMAT_R64G64_UINT,
389 		VK_FORMAT_R64G64_SINT,
390 		VK_FORMAT_R64G64_SFLOAT,
391 		VK_FORMAT_R64G64B64_UINT,
392 		VK_FORMAT_R64G64B64_SINT,
393 		VK_FORMAT_R64G64B64_SFLOAT,
394 		VK_FORMAT_R64G64B64A64_UINT,
395 		VK_FORMAT_R64G64B64A64_SINT,
396 		VK_FORMAT_R64G64B64A64_SFLOAT,
397 		VK_FORMAT_B10G11R11_UFLOAT_PACK32,
398 		VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
399 		VK_FORMAT_D16_UNORM,
400 		VK_FORMAT_X8_D24_UNORM_PACK32,
401 		VK_FORMAT_D32_SFLOAT,
402 		VK_FORMAT_S8_UINT,
403 		VK_FORMAT_D16_UNORM_S8_UINT,
404 		VK_FORMAT_D24_UNORM_S8_UINT,
405 		VK_FORMAT_D32_SFLOAT_S8_UINT,
406 		VK_FORMAT_BC1_RGB_UNORM_BLOCK,
407 		VK_FORMAT_BC1_RGB_SRGB_BLOCK,
408 		VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
409 		VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
410 		VK_FORMAT_BC2_UNORM_BLOCK,
411 		VK_FORMAT_BC2_SRGB_BLOCK,
412 		VK_FORMAT_BC3_UNORM_BLOCK,
413 		VK_FORMAT_BC3_SRGB_BLOCK,
414 		VK_FORMAT_BC4_UNORM_BLOCK,
415 		VK_FORMAT_BC4_SNORM_BLOCK,
416 		VK_FORMAT_BC5_UNORM_BLOCK,
417 		VK_FORMAT_BC5_SNORM_BLOCK,
418 		VK_FORMAT_BC6H_UFLOAT_BLOCK,
419 		VK_FORMAT_BC6H_SFLOAT_BLOCK,
420 		VK_FORMAT_BC7_UNORM_BLOCK,
421 		VK_FORMAT_BC7_SRGB_BLOCK,
422 		VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
423 		VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
424 		VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
425 		VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
426 		VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
427 		VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
428 		VK_FORMAT_EAC_R11_UNORM_BLOCK,
429 		VK_FORMAT_EAC_R11_SNORM_BLOCK,
430 		VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
431 		VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
432 		VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
433 		VK_FORMAT_ASTC_4x4_SRGB_BLOCK,
434 		VK_FORMAT_ASTC_5x4_UNORM_BLOCK,
435 		VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
436 		VK_FORMAT_ASTC_5x5_UNORM_BLOCK,
437 		VK_FORMAT_ASTC_5x5_SRGB_BLOCK,
438 		VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
439 		VK_FORMAT_ASTC_6x5_SRGB_BLOCK,
440 		VK_FORMAT_ASTC_6x6_UNORM_BLOCK,
441 		VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
442 		VK_FORMAT_ASTC_8x5_UNORM_BLOCK,
443 		VK_FORMAT_ASTC_8x5_SRGB_BLOCK,
444 		VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
445 		VK_FORMAT_ASTC_8x6_SRGB_BLOCK,
446 		VK_FORMAT_ASTC_8x8_UNORM_BLOCK,
447 		VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
448 		VK_FORMAT_ASTC_10x5_UNORM_BLOCK,
449 		VK_FORMAT_ASTC_10x5_SRGB_BLOCK,
450 		VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
451 		VK_FORMAT_ASTC_10x6_SRGB_BLOCK,
452 		VK_FORMAT_ASTC_10x8_UNORM_BLOCK,
453 		VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
454 		VK_FORMAT_ASTC_10x10_UNORM_BLOCK,
455 		VK_FORMAT_ASTC_10x10_SRGB_BLOCK,
456 		VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
457 		VK_FORMAT_ASTC_12x10_SRGB_BLOCK,
458 		VK_FORMAT_ASTC_12x12_UNORM_BLOCK,
459 		VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
460 		VK_FORMAT_G8B8G8R8_422_UNORM,
461 		VK_FORMAT_B8G8R8G8_422_UNORM,
462 		VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
463 		VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
464 		VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
465 		VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
466 		VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
467 		VK_FORMAT_R10X6_UNORM_PACK16,
468 		VK_FORMAT_R10X6G10X6_UNORM_2PACK16,
469 		VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,
470 		VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,
471 		VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,
472 		VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16,
473 		VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
474 		VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16,
475 		VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
476 		VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
477 		VK_FORMAT_R12X4_UNORM_PACK16,
478 		VK_FORMAT_R12X4G12X4_UNORM_2PACK16,
479 		VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,
480 		VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,
481 		VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,
482 		VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16,
483 		VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
484 		VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16,
485 		VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16,
486 		VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16,
487 		VK_FORMAT_G16B16G16R16_422_UNORM,
488 		VK_FORMAT_B16G16R16G16_422_UNORM,
489 		VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM,
490 		VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
491 		VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM,
492 		VK_FORMAT_G16_B16R16_2PLANE_422_UNORM,
493 		VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM,
494 		VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,
495 		VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,
496 		VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG,
497 		VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG,
498 		VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,
499 		VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,
500 		VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG,
501 		VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG
502 	};
503 	int										formatCount						= (int)(sizeof(formatlist) / sizeof(unsigned int));
504 
505 	// If ycbcr is not supported, only use the standard texture formats
506 	if (!isYcbcrSupported)
507 		formatCount = 184;
508 
509 	// Find supported image formats
510 	for (int i = 0; i < formatCount; i++)
511 	{
512 		vk::VkImageFormatProperties imageformatprops;
513 
514 		// Check for support in linear tiling mode
515 		if (m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(
516 			m_context.getPhysicalDevice(),
517 			(VkFormat)formatlist[i],
518 			VK_IMAGE_TYPE_2D,
519 			VK_IMAGE_TILING_LINEAR,
520 			VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
521 			0,
522 			&imageformatprops) == VK_SUCCESS)
523 			linearFormats.push_back(formatlist[i]);
524 
525 		// Check for support in optimal tiling mode
526 		if (m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(
527 			m_context.getPhysicalDevice(),
528 			(VkFormat)formatlist[i],
529 			VK_IMAGE_TYPE_2D,
530 			VK_IMAGE_TILING_OPTIMAL,
531 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
532 			0,
533 			&imageformatprops) == VK_SUCCESS)
534 			optimalFormats.push_back(formatlist[i]);
535 	}
536 
537 	// Check for supported heap types
538 	m_context.getInstanceInterface().getPhysicalDeviceMemoryProperties(m_context.getPhysicalDevice(), &memProperties);
539 
540 	for (unsigned int j = 0; j < legalMemoryTypeCount; j++)
541 	{
542 		bool found = false;
543 		for (unsigned int i = 0; !found && i < memProperties.memoryTypeCount; i++)
544 		{
545 			if (legalMemoryTypes[j].matchesHeap(memProperties.memoryTypes[i].propertyFlags))
546 			{
547 				memoryTypes.push_back(j);
548 				found = true;
549 			}
550 		}
551 	}
552 
553 	// Log the used image types and heap types
554 	tcu::TestLog& log = m_context.getTestContext().getLog();
555 
556 	{
557 		std::ostringstream values;
558 		for (unsigned int i = 0; i < linearFormats.size(); i++)
559 			values << " " << linearFormats[i];
560 		log << tcu::TestLog::Message << "Using linear formats:" << values.str() << tcu::TestLog::EndMessage;
561 	}
562 
563 	{
564 		std::ostringstream values;
565 		for (unsigned int i = 0; i < optimalFormats.size(); i++)
566 			values << " " << optimalFormats[i];
567 		log << tcu::TestLog::Message << "Using optimal formats:" << values.str() << tcu::TestLog::EndMessage;
568 	}
569 
570 	{
571 		std::ostringstream values;
572 		for (unsigned int i = 0; i < memoryTypes.size(); i++)
573 			values << " " << memoryTypes[i];
574 		log << tcu::TestLog::Message << "Using memory types:" << values.str() << tcu::TestLog::EndMessage;
575 	}
576 
577 	for (unsigned int i = 0; i < testCycles; i++)
578 	{
579 		if (deRandom_getBool(&m_random))
580 			objs[i] = new BufferAllocator(m_random, isDedicatedAllocationSupported, memoryTypes);
581 		else
582 			objs[i] = new ImageAllocator(m_random, isDedicatedAllocationSupported, linearFormats, optimalFormats, memoryTypes);
583 		order[i] = i;
584 	}
585 
586 	// First get reference values for the object sizes
587 	for (unsigned int i = 0; i < testCycles; i++)
588 	{
589 		objs[i]->allocate(m_context);
590 		refSizes[i] = objs[i]->getSize(m_context);
591 		objs[i]->deallocate(m_context);
592 	}
593 
594 	// Shuffle order by swapping random pairs
595 	for (unsigned int i = 0; i < testCycles; i++)
596 	{
597 		int a = deRandom_getUint32(&m_random) % testCycles;
598 		int b = deRandom_getUint32(&m_random) % testCycles;
599 		DE_SWAP(int, order[a], order[b]);
600 	}
601 
602 	// Allocate objects in shuffled order
603 	for (unsigned int i = 0; i < testCycles; i++)
604 		objs[order[i]]->allocate(m_context);
605 
606 	// Check for size mismatches
607 	for (unsigned int i = 0; i < testCycles; i++)
608 	{
609 		size_t val = objs[order[i]]->getSize(m_context);
610 
611 		if (val != refSizes[order[i]])
612 		{
613 			success = false;
614 			log	<< tcu::TestLog::Message
615 				<< "Object "
616 				<< order[i]
617 				<< " size mismatch ("
618 				<< val
619 				<< " != "
620 				<< refSizes[order[i]]
621 				<< ")"
622 				<< tcu::TestLog::EndMessage;
623 		}
624 	}
625 
626 	// Clean up
627 	for (unsigned int i = 0; i < testCycles; i++)
628 		objs[order[i]]->deallocate(m_context);
629 
630 	if (success)
631 		return tcu::TestStatus::pass("Pass");
632 
633 	return tcu::TestStatus::fail("One or more allocation is not invariant");
634 }
635 
636 class InvarianceCase : public vkt::TestCase
637 {
638 public:
639 							InvarianceCase	(tcu::TestContext&	testCtx,
640 											 const std::string&	name,
641 											 const std::string&	description);
642 	virtual					~InvarianceCase	(void);
643 
644 	virtual TestInstance*	createInstance	(Context&			context) const;
645 };
646 
InvarianceCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description)647 InvarianceCase::InvarianceCase	(tcu::TestContext&	testCtx,
648 								 const std::string&	name,
649 								 const std::string&	description)
650 	: vkt::TestCase(testCtx, name, description)
651 {
652 }
653 
~InvarianceCase()654 InvarianceCase::~InvarianceCase()
655 {
656 }
657 
createInstance(Context & context) const658 TestInstance* InvarianceCase::createInstance (Context& context) const
659 {
660 	return new InvarianceInstance(context, 0x600613);
661 }
662 
createMemoryRequirementInvarianceTests(tcu::TestContext & testCtx)663 tcu::TestCaseGroup* createMemoryRequirementInvarianceTests (tcu::TestContext& testCtx)
664 {
665 	de::MovePtr<tcu::TestCaseGroup> invarianceTests(new tcu::TestCaseGroup(testCtx, "invariance", "Memory requirement invariance tests"));
666 
667 	// Only one child, leaving room for potential targeted cases later on.
668 	invarianceTests->addChild(new InvarianceCase(testCtx, "random", std::string("Random case")));
669 
670 	return invarianceTests.release();
671 }
672 
673 } // api
674 } // vkt
675