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