• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 The Khronos Group Inc.
6  * Copyright (c) 2016 The Android Open Source Project
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  * \file
22 * \brief Cover for non-zero of memoryTypeBits from vkGetBufferMemoryRequirements*() tests.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktApiBufferMemoryRequirementsTests.hpp"
26 #include "vktApiBufferMemoryRequirementsTestsUtils.hpp"
27 #include "vktCustomInstancesDevices.hpp"
28 
29 #include "vkMemUtil.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkTypeUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "deFilePath.hpp"
35 #include "tcuTestLog.hpp"
36 #include "tcuCommandLine.hpp"
37 
38 #include <algorithm>
39 #include <array>
40 #include <functional>
41 #include <iostream>
42 #include <set>
43 #include <sstream>
44 #include <tuple>
45 #include <vector>
46 
47 namespace vkt
48 {
49 namespace api
50 {
51 namespace
52 {
53 
54 using namespace de;
55 using namespace vk;
56 using namespace tcu;
57 
58 struct TestConfig;
59 struct InstanceConfig;
60 
61 enum BufferFateFlagBits
62 {
63 	Transfer		= 0x01,
64 	Storage			= 0x02,
65 	Other			= 0x04,
66 	AccStructure	= 0x08,
67 	Video			= 0x10
68 };
69 typedef deUint32	BufferFateFlags;
70 typedef typename std::add_pointer<typename std::add_const<char>::type>::type	cstr;
71 typedef u::BitsSet<BufferFateFlags, BufferFateFlagBits, cstr> BufferFateBits;
72 
73 const BufferFateBits	AvailableBufferFateBits
74 {
75 	std::make_tuple(Transfer,		"transfer_usage_bits"	),
76 	std::make_tuple(Storage,		"storage_usage_bits"	),
77 	std::make_tuple(Other,			"other_usage_bits"		),
78 	std::make_tuple(AccStructure,	"acc_struct_usage_bits"	),
79 	std::make_tuple(Video,			"video_usage_bits"		),
80 };
81 
82 typedef u::BitsSet<VkBufferCreateFlags, VkBufferCreateFlagBits, cstr>				BufferCreateBits;
83 typedef u::BitsSet<VkBufferUsageFlags, VkBufferUsageFlagBits, BufferFateFlagBits>	BufferUsageBits;
84 typedef u::BitsSet<VkExternalMemoryHandleTypeFlags,
85 					VkExternalMemoryHandleTypeFlagBits, cstr, bool>					ExternalMemoryHandleBits;
86 typedef SharedPtr<BufferCreateBits>			BufferCreateBitsPtr;
87 typedef SharedPtr<BufferUsageBits>			BufferUsageBitsPtr;
88 typedef SharedPtr<ExternalMemoryHandleBits>	ExternalMemoryHandleBitsPtr;
89 
90 struct TestConfig
91 {
92 	bool						useMethod2;
93 	SharedPtr<BufferCreateBits>	createBits;
94 	SharedPtr<BufferFateBits>	fateBits;
95 	bool						incExtMemTypeFlags;
96 	// Tests the buffer memory size requirement is less than or equal to the aligned size of the buffer.
97 	// Requires VK_KHR_maintenance4 extension.
98 	bool						testSizeRequirements;
99 };
100 struct InstanceConfig
101 {
102 	bool												useMethod2;
103 	SharedPtr<BufferCreateBits>							createBits;
104 	SharedPtr<BufferFateBits>							fateBits;
105 	SharedPtr<std::vector<BufferUsageBitsPtr>>			usageFlags;
106 	bool												incExtMemTypeFlags;
107 	SharedPtr<std::vector<ExternalMemoryHandleBitsPtr>>	extMemHandleFlags;
108 	bool												testSizeRequirements;
109 
InstanceConfigvkt::api::__anon384aa0210111::InstanceConfig110 	InstanceConfig(const TestConfig& conf)
111 		: useMethod2			(conf.useMethod2)
112 		, createBits			(conf.createBits)
113 		, fateBits				(conf.fateBits)
114 		, usageFlags			(new std::vector<SharedPtr<BufferUsageBits>>)
115 		, incExtMemTypeFlags	(conf.incExtMemTypeFlags)
116 		, extMemHandleFlags		(new std::vector<SharedPtr<ExternalMemoryHandleBits>>)
117 		, testSizeRequirements	(conf.testSizeRequirements) {}
118 };
119 
120 const BufferCreateBits	AvailableBufferCreateBits
121 {
122 	std::make_tuple( VkBufferCreateFlagBits(0),				"no_flags"				),
123 	std::make_tuple( VK_BUFFER_CREATE_PROTECTED_BIT,			"protected"			),
124 #ifndef CTS_USES_VULKANSC
125 	std::make_tuple( VK_BUFFER_CREATE_SPARSE_BINDING_BIT,		"sparse_binding"	),
126 	std::make_tuple( VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,	"sparse_residency"		),
127 	std::make_tuple( VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,		"sparse_aliased"	),
128 #endif // CTS_USES_VULKANSC
129 };
130 
131 const BufferUsageBits	AvailableBufferUsageBits
132 {
133 	std::make_tuple( VK_BUFFER_USAGE_TRANSFER_SRC_BIT										, Transfer		),
134 	std::make_tuple( VK_BUFFER_USAGE_TRANSFER_DST_BIT										, Transfer		),
135 	std::make_tuple( VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT								, Storage		),
136 	std::make_tuple( VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT								, Storage		),
137 	std::make_tuple( VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT										, Storage		),
138 	std::make_tuple( VK_BUFFER_USAGE_STORAGE_BUFFER_BIT										, Storage		),
139 	std::make_tuple( VK_BUFFER_USAGE_INDEX_BUFFER_BIT										, Storage		),
140 	std::make_tuple( VK_BUFFER_USAGE_VERTEX_BUFFER_BIT										, Storage		),
141 	std::make_tuple( VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT									, Other			),
142 	std::make_tuple( VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT								, Other			),
143 #ifndef CTS_USES_VULKANSC
144 	std::make_tuple( VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR								, Video			),
145 	std::make_tuple( VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR								, Video			),
146 	std::make_tuple( VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT						, Other			),
147 	std::make_tuple( VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT				, Other			),
148 	std::make_tuple( VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT							, Other			),
149 	std::make_tuple( VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR	, AccStructure	),
150 	std::make_tuple( VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR					, AccStructure	),
151 	std::make_tuple( VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR							, AccStructure	),
152 	std::make_tuple( VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR								, Video			),
153 	std::make_tuple( VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR								, Video			),
154 #endif // CTS_USES_VULKANSC
155 };
156 
157 #define INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS VkExternalMemoryHandleTypeFlagBits(0)
158 const ExternalMemoryHandleBits	AvailableExternalMemoryHandleBits
159 {
160 	std::make_tuple( INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS						, "no_flags",			false ),
161 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT							, "opaque_fd",			false ),
162 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT						, "opaque_win32",		false ),
163 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT					, "opaque_win32_kmt",	false ),
164 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT						, "d3d11_tex",			false ),
165 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT					, "d3d11_tex_kmt",		false ),
166 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT							, "d3d12_heap",			false ),
167 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT						, "d3d12_rsrc",			false ),
168 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT							, "dma_buf",			false ),
169 #ifndef CTS_USES_VULKANSC
170 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID		, "android_hw",			false ),
171 #endif // CTS_USES_VULKANSC
172 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT					, "host_alloc",			true  ),
173 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT		, "host_mapped",		true  ),
174 #ifndef CTS_USES_VULKANSC
175 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA					, "zircon_vmo",			false ),
176 	std::make_tuple( VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV						, "roma_addr",			false ),
177 #endif // CTS_USES_VULKANSC
178 };
179 
180 template<class Flag, class Bit, class Str, class... Ignored>
bitsToString(const u::BitsSet<Flag,Bit,Str,Ignored...> & bits,const std::string & prefix=std::string ())181 std::string bitsToString (const u::BitsSet<Flag, Bit, Str, Ignored...>& bits,
182 						  const std::string& prefix = std::string())
183 {
184 	DE_ASSERT(!bits.empty());
185 	std::stringstream s;
186 	s << prefix;
187 	bool atLeastOne = false;
188 	for (const auto& bit : bits) {
189 		if (atLeastOne) s << '_';
190 		s << std::get<1>(bit);
191 		atLeastOne = true;
192 	}
193 	return s.str();
194 }
195 
updateBufferCreateFlags(std::vector<BufferCreateBits> & flags)196 void updateBufferCreateFlags(std::vector<BufferCreateBits>& flags)
197 {
198 #ifndef CTS_USES_VULKANSC
199 	const auto&	residencyBit	= AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT);
200 	const auto&	aliasedBit		= AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT);
201 	const auto&	bindingBit		= AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_BINDING_BIT);
202 	const auto&	protectedBit	= AvailableBufferCreateBits.get(VK_BUFFER_CREATE_PROTECTED_BIT);
203 #endif // CTS_USES_VULKANSC
204 	const auto&	noneBit			= AvailableBufferCreateBits.get(VkBufferCreateFlagBits(0));
205 
206 #ifndef CTS_USES_VULKANSC
207 	// VUID-VkBufferCreateInfo-flags-00918 { if sparse residency or sparse aliased include sparse binding }
208 	for (auto& bits : flags)
209 	{
210 		if (bits.contains(residencyBit) || bits.contains(aliasedBit))
211 			bits.insert(bindingBit);
212 	}
213 
214 	// VUID-VkBufferCreateInfo-None-01888 { if sparse residency, sparse aliased or sparse binding then flags must not include protected }
215 	const typename BufferCreateBits::key_type disallowdBits[] { residencyBit, aliasedBit, bindingBit };
216 	for (auto i = flags.begin(); i != flags.end();)
217 	{
218 		auto& bits = *i;
219 		if (bits.contains(protectedBit))
220 		{
221 			for (const auto& disallowdBit : disallowdBits)
222 			{
223 				auto find = bits.find(disallowdBit);
224 				if (find != bits.end())
225 					bits.erase(find);
226 			}
227 		}
228 		i = bits.empty() ? flags.erase(i) : std::next(i);
229 	}
230 #endif // CTS_USES_VULKANSC
231 
232 	// since 0 is a valid VkBufferCreateFlagBits flag then remove it flags where it exists along with other non-zero flags
233 	for (auto i = flags.begin(); i != flags.end(); ++i)
234 	{
235 		auto& bits = *i;
236 		auto find = bits.find(noneBit);
237 		if (find != bits.end() && bits.size() > 1)
238 		{
239 			bits.erase(find);
240 		}
241 	}
242 
243 	// remove duplicates
244 	for (auto i = flags.begin(); i != flags.end(); ++i)
245 	{
246 		for (auto j = std::next(i); j != flags.end();)
247 			j = (*i == *j) ? flags.erase(j) : std::next(j);
248 	}
249 }
250 
251 class BufferMemoryRequirementsInstance : public TestInstance
252 {
253 public:
BufferMemoryRequirementsInstance(Context & context,const InstanceConfig config)254 							BufferMemoryRequirementsInstance	(Context&				context,
255 																 const InstanceConfig	config)
256 								: TestInstance	(context)
257 								, m_config		(config) {}
258 
259 	virtual					~BufferMemoryRequirementsInstance	(void) override = default;
260 	virtual tcu::TestStatus	iterate								(void) override;
261 
262 	void						getBufferMemoryRequirements		(VkMemoryRequirements&	result,
263 																 const DeviceInterface&	vkd,
264 																 VkDevice				device,
265 																 VkBuffer				buffer) const;
266 	void						getBufferMemoryRequirements2	(VkMemoryRequirements&	result,
267 																 const DeviceInterface&	vkd,
268 																 VkDevice				device,
269 																 VkBuffer				buffer) const;
270 	typedef void (BufferMemoryRequirementsInstance::* Method)	(VkMemoryRequirements&	result,
271 																 const DeviceInterface&	intf,
272 																 VkDevice				device,
273 																 VkBuffer				buffer) const;
274 	template<class T, class... AddArgs>
275 						void*	chainVkStructure				(void*					pNext,
276 																 const AddArgs&...		addArgs) const;
277 private:
278 	void						logFailedSubtests				(const std::vector<BufferCreateBitsPtr>&			failCreateBits,
279 																 const std::vector<BufferUsageBitsPtr>&				failUsageBits,
280 																 const std::vector<ExternalMemoryHandleBitsPtr>&	failExtMemHandleBits) const;
281 	const InstanceConfig	m_config;
282 };
283 
284 class MemoryRequirementsTest : public TestCase
285 {
286 public:
MemoryRequirementsTest(TestContext & testCtx,const std::string & name,const TestConfig testConfig)287 							MemoryRequirementsTest	(TestContext&			testCtx,
288 													 const std::string&		name,
289 													 const TestConfig		testConfig)
290 								: TestCase		(testCtx, name)
291 								, m_testConfig	(testConfig)
292 								, m_instConfig	(testConfig) {}
293 
294 	virtual					~MemoryRequirementsTest	(void) override = default;
295 	virtual void			checkSupport			(Context&				context) const override;
createInstance(Context & context) const296 	virtual TestInstance*	createInstance			(Context&				context) const override
297 	{
298 		return new BufferMemoryRequirementsInstance(context, m_instConfig);
299 	}
300 
301 private:
302 	const TestConfig	m_testConfig;
303 	InstanceConfig		m_instConfig;
304 };
305 
306 struct Info
307 {
308 	enum Type {
309 		Create,
310 		Usage
311 	}					m_type;
312 	std::ostringstream	m_str;
313 	cstr				m_file;
314 	int					m_line;
Infovkt::api::__anon384aa0210111::Info315 	template<class Msg>	Info(Type type, const Msg& msg, cstr file, int line)
316 		: m_type(type), m_str(), m_file(file), m_line(line) { m_str << msg; }
operator <<(std::ostringstream & str,const Info & info)317 	friend std::ostringstream& operator<<(std::ostringstream& str, const Info& info) {
318 		switch (info.m_type) {
319 		case Create:
320 			str << "Create buffer with " << info.m_str.str() << " not supported by device at "
321 				<< de::FilePath(info.m_file).getBaseName() << ":" << info.m_line;
322 			break;
323 		case Usage:
324 			str << info.m_str.str() << " at "
325 				<< de::FilePath(info.m_file).getBaseName() << ":" << info.m_line;
326 			break;
327 		}
328 		return str;
329 	}
330 };
331 #define INFOCREATE(msg_) Info(Info::Create, (msg_), __FILE__, __LINE__)
332 #define INFOUSAGE(msg_) Info(Info::Usage, (msg_), __FILE__, __LINE__)
333 
334 #ifndef CTS_USES_VULKANSC
readVideoCodecOperationFlagsKHR(const InstanceInterface & vki,const VkPhysicalDevice & device)335 VkVideoCodecOperationFlagsKHR readVideoCodecOperationFlagsKHR (const InstanceInterface& vki, const VkPhysicalDevice& device)
336 {
337 	uint32_t	queueFamilyPropertyCount = 0;
338 	vki.getPhysicalDeviceQueueFamilyProperties2(device, &queueFamilyPropertyCount, nullptr);
339 	DE_ASSERT(queueFamilyPropertyCount);
340 
341 	std::vector<VkQueueFamilyVideoPropertiesKHR>	videoQueueFamilyProperties(
342 														queueFamilyPropertyCount,
343 														{
344 														   VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR,		// VkStructureType					sType
345 														   nullptr,													// void*							pNext
346 														   0														// VkVideoCodecOperationFlagsKHR	videoCodecOperations
347 														});
348 	std::vector<VkQueueFamilyProperties2>			queueFamilyProperties(
349 														queueFamilyPropertyCount,
350 														{
351 															VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2,			// VkStructureType					sType
352 															nullptr,												// void*							pNext
353 															{}														// VkQueueFamilyProperties			queueFamilyProperties
354 														});
355 	for (auto begin = queueFamilyProperties.begin(), i = begin, end = queueFamilyProperties.end(); i != end; ++i)
356 	{
357 		i->pNext = &videoQueueFamilyProperties.data()[std::distance(begin, i)];
358 	}
359 
360 	vki.getPhysicalDeviceQueueFamilyProperties2(device, &queueFamilyPropertyCount, queueFamilyProperties.data());
361 
362 	VkVideoCodecOperationFlagsKHR	codecOperationFlags = VK_VIDEO_CODEC_OPERATION_NONE_KHR;
363 	for (const VkQueueFamilyVideoPropertiesKHR& props : videoQueueFamilyProperties)
364 	{
365 		codecOperationFlags |= props.videoCodecOperations;
366 	}
367 
368 	return codecOperationFlags;
369 }
370 #endif // CTS_USES_VULKANSC
371 
checkSupport(Context & context) const372 void MemoryRequirementsTest::checkSupport (Context& context) const
373 {
374 	const InstanceInterface&						intf				= context.getInstanceInterface();
375 	const VkPhysicalDevice							physDevice			= context.getPhysicalDevice();
376 	auto&											log					= context.getTestContext().getLog();
377 
378 	context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
379 
380 	if (m_testConfig.useMethod2)
381 		context.requireDeviceFunctionality("VK_KHR_get_memory_requirements2");
382 
383 	VkPhysicalDeviceProtectedMemoryFeatures			protectedMemFeatures
384 	{
385 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,	// VkStructureType	sType;
386 		nullptr,															// void*			pNext;
387 		VK_FALSE															// VkBool32			protectedMemory;
388 	};
389 	VkPhysicalDeviceFeatures2						extFeatures
390 	{
391 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,					// VkStructureType			sType;
392 		&protectedMemFeatures,												// void*					pNext;
393 		{}																	// VkPhysicalDeviceFeatures	features;
394 	};
395 	intf.getPhysicalDeviceFeatures2(physDevice, &extFeatures);
396 
397 	const VkPhysicalDeviceFeatures&	features					= extFeatures.features;
398 	const VkBool32&					protectedMemFeatureEnabled	= protectedMemFeatures.protectedMemory;
399 
400 	// check the creating bits
401 	{
402 		std::ostringstream			str;
403 		bool		notSupported	= false;
404 		const auto& createBits		= *m_testConfig.createBits;
405 
406 		if (createBits.contains(VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && (VK_FALSE == features.sparseBinding))
407 		{
408 			str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_BINDING_BIT));
409 			notSupported = true;
410 		}
411 		if (createBits.contains(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && (VK_FALSE == features.sparseResidencyBuffer))
412 		{
413 			if (notSupported) str << std::endl;
414 			str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT));
415 			notSupported = true;
416 		}
417 		if (createBits.contains(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && (VK_FALSE == features.sparseResidencyAliased))
418 		{
419 			if (notSupported) str << std::endl;
420 			str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT));
421 			notSupported = true;
422 		}
423 		if (createBits.contains(VK_BUFFER_CREATE_PROTECTED_BIT) && (VK_FALSE == protectedMemFeatureEnabled))
424 		{
425 			if (notSupported) str << std::endl;
426 			str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_PROTECTED_BIT));
427 			notSupported = true;
428 		}
429 		if (notSupported)
430 		{
431 			log << tcu::TestLog::Message << str.str() << tcu::TestLog::EndMessage;
432 			TCU_THROW(NotSupportedError, "One or more create buffer flags not supported by device (check log for details)");
433 		}
434 	}
435 
436 	// check the usage bits and build instance input
437 	{
438 		std::vector<BufferUsageBits>	usageFlags;
439 		for (const auto& bit : *m_testConfig.fateBits)
440 		{
441 			auto fate = m_testConfig.fateBits->extract(bit);
442 			std::vector<VkBufferUsageFlags>		usageHints;
443 			std::vector<BufferUsageBits>		usageFlagsTmp;
444 			u::combine(usageFlagsTmp, AvailableBufferUsageBits.select<1>(fate), usageHints);
445 			u::mergeFlags(usageFlags, usageFlagsTmp);
446 		}
447 
448 		std::ostringstream str;
449 		std::array<bool, 7> msgs;
450 		bool notSupported	= false;
451 		int  entryCount		= 0;
452 		msgs.fill(false);
453 
454 		for (auto i = usageFlags.begin(); i != usageFlags.end();)
455 		{
456 			notSupported = false;
457 
458 #ifndef CTS_USES_VULKANSC
459 			if (i->any({VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR,
460 					   VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR})
461 					&& !context.isDeviceFunctionalitySupported("VK_KHR_acceleration_structure"))
462 			{
463 				if (!msgs[0])
464 				{
465 					if (entryCount++) str << std::endl;
466 					str << INFOUSAGE("VK_KHR_acceleration_structure not supported by device");
467 					msgs[0] = true;
468 				}
469 				notSupported = true;
470 			}
471 #endif // CTS_USES_VULKANSC
472 
473 			if (i->contains(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
474 					&& !context.isBufferDeviceAddressSupported())
475 			{
476 				if (!msgs[1])
477 				{
478 					if (entryCount++) str << std::endl;
479 					str << INFOUSAGE("VK_EXT_buffer_device_address not supported by device");
480 					msgs[1] = true;
481 				}
482 				notSupported = true;
483 			}
484 
485 #ifndef CTS_USES_VULKANSC
486 			if (i->any({VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR,
487 					   VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR}))
488 			{
489 				if (!context.isDeviceFunctionalitySupported(VK_KHR_VIDEO_QUEUE_EXTENSION_NAME))
490 				{
491 					if (!msgs[2])
492 					{
493 						if (entryCount++) str << std::endl;
494 						str << INFOUSAGE("VK_EXT_video_queue not supported by device");
495 						msgs[2] = true;
496 					}
497 					notSupported = true;
498 				}
499 				else
500 				{
501 					const VkVideoCodecOperationFlagsKHR videoFlags = readVideoCodecOperationFlagsKHR(intf, physDevice);
502 
503 					if (i->any({VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR}))
504 					{
505 						if (!context.isDeviceFunctionalitySupported(VK_EXT_VIDEO_ENCODE_H264_EXTENSION_NAME))
506 						{
507 							if (!msgs[3])
508 							{
509 								if (entryCount++) str << std::endl;
510 								str << INFOUSAGE("VK_EXT_video_encode_h264 not supported by device");
511 								msgs[3] = true;
512 							}
513 							notSupported = true;
514 						}
515 						if (!(videoFlags & VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT))
516 						{
517 							if (!msgs[4])
518 							{
519 								if (entryCount++) str << std::endl;
520 								str << INFOUSAGE("Could not find a queue that supports VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT on device");
521 								msgs[4] = true;
522 							}
523 							notSupported = true;
524 						}
525 					}
526 					if (i->any({VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR}))
527 					{
528 						if (!context.isDeviceFunctionalitySupported(VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME))
529 						{
530 							if (!msgs[5])
531 							{
532 								if (entryCount++) str << std::endl;
533 								str << INFOUSAGE("VK_KHR_video_decode_h264 not supported by device");
534 								msgs[5] = true;
535 							}
536 							notSupported = true;
537 						}
538 						if (!(videoFlags & VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR))
539 						{
540 							if (!msgs[6])
541 							{
542 								if (entryCount++) str << std::endl;
543 								str << INFOUSAGE("Could not find a queue that supports VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR on device");
544 								msgs[6] = true;
545 							}
546 							notSupported = true;
547 						}
548 					}
549 				}
550 			}
551 #endif // CTS_USES_VULKANSC
552 
553 			i = notSupported ? usageFlags.erase(i) : std::next(i);
554 		}
555 
556 		// remove duplicates
557 		for (auto i = usageFlags.begin(); i != usageFlags.end(); ++i)
558 		{
559 			for (auto j = std::next(i); j != usageFlags.end();)
560 				j = (*i == *j) ? usageFlags.erase(j) : std::next(j);
561 		}
562 
563 		if (usageFlags.empty())
564 		{
565 			log << tcu::TestLog::Message << str.str() << tcu::TestLog::EndMessage;
566 			TCU_THROW(NotSupportedError, "One or more buffer usage flags not supported by device (check log for details)");
567 		}
568 		else
569 		{
570 			if (entryCount > 0)
571 			{
572 				log << tcu::TestLog::Message << str.str() << tcu::TestLog::EndMessage;
573 			}
574 			DE_ASSERT(m_instConfig.usageFlags.get());
575 			m_instConfig.usageFlags->resize(usageFlags.size());
576 			std::transform(usageFlags.begin(), usageFlags.end(), m_instConfig.usageFlags->begin(),
577 						   [](BufferUsageBits& bits){ return BufferUsageBits::makeShared(std::move(bits)); });
578 		}
579 	}
580 
581 	// check the external memory handle type bits and build instance input
582 	{
583 		std::vector<ExternalMemoryHandleBits>	extMemHandleFlags;
584 		if (m_testConfig.incExtMemTypeFlags)
585 			extMemHandleFlags.push_back({AvailableExternalMemoryHandleBits.get(INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS)});
586 		else
587 		{
588 			std::vector<VkExternalMemoryHandleTypeFlags>	handleHints;
589 			std::vector<ExternalMemoryHandleBits>			handleFlagsTmp;
590 			u::combine(handleFlagsTmp, AvailableExternalMemoryHandleBits.select<2>(true), handleHints);
591 			u::mergeFlags(extMemHandleFlags, handleFlagsTmp);
592 		}
593 
594 		DE_ASSERT(m_instConfig.extMemHandleFlags.get());
595 		m_instConfig.extMemHandleFlags->resize(extMemHandleFlags.size());
596 		std::transform(extMemHandleFlags.begin(), extMemHandleFlags.end(), m_instConfig.extMemHandleFlags->begin(),
597 					   [](ExternalMemoryHandleBits& bits){ return ExternalMemoryHandleBits::makeShared(std::move(bits)); });
598 	}
599 
600 	if (m_testConfig.testSizeRequirements)
601 	{
602 		if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance4"))
603 			TCU_THROW(NotSupportedError, "VK_KHR_maintenance4 not supported");
604 	}
605 }
606 
logFailedSubtests(const std::vector<BufferCreateBitsPtr> & failCreateBits,const std::vector<BufferUsageBitsPtr> & failUsageBits,const std::vector<ExternalMemoryHandleBitsPtr> & failExtMemHandleBits) const607 void BufferMemoryRequirementsInstance::logFailedSubtests (const std::vector<BufferCreateBitsPtr>&			failCreateBits,
608 														  const std::vector<BufferUsageBitsPtr>&			failUsageBits,
609 														  const std::vector<ExternalMemoryHandleBitsPtr>&	failExtMemHandleBits) const
610 {
611 	const deUint32	flagCount	= deUint32(failCreateBits.size());
612 	TestLog&		log			= m_context.getTestContext().getLog();
613 	deUint32		entries		= 0;
614 
615 	DE_ASSERT(flagCount && flagCount == failUsageBits.size() && flagCount == failExtMemHandleBits.size());
616 
617 	log << TestLog::Section("Failed", "Failed subtests");
618 
619 	for (deUint32 i = 0; i < flagCount; ++i)
620 	{
621 		{
622 			log << TestLog::Section("VkBufferCreateFlags", "Buffer create flags");
623 			auto msg = log << TestLog::Message;
624 			entries = 0;
625 			for (const auto& createBit : *failCreateBits[i])
626 			{
627 				if (entries++) msg << " ";
628 				const VkBufferCreateFlags flags = BufferCreateBits::extract(createBit);
629 				if (flags == 0)
630 					msg << "0";
631 				else msg << getBufferCreateFlagsStr(flags);
632 			}
633 			msg << TestLog::EndMessage << TestLog::EndSection;
634 		}
635 
636 		{
637 			log << TestLog::Section("VkBufferUsageFlags", "Buffer usage flags");
638 			auto msg = log << TestLog::Message;
639 			entries = 0;
640 			for (const auto& usageBit : *failUsageBits[i])
641 			{
642 				if (entries++) msg << " ";
643 				msg << getBufferUsageFlagsStr(BufferUsageBits::extract(usageBit));
644 			}
645 			msg << TestLog::EndMessage << TestLog::EndSection;
646 		}
647 
648 		{
649 			log << TestLog::Section("VkExternalMemoryHandleTypeFlags", "External memory handle type flags");
650 			auto msg = log << TestLog::Message;
651 			entries = 0;
652 			for (const auto& extMemHandleTypeBit : *failExtMemHandleBits[i])
653 			{
654 				if (entries++) msg << " ";
655 				msg << getExternalMemoryHandleTypeFlagsStr(ExternalMemoryHandleBits::extract(extMemHandleTypeBit));
656 			}
657 			msg << TestLog::EndMessage << TestLog::EndSection;
658 		}
659 	}
660 
661 	log << TestLog::EndSection;
662 }
663 
getBufferMemoryRequirements2(VkMemoryRequirements & result,const DeviceInterface & vkd,VkDevice device,VkBuffer buffer) const664 void BufferMemoryRequirementsInstance::getBufferMemoryRequirements2	(VkMemoryRequirements&	result,
665 																	 const DeviceInterface&	vkd,
666 																	 VkDevice				device,
667 																	 VkBuffer				buffer) const
668 {
669 	VkMemoryDedicatedRequirements	dedicatedRequirements	=
670 	{
671 		VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,		// VkStructureType			sType;
672 		nullptr,												// const void*				pNext;
673 		VK_FALSE,												// VkBool32					prefersDedicatedAllocation
674 		VK_FALSE												// VkBool32					requiresDedicatedAllocation
675 	};
676 
677 	VkMemoryRequirements2			desiredRequirements		=
678 	{
679 		VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,				// VkStructureType			sType
680 		&dedicatedRequirements,									// void*					pNext
681 		result													// VkMemoryRequirements		memoryRequirements
682 	};
683 
684 	VkBufferMemoryRequirementsInfo2	requirementsInfo		=
685 	{
686 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,	// VkStructureType			sType
687 		nullptr,												// const void*				pNext
688 		buffer													// VkBuffer					buffer
689 	};
690 
691 	vkd.getBufferMemoryRequirements2(device, &requirementsInfo, &desiredRequirements);
692 
693 	result = desiredRequirements.memoryRequirements;
694 }
695 
getBufferMemoryRequirements(VkMemoryRequirements & result,const DeviceInterface & vkd,VkDevice device,VkBuffer buffer) const696 void BufferMemoryRequirementsInstance::getBufferMemoryRequirements	(VkMemoryRequirements&	result,
697 																	 const DeviceInterface&	vkd,
698 																	 VkDevice				device,
699 																	 VkBuffer				buffer) const
700 {
701 	vkd.getBufferMemoryRequirements(device, buffer, &result);
702 }
703 
704 template<> void*
chainVkStructure(void * pNext,const VkExternalMemoryHandleTypeFlags & handleTypes) const705 BufferMemoryRequirementsInstance::chainVkStructure<VkExternalMemoryBufferCreateInfo> (void* pNext, const VkExternalMemoryHandleTypeFlags& handleTypes) const
706 {
707 	static VkExternalMemoryBufferCreateInfo	memInfo{};
708 	memInfo.sType		= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO;
709 	memInfo.pNext		= pNext;
710 	memInfo.handleTypes	= handleTypes;
711 
712 	return &memInfo;
713 }
714 
715 #ifndef CTS_USES_VULKANSC
chainVkStructure(void * pNext,const VkBufferUsageFlags & videoCodecUsage) const716 template<> void* BufferMemoryRequirementsInstance::chainVkStructure<VkVideoProfileListInfoKHR> (void* pNext, const VkBufferUsageFlags& videoCodecUsage) const
717 {
718 	const bool encode = (videoCodecUsage & VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR) || (videoCodecUsage & VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR);
719 	const bool decode = (videoCodecUsage & VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR) || (videoCodecUsage & VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR);
720 
721 	static VkVideoEncodeH264ProfileInfoEXT	encodeProfile
722 	{
723 		VK_STRUCTURE_TYPE_VIDEO_ENCODE_H264_PROFILE_INFO_EXT,	// VkStructureType						sType;
724 		nullptr,												// const void*							pNext;
725 		STD_VIDEO_H264_PROFILE_IDC_BASELINE						// StdVideoH264ProfileIdc				stdProfileIdc;
726 	};
727 
728 	static VkVideoDecodeH264ProfileInfoKHR	decodeProfile
729 	{
730 		VK_STRUCTURE_TYPE_VIDEO_DECODE_H264_PROFILE_INFO_KHR,	// VkStructureType						sType;
731 		nullptr,												// const void*							pNext;
732 		STD_VIDEO_H264_PROFILE_IDC_BASELINE,					// StdVideoH264ProfileIdc				stdProfileIdc;
733 		VK_VIDEO_DECODE_H264_PICTURE_LAYOUT_PROGRESSIVE_KHR		// VkVideoDecodeH264FieldLayoutFlagsEXT	fieldLayout;
734 	};
735 
736 	static const VkVideoProfileInfoKHR	videoProfiles[]
737 	{
738 		// encode profile
739 		{
740 			VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR,			// VkStructureType						sType;
741 			&encodeProfile,										// void*								pNext;
742 			VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT,		// VkVideoCodecOperationFlagBitsKHR		videoCodecOperation;
743 			VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR,		// VkVideoChromaSubsamplingFlagsKHR		chromaSubsampling;
744 			VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR,				// VkVideoComponentBitDepthFlagsKHR		lumaBitDepth;
745 			VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR				// VkVideoComponentBitDepthFlagsKHR		chromaBitDepth;
746 		},
747 		// decode profile
748 		{
749 			VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR,			// VkStructureType						sType;
750 			&decodeProfile,										// void*								pNext;
751 			VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR,		// VkVideoCodecOperationFlagBitsKHR		videoCodecOperation;
752 			VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR,		// VkVideoChromaSubsamplingFlagsKHR		chromaSubsampling;
753 			VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR,				// VkVideoComponentBitDepthFlagsKHR		lumaBitDepth;
754 			VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR				// VkVideoComponentBitDepthFlagsKHR		chromaBitDepth;
755 		}
756 	};
757 	static VkVideoProfileListInfoKHR	profiles;
758 	profiles.sType			= VK_STRUCTURE_TYPE_VIDEO_PROFILE_LIST_INFO_KHR;
759 	profiles.pNext			= pNext;
760 	if (encode && decode)
761 	{
762 		profiles.profileCount	= 2u;
763 		profiles.pProfiles		= videoProfiles;
764 	}
765 	else if (encode)
766 	{
767 		profiles.profileCount	= 1u;
768 		profiles.pProfiles		= &videoProfiles[0];
769 	}
770 	else
771 	{
772 		profiles.profileCount	= 1u;
773 		profiles.pProfiles		= &videoProfiles[1];
774 	}
775 	return &profiles;
776 }
777 #endif // CTS_USES_VULKANSC
778 
createProtectedDevice(const Context & context)779 static Move<VkDevice> createProtectedDevice(const Context &context)
780 {
781 	auto &cmdLine = context.getTestContext().getCommandLine();
782 	const float queuePriority = 1.0f;
783 
784 	VkPhysicalDeviceProtectedMemoryFeatures protectedMemoryFeatures;
785 	protectedMemoryFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES;
786 	protectedMemoryFeatures.pNext = DE_NULL;
787 	protectedMemoryFeatures.protectedMemory = VK_TRUE;
788 
789 	VkDeviceQueueCreateInfo queueInfo =
790 	{
791 		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	// VkStructureType			sType;
792 		DE_NULL,									// const void*				pNext;
793 		vk::VK_DEVICE_QUEUE_CREATE_PROTECTED_BIT,	// VkDeviceQueueCreateFlags	flags;
794 		context.getUniversalQueueFamilyIndex(),		// deUint32					queueFamilyIndex;
795 		1u,											// deUint32					queueCount;
796 		&queuePriority								// const float*				pQueuePriorities;
797 	};
798 	const VkDeviceCreateInfo deviceInfo =
799 	{
800 		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,	// VkStructureType					sType;
801 		&protectedMemoryFeatures,				// const void*						pNext;
802 		(VkDeviceCreateFlags)0,					// VkDeviceCreateFlags				flags;
803 		1u,										// uint32_t							queueCreateInfoCount;
804 		&queueInfo,								// const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
805 		0u,										// uint32_t							enabledLayerCount;
806 		DE_NULL,								// const char* const*				ppEnabledLayerNames;
807 		0u,										// uint32_t							enabledExtensionCount;
808 		DE_NULL,								// const char* const*				ppEnabledExtensionNames;
809 		DE_NULL									// const VkPhysicalDeviceFeatures*	pEnabledFeatures;
810 	};
811 	return createCustomDevice(cmdLine.isValidationEnabled(), context.getPlatformInterface(), context.getInstance(), context.getInstanceInterface(), context.getPhysicalDevice(), &deviceInfo);
812 }
813 
iterate(void)814 TestStatus	BufferMemoryRequirementsInstance::iterate (void)
815 {
816 	const DeviceInterface&							vkd					= m_context.getDeviceInterface();
817 	const deUint32									queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
818 	const Method									method				= m_config.useMethod2
819 																			? &BufferMemoryRequirementsInstance::getBufferMemoryRequirements2
820 																			: &BufferMemoryRequirementsInstance::getBufferMemoryRequirements;
821 
822 	deUint32										passCount			= 0;
823 	deUint32										failCount			= 0;
824 	std::vector<BufferCreateBitsPtr>				failCreateBits;
825 	std::vector<BufferUsageBitsPtr>					failUsageBits;
826 	std::vector<ExternalMemoryHandleBitsPtr>		failExtMemHandleBits;
827 
828 	Move<VkDevice> protectedDevice;
829 	VkDevice device;
830 	if (m_config.createBits->contains(VK_BUFFER_CREATE_PROTECTED_BIT))
831 	{
832 		protectedDevice = createProtectedDevice(m_context);
833 		device = *protectedDevice;
834 	}
835 	else
836 	{
837 		device = m_context.getDevice();
838 	}
839 
840 	DE_ASSERT(!m_config.createBits->empty());
841 	const VkBufferCreateFlags infoCreateFlags = *m_config.createBits;
842 	{
843 		DE_ASSERT(!m_config.usageFlags->empty());
844 		for (auto u = m_config.usageFlags->cbegin(); u != m_config.usageFlags->cend(); ++u)
845 		{
846 			const VkBufferUsageFlags infoUsageFlags = *(u->get());
847 
848 			DE_ASSERT(!m_config.extMemHandleFlags->empty());
849 			for (auto m = m_config.extMemHandleFlags->cbegin(); m != m_config.extMemHandleFlags->cend(); ++m)
850 			{
851 				const VkExternalMemoryHandleTypeFlags handleFlags = *(m->get());
852 
853 				void* pNext = nullptr;
854 
855 #ifndef CTS_USES_VULKANSC
856 				if (m_config.fateBits->contains(BufferFateFlagBits::Video))
857 				{
858 					pNext = chainVkStructure<VkVideoProfileListInfoKHR>(pNext, infoUsageFlags);
859 				}
860 #endif // CTS_USES_VULKANSC
861 				if (m_config.incExtMemTypeFlags)
862 				{
863 					pNext = chainVkStructure<VkExternalMemoryBufferCreateInfo>(pNext, handleFlags);
864 				}
865 				VkBufferCreateInfo	createInfo
866 				{
867 					VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,					// VkStructureType					sType;
868 					pNext,													// const void*						pNext;
869 					infoCreateFlags,										// VkBufferCreateFlags				flags;
870 					4096u,													// VkDeviceSize						size;
871 					infoUsageFlags,											// VkBufferUsageFlags				usage;
872 					VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode					sharingMode;
873 					1u,														// uint32_t							queueFamilyIndexCount;
874 					&queueFamilyIndex,										// const uint32_t*					pQueueFamilyIndices;
875 				};
876 
877 #ifndef CTS_USES_VULKANSC
878 				if (m_config.testSizeRequirements)
879 				{
880 					VkPhysicalDeviceMaintenance4PropertiesKHR	maintenance4Properties		=
881 					{
882 						VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR,	// VkStructureType	sType;
883 						DE_NULL,														// void*			pNext;
884 						0u																// VkDeviceSize		maxBufferSize;
885 					};
886 
887 					VkPhysicalDeviceProperties2					physicalDeviceProperties2	=
888 					{
889 						VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,	// VkStructureType				sType;
890 						&maintenance4Properties,						// void*						pNext;
891 						{},												// VkPhysicalDeviceProperties	properties;
892 					};
893 
894 					m_context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &physicalDeviceProperties2);
895 
896 					const VkDeviceSize							maxBufferSize				= maintenance4Properties.maxBufferSize;
897 					DE_ASSERT(maxBufferSize > 0);
898 					VkDeviceSize								N							= 0;
899 
900 					while ((1ull << N) + 1 < maxBufferSize)
901 					{
902 						createInfo.size = (1ull << N) + 1;
903 
904 						try
905 						{
906 							Move<VkBuffer> buffer = createBuffer(vkd, device, &createInfo);
907 
908 							VkMemoryRequirements reqs{};
909 							(this->*method)(reqs, vkd, device, *buffer);
910 
911 							if (reqs.size <= static_cast<VkDeviceSize>(deAlign64(static_cast<deInt64>(createInfo.size), static_cast<deInt64>(reqs.alignment))))
912 							{
913 								++passCount;
914 							} else
915 							{
916 								++failCount;
917 								failCreateBits.emplace_back(m_config.createBits);
918 								failUsageBits.emplace_back(*u);
919 								failExtMemHandleBits.emplace_back(*m);
920 							}
921 
922 							N++;
923 						}
924 						catch (const vk::OutOfMemoryError&)
925 						{
926 							break;
927 						}
928 					}
929 
930 					if (m_context.getTestContext().getWatchDog())
931 						qpWatchDog_reset(m_context.getTestContext().getWatchDog());
932 				}
933 				else
934 #endif // CTS_USES_VULKANSC
935 				{
936 					Move<VkBuffer> buffer = createBuffer(vkd, device, &createInfo);
937 
938 					VkMemoryRequirements reqs{};
939 					(this->*method)(reqs, vkd, device, *buffer);
940 					if (reqs.memoryTypeBits)
941 						++passCount;
942 					else
943 					{
944 						++failCount;
945 						failCreateBits.emplace_back(m_config.createBits);
946 						failUsageBits.emplace_back(*u);
947 						failExtMemHandleBits.emplace_back(*m);
948 					}
949 				}
950 			}
951 		}
952 	}
953 
954 	if (failCount)
955 	{
956 		logFailedSubtests(failCreateBits, failUsageBits, failExtMemHandleBits);
957 		return TestStatus::fail(std::to_string(failCount));
958 	}
959 
960 	return TestStatus::pass(std::to_string(passCount));
961 }
962 
963 } // unnamed namespace
964 
createBufferMemoryRequirementsTests(tcu::TestContext & testCtx)965 tcu::TestCaseGroup* createBufferMemoryRequirementsTests (tcu::TestContext& testCtx)
966 {
967 	struct
968 	{
969 		bool		include;
970 		cstr		name;
971 	} const extMemTypeFlags[] { { false, "ext_mem_flags_excluded" }, { true, "ext_mem_flags_included" } };
972 
973 	struct
974 	{
975 		bool		method;
976 		cstr		name;
977 	} const methods[]
978 	{
979 		{ false, "method1" },
980 		{ true, "method2" }
981 	};
982 
983 	std::vector<SharedPtr<BufferCreateBits>>	createBitPtrs;
984 	{
985 		std::vector<VkBufferCreateFlags>		hints;
986 		std::vector<BufferCreateBits>			createFlags;
987 		u::combine(createFlags,	AvailableBufferCreateBits, hints);
988 		updateBufferCreateFlags(createFlags);
989 		createBitPtrs.resize(createFlags.size());
990 		std::transform(createFlags.begin(), createFlags.end(), createBitPtrs.begin(),
991 					   [](BufferCreateBits& bits) { return BufferCreateBits::makeShared(std::move(bits)); });
992 	}
993 
994 	std::vector<SharedPtr<BufferFateBits>>	fateBitPtrs;
995 	{
996 		// An excerpt above has been disabled consciously for the sake of computational complexity.
997 		// Enabled block does the same things sequentially, it doesn't create cartesian product of combination of bits.
998 #if 0
999 		std::vector<BufferFateFlags>	hints;
1000 		std::vector<BufferFateBits>		bufferFateFlags;
1001 		u::combine(bufferFateFlags, AvailableBufferFateBits, hints);
1002 		fateBitPtrs.resize(bufferFateFlags.size());
1003 		std::transform(bufferFateFlags.begin(), bufferFateFlags.end(), fateBitPtrs.begin(),
1004 					   [](BufferFateBits& bits) { return BufferFateBits::makeShared(std::move(bits)); });
1005 #else
1006 		fateBitPtrs.resize(AvailableBufferFateBits.size());
1007 		std::transform(AvailableBufferFateBits.begin(), AvailableBufferFateBits.end(), fateBitPtrs.begin(),
1008 					   [](const typename BufferFateBits::value_type& bit) { return BufferFateBits::makeShared(bit); });
1009 #endif
1010 	}
1011 
1012 	auto groupRoot = new TestCaseGroup(testCtx, "buffer_memory_requirements");
1013 	for (const auto& createBits : createBitPtrs)
1014 	{
1015 		auto groupCreate = new TestCaseGroup(testCtx, bitsToString(*createBits, "create_").c_str());
1016 		for (const auto& extMemTypeFlag : extMemTypeFlags)
1017 		{
1018 			auto groupExtMemTypeFlags = new TestCaseGroup(testCtx, extMemTypeFlag.name);
1019 			for (const auto& method : methods)
1020 			{
1021 				auto groupMethod = new TestCaseGroup(testCtx, method.name);
1022 				for (const auto& fateBits : fateBitPtrs)
1023 				{
1024 #ifndef CTS_USES_VULKANSC
1025 					for (const auto testSizeReq : {false, true})
1026 #else
1027 					const bool testSizeReq = false;
1028 #endif // CTS_USES_VULKANSC
1029 					{
1030 						TestConfig	config;
1031 						config.fateBits				= fateBits;
1032 						config.incExtMemTypeFlags	= extMemTypeFlag.include;
1033 						config.createBits			= createBits;
1034 						config.useMethod2			= method.method;
1035 						config.testSizeRequirements	= testSizeReq;
1036 						groupMethod->addChild(new MemoryRequirementsTest(testCtx, ((testSizeReq ? "size_req_" : "") + bitsToString(*fateBits)).c_str(), config));
1037 					}
1038 				}
1039 				groupExtMemTypeFlags->addChild(groupMethod);
1040 			}
1041 			groupCreate->addChild(groupExtMemTypeFlags);
1042 		}
1043 		groupRoot->addChild(groupCreate);
1044 	}
1045 
1046 	return groupRoot;
1047 }
1048 } // api
1049 } // vkt
1050