• 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 
28 #include "vkMemUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "deFilePath.hpp"
34 #include "tcuTestLog.hpp"
35 
36 #include <algorithm>
37 #include <array>
38 #include <functional>
39 #include <iostream>
40 #include <set>
41 #include <sstream>
42 #include <tuple>
43 #include <vector>
44 
45 namespace vkt
46 {
47 namespace api
48 {
49 namespace
50 {
51 
52 using namespace de;
53 using namespace vk;
54 using namespace tcu;
55 
56 struct TestConfig;
57 struct InstanceConfig;
58 
59 enum BufferFateFlagBits
60 {
61 	Transfer		= 0x01,
62 	Storage			= 0x02,
63 	Other			= 0x04,
64 	AccStructure	= 0x08,
65 	Video			= 0x10
66 };
67 typedef deUint32	BufferFateFlags;
68 typedef typename std::add_pointer<typename std::add_const<char>::type>::type	cstr;
69 typedef u::BitsSet<BufferFateFlags, BufferFateFlagBits, cstr> BufferFateBits;
70 
71 const BufferFateBits	AvailableBufferFateBits
72 {
73 	std::make_tuple(Transfer,		"transfer_usage_bits"	),
74 	std::make_tuple(Storage,		"storage_usage_bits"	),
75 	std::make_tuple(Other,			"other_usage_bits"		),
76 	std::make_tuple(AccStructure,	"acc_struct_usage_bits"	),
77 	std::make_tuple(Video,			"video_usage_bits"		),
78 };
79 
80 typedef u::BitsSet<VkBufferCreateFlags, VkBufferCreateFlagBits, cstr>				BufferCreateBits;
81 typedef u::BitsSet<VkBufferUsageFlags, VkBufferUsageFlagBits, BufferFateFlagBits>	BufferUsageBits;
82 typedef u::BitsSet<VkExternalMemoryHandleTypeFlags,
83 					VkExternalMemoryHandleTypeFlagBits, cstr, bool>					ExternalMemoryHandleBits;
84 typedef SharedPtr<BufferCreateBits>			BufferCreateBitsPtr;
85 typedef SharedPtr<BufferUsageBits>			BufferUsageBitsPtr;
86 typedef SharedPtr<ExternalMemoryHandleBits>	ExternalMemoryHandleBitsPtr;
87 
88 struct TestConfig
89 {
90 	bool						useMethod2;
91 	SharedPtr<BufferCreateBits>	createBits;
92 	SharedPtr<BufferFateBits>	fateBits;
93 	bool						incExtMemTypeFlags;
94 	// Tests the buffer memory size requirement is less than or equal to the aligned size of the buffer.
95 	// Requires VK_KHR_maintenance4 extension.
96 	bool						testSizeRequirements;
97 };
98 struct InstanceConfig
99 {
100 	bool												useMethod2;
101 	SharedPtr<BufferCreateBits>							createBits;
102 	SharedPtr<BufferFateBits>							fateBits;
103 	SharedPtr<std::vector<BufferUsageBitsPtr>>			usageFlags;
104 	bool												incExtMemTypeFlags;
105 	SharedPtr<std::vector<ExternalMemoryHandleBitsPtr>>	extMemHandleFlags;
106 	bool												testSizeRequirements;
107 
InstanceConfigvkt::api::__anonc21762200111::InstanceConfig108 	InstanceConfig(const TestConfig& conf)
109 		: useMethod2			(conf.useMethod2)
110 		, createBits			(conf.createBits)
111 		, fateBits				(conf.fateBits)
112 		, usageFlags			(new std::vector<SharedPtr<BufferUsageBits>>)
113 		, incExtMemTypeFlags	(conf.incExtMemTypeFlags)
114 		, extMemHandleFlags		(new std::vector<SharedPtr<ExternalMemoryHandleBits>>)
115 		, testSizeRequirements	(conf.testSizeRequirements) {}
116 };
117 
118 const BufferCreateBits	AvailableBufferCreateBits
119 {
120 	std::make_tuple(VkBufferCreateFlagBits(0),				"no_flags"			),
121 	std::make_tuple(VK_BUFFER_CREATE_PROTECTED_BIT,			"protected"			),
122 	std::make_tuple(VK_BUFFER_CREATE_SPARSE_BINDING_BIT,	"sparse_binding"	),
123 	std::make_tuple(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT,	"sparse_residency"	),
124 	std::make_tuple(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT,	"sparse_aliased"	),
125 };
126 
127 const BufferUsageBits	AvailableBufferUsageBits
128 {
129 	std::make_tuple(VK_BUFFER_USAGE_TRANSFER_SRC_BIT										, Transfer		),
130 	std::make_tuple(VK_BUFFER_USAGE_TRANSFER_DST_BIT										, Transfer		),
131 	std::make_tuple(VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT								, Storage		),
132 	std::make_tuple(VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT								, Storage		),
133 	std::make_tuple(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT										, Storage		),
134 	std::make_tuple(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT										, Storage		),
135 	std::make_tuple(VK_BUFFER_USAGE_INDEX_BUFFER_BIT										, Storage		),
136 	std::make_tuple(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT										, Storage		),
137 	std::make_tuple(VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT										, Other			),
138 	std::make_tuple(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT								, Other			),
139 	std::make_tuple(VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR								, Video			),
140 	std::make_tuple(VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR								, Video			),
141 	std::make_tuple(VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT						, Other			),
142 	std::make_tuple(VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT				, Other			),
143 	std::make_tuple(VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT							, Other			),
144 	std::make_tuple(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR	, AccStructure	),
145 	std::make_tuple(VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR					, AccStructure	),
146 	std::make_tuple(VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR							, AccStructure	),
147 	std::make_tuple(VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR								, Video			),
148 	std::make_tuple(VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR								, Video			),
149 };
150 
151 #define INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS VkExternalMemoryHandleTypeFlagBits(0)
152 const ExternalMemoryHandleBits	AvailableExternalMemoryHandleBits
153 {
154 	std::make_tuple(INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS					, "no_flags",			false ),
155 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT						, "opaque_fd",			false ),
156 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT						, "opaque_win32",		false ),
157 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT					, "opaque_win32_kmt",	false ),
158 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT					, "d3d11_tex",			false ),
159 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_KMT_BIT				, "d3d11_tex_kmt",		false ),
160 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP_BIT						, "d3d12_heap",			false ),
161 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE_BIT					, "d3d12_rsrc",			false ),
162 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT						, "dma_buf",			false ),
163 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID	, "android_hw",			false ),
164 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT				, "host_alloc",			true  ),
165 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_MAPPED_FOREIGN_MEMORY_BIT_EXT	, "host_mapped",		true  ),
166 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_ZIRCON_VMO_BIT_FUCHSIA				, "zircon_vmo",			false ),
167 	std::make_tuple(VK_EXTERNAL_MEMORY_HANDLE_TYPE_RDMA_ADDRESS_BIT_NV					, "roma_addr",			false ),
168 };
169 
170 template<class Flag, class Bit, class Str, class... Ignored>
bitsToString(const u::BitsSet<Flag,Bit,Str,Ignored...> & bits,const std::string & prefix=std::string ())171 std::string bitsToString (const u::BitsSet<Flag, Bit, Str, Ignored...>& bits,
172 						  const std::string& prefix = std::string())
173 {
174 	DE_ASSERT(!bits.empty());
175 	std::stringstream s;
176 	s << prefix;
177 	bool atLeastOne = false;
178 	for (const auto& bit : bits) {
179 		if (atLeastOne) s << '_';
180 		s << std::get<1>(bit);
181 		atLeastOne = true;
182 	}
183 	return s.str();
184 }
185 
updateBufferCreateFlags(std::vector<BufferCreateBits> & flags)186 void updateBufferCreateFlags(std::vector<BufferCreateBits>& flags)
187 {
188 	const auto&	residencyBit	= AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT);
189 	const auto&	aliasedBit		= AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT);
190 	const auto&	bindingBit		= AvailableBufferCreateBits.get(VK_BUFFER_CREATE_SPARSE_BINDING_BIT);
191 	const auto&	protectedBit	= AvailableBufferCreateBits.get(VK_BUFFER_CREATE_PROTECTED_BIT);
192 	const auto&	noneBit			= AvailableBufferCreateBits.get(VkBufferCreateFlagBits(0));
193 
194 	// VUID-VkBufferCreateInfo-flags-00918 { if sparse residency or sparse aliased include sparse binding }
195 	for (auto& bits : flags)
196 	{
197 		if (bits.contains(residencyBit) || bits.contains(aliasedBit))
198 			bits.insert(bindingBit);
199 	}
200 
201 	// VUID-VkBufferCreateInfo-None-01888 { if sparse residency, sparse aliased or sparse binding then flags must not include protected }
202 	const typename BufferCreateBits::key_type disallowdBits[] { residencyBit, aliasedBit, bindingBit };
203 	for (auto i = flags.begin(); i != flags.end();)
204 	{
205 		auto& bits = *i;
206 		if (bits.contains(protectedBit))
207 		{
208 			for (const auto& disallowdBit : disallowdBits)
209 			{
210 				auto find = bits.find(disallowdBit);
211 				if (find != bits.end())
212 					bits.erase(find);
213 			}
214 		}
215 		i = bits.empty() ? flags.erase(i) : std::next(i);
216 	}
217 
218 	// since 0 is a valid VkBufferCreateFlagBits flag then remove it flags where it exists along with other non-zero flags
219 	for (auto i = flags.begin(); i != flags.end(); ++i)
220 	{
221 		auto& bits = *i;
222 		auto find = bits.find(noneBit);
223 		if (find != bits.end() && bits.size() > 1)
224 		{
225 			bits.erase(find);
226 		}
227 	}
228 
229 	// remove duplicates
230 	for (auto i = flags.begin(); i != flags.end(); ++i)
231 	{
232 		for (auto j = std::next(i); j != flags.end();)
233 			j = (*i == *j) ? flags.erase(j) : std::next(j);
234 	}
235 }
236 
237 class BufferMemoryRequirementsInstance : public TestInstance
238 {
239 public:
BufferMemoryRequirementsInstance(Context & context,const InstanceConfig config)240 							BufferMemoryRequirementsInstance	(Context&				context,
241 																 const InstanceConfig	config)
242 								: TestInstance	(context)
243 								, m_config		(config) {}
244 
245 	virtual					~BufferMemoryRequirementsInstance	(void) override = default;
246 	virtual tcu::TestStatus	iterate								(void) override;
247 
248 	void						getBufferMemoryRequirements		(VkMemoryRequirements&	result,
249 																 const DeviceInterface&	vkd,
250 																 VkDevice				device,
251 																 VkBuffer				buffer) const;
252 	void						getBufferMemoryRequirements2	(VkMemoryRequirements&	result,
253 																 const DeviceInterface&	vkd,
254 																 VkDevice				device,
255 																 VkBuffer				buffer) const;
256 	typedef void (BufferMemoryRequirementsInstance::* Method)	(VkMemoryRequirements&	result,
257 																 const DeviceInterface&	intf,
258 																 VkDevice				device,
259 																 VkBuffer				buffer) const;
260 	template<class T, class... AddArgs>
261 						void*	chainVkStructure				(void*					pNext,
262 																 const AddArgs&...		addArgs) const;
263 private:
264 	void						logFailedSubtests				(const std::vector<BufferCreateBitsPtr>&			failCreateBits,
265 																 const std::vector<BufferUsageBitsPtr>&				failUsageBits,
266 																 const std::vector<ExternalMemoryHandleBitsPtr>&	failExtMemHandleBits) const;
267 	const InstanceConfig	m_config;
268 };
269 
270 class MemoryRequirementsTest : public TestCase
271 {
272 public:
MemoryRequirementsTest(TestContext & testCtx,const std::string & name,const TestConfig testConfig)273 							MemoryRequirementsTest	(TestContext&			testCtx,
274 													 const std::string&		name,
275 													 const TestConfig		testConfig)
276 								: TestCase		(testCtx, name, std::string())
277 								, m_testConfig	(testConfig)
278 								, m_instConfig	(testConfig) {}
279 
280 	virtual					~MemoryRequirementsTest	(void) override = default;
281 	virtual void			checkSupport			(Context&				context) const override;
createInstance(Context & context) const282 	virtual TestInstance*	createInstance			(Context&				context) const override
283 	{
284 		return new BufferMemoryRequirementsInstance(context, m_instConfig);
285 	}
286 
287 private:
288 	const TestConfig	m_testConfig;
289 	InstanceConfig		m_instConfig;
290 };
291 
292 struct Info
293 {
294 	enum Type {
295 		Create,
296 		Usage
297 	}					m_type;
298 	std::ostringstream	m_str;
299 	cstr				m_file;
300 	int					m_line;
Infovkt::api::__anonc21762200111::Info301 	template<class Msg>	Info(Type type, const Msg& msg, cstr file, int line)
302 		: m_type(type), m_str(), m_file(file), m_line(line) { m_str << msg; }
operator <<(std::ostringstream & str,const Info & info)303 	friend std::ostringstream& operator<<(std::ostringstream& str, const Info& info) {
304 		switch (info.m_type) {
305 		case Create:
306 			str << "  Info (Create buffer with " << info.m_str.str() << " not supported by device at "
307 				<< de::FilePath(info.m_file).getBaseName() << ":" << info.m_line << ")";
308 			break;
309 		case Usage:
310 			str << "  Info (Create buffer with " << info.m_str.str() << " not supported by device at "
311 				<< de::FilePath(info.m_file).getBaseName() << ":" << info.m_line << ")";
312 			break;
313 		}
314 		return str;
315 	}
316 };
317 #define INFOCREATE(msg_) Info(Info::Create, (msg_), __FILE__, __LINE__)
318 #define INFOUSAGE(msg_) Info(Info::Usage, (msg_), __FILE__, __LINE__)
319 
checkSupport(Context & context) const320 void MemoryRequirementsTest::checkSupport (Context& context) const
321 {
322 	const InstanceInterface&						intf				= context.getInstanceInterface();
323 	const VkPhysicalDevice							physDevice			= context.getPhysicalDevice();
324 	const std::vector<VkExtensionProperties>		supportedExtensions = enumerateDeviceExtensionProperties(intf, physDevice, nullptr);
325 
326 	VkPhysicalDeviceProtectedMemoryFeatures			protectedMemFeatures
327 	{
328 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,	// VkStructureType	sType;
329 		nullptr,															// void*			pNext;
330 		VK_FALSE															// VkBool32			protectedMemory;
331 	};
332 	VkPhysicalDeviceFeatures2						extFeatures
333 	{
334 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,					// VkStructureType			sType;
335 		&protectedMemFeatures,												// void*					pNext;
336 		{}																	// VkPhysicalDeviceFeatures	features;
337 	};
338 	intf.getPhysicalDeviceFeatures2(physDevice, &extFeatures);
339 
340 	const VkPhysicalDeviceFeatures&	features					= extFeatures.features;
341 	const VkBool32&					protectedMemFeatureEnabled	= protectedMemFeatures.protectedMemory;
342 
343 
344 	// check the creating bits
345 	{
346 		std::ostringstream			str;
347 		bool		notSupported	= false;
348 		const auto& createBits		= *m_testConfig.createBits;
349 
350 		if (createBits.contains(VK_BUFFER_CREATE_SPARSE_BINDING_BIT) && (VK_FALSE == features.sparseBinding))
351 		{
352 			if (notSupported) str << std::endl;
353 			str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_BINDING_BIT));
354 			notSupported = true;
355 		}
356 		if (createBits.contains(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) && (VK_FALSE == features.sparseResidencyBuffer))
357 		{
358 			if (notSupported) str << std::endl;
359 			str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT));
360 			notSupported = true;
361 		}
362 		if (createBits.contains(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) && (VK_FALSE == features.sparseResidencyAliased))
363 		{
364 			if (notSupported) str << std::endl;
365 			str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_SPARSE_ALIASED_BIT));
366 			notSupported = true;
367 		}
368 		if (createBits.contains(VK_BUFFER_CREATE_PROTECTED_BIT) && (VK_FALSE == protectedMemFeatureEnabled))
369 		{
370 			if (notSupported) str << std::endl;
371 			str << INFOCREATE(getBufferCreateFlagsStr(VK_BUFFER_CREATE_PROTECTED_BIT));
372 			notSupported = true;
373 		}
374 		if (notSupported)
375 		{
376 			std::cout << str.str() << std::endl;
377 			TCU_THROW(NotSupportedError, "One or more create buffer flags not supported by device");
378 		}
379 	}
380 
381 	// check the usage bits and build instance input
382 	{
383 		std::vector<BufferUsageBits>	usageFlags;
384 		for (const auto& bit : *m_testConfig.fateBits)
385 		{
386 			auto fate = m_testConfig.fateBits->extract(bit);
387 			std::vector<VkBufferUsageFlags>		usageHints;
388 			std::vector<BufferUsageBits>		usageFlagsTmp;
389 			u::combine(usageFlagsTmp, AvailableBufferUsageBits.select<1>(fate), usageHints);
390 			u::mergeFlags(usageFlags, usageFlagsTmp);
391 		}
392 
393 		std::ostringstream str;
394 		std::array<bool, 5> msgs;
395 		bool notSupported	= false;
396 		int  entryCount		= 0;
397 		msgs.fill(false);
398 
399 		for (auto i = usageFlags.begin(); i != usageFlags.end();)
400 		{
401 			notSupported = false;
402 
403 			if (i->any({VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR,
404 					   VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR, VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR})
405 					&& !isExtensionSupported(supportedExtensions, RequiredExtension("VK_KHR_acceleration_structure")))
406 			{
407 				if (!msgs[0])
408 				{
409 					if (entryCount++) str << std::endl;
410 					str << INFOUSAGE("VK_KHR_acceleration_structure not supported by device");
411 					msgs[0] = true;
412 				}
413 				notSupported = true;
414 			}
415 
416 			if (i->contains(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
417 					&& !isExtensionSupported(supportedExtensions, RequiredExtension("VK_EXT_buffer_device_address")))
418 			{
419 				if (!msgs[1])
420 				{
421 					if (entryCount++) str << std::endl;
422 					str << INFOUSAGE("VK_EXT_buffer_device_address not supported by device");
423 					msgs[1] = true;
424 				}
425 				notSupported = true;
426 			}
427 
428 			if (i->any({VK_BUFFER_USAGE_VIDEO_DECODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_DECODE_DST_BIT_KHR,
429 					   VK_BUFFER_USAGE_VIDEO_ENCODE_SRC_BIT_KHR, VK_BUFFER_USAGE_VIDEO_ENCODE_DST_BIT_KHR}))
430 			{
431 
432 			}
433 
434 			i = notSupported ? usageFlags.erase(i) : std::next(i);
435 		}
436 
437 		// remove duplicates
438 		for (auto i = usageFlags.begin(); i != usageFlags.end(); ++i)
439 		{
440 			for (auto j = std::next(i); j != usageFlags.end();)
441 				j = (*i == *j) ? usageFlags.erase(j) : std::next(j);
442 		}
443 
444 		if (usageFlags.empty())
445 		{
446 			std::cout << str.str() << std::endl;
447 			TCU_THROW(NotSupportedError, "One or more buffer usage flags not supported by device");
448 		}
449 		else
450 		{
451 			if (entryCount > 0)
452 			{
453 				std::cout << str.str() << std::endl;
454 			}
455 			DE_ASSERT(m_instConfig.usageFlags.get());
456 			m_instConfig.usageFlags->resize(usageFlags.size());
457 			std::transform(usageFlags.begin(), usageFlags.end(), m_instConfig.usageFlags->begin(),
458 						   [](BufferUsageBits& bits){ return BufferUsageBits::makeShared(std::move(bits)); });
459 		}
460 	}
461 
462 	// check the external memory handle type bits and build instance input
463 	{
464 		std::vector<ExternalMemoryHandleBits>	extMemHandleFlags;
465 		if (m_testConfig.incExtMemTypeFlags)
466 			extMemHandleFlags.push_back({AvailableExternalMemoryHandleBits.get(INTERNALTEST_EXTERNAL_MEMORY_HANDLE_TYPE_NO_BITS)});
467 		else
468 		{
469 			std::vector<VkExternalMemoryHandleTypeFlags>	handleHints;
470 			std::vector<ExternalMemoryHandleBits>			handleFlagsTmp;
471 			u::combine(handleFlagsTmp, AvailableExternalMemoryHandleBits.select<2>(true), handleHints);
472 			u::mergeFlags(extMemHandleFlags, handleFlagsTmp);
473 		}
474 
475 		DE_ASSERT(m_instConfig.extMemHandleFlags.get());
476 		m_instConfig.extMemHandleFlags->resize(extMemHandleFlags.size());
477 		std::transform(extMemHandleFlags.begin(), extMemHandleFlags.end(), m_instConfig.extMemHandleFlags->begin(),
478 					   [](ExternalMemoryHandleBits& bits){ return ExternalMemoryHandleBits::makeShared(std::move(bits)); });
479 	}
480 
481 	if (m_testConfig.testSizeRequirements)
482 	{
483 		if (!context.isDeviceFunctionalitySupported("VK_KHR_maintenance4"))
484 			TCU_THROW(NotSupportedError, "VK_KHR_maintenance4 not supported");
485 	}
486 }
487 
logFailedSubtests(const std::vector<BufferCreateBitsPtr> & failCreateBits,const std::vector<BufferUsageBitsPtr> & failUsageBits,const std::vector<ExternalMemoryHandleBitsPtr> & failExtMemHandleBits) const488 void BufferMemoryRequirementsInstance::logFailedSubtests (const std::vector<BufferCreateBitsPtr>&			failCreateBits,
489 														  const std::vector<BufferUsageBitsPtr>&			failUsageBits,
490 														  const std::vector<ExternalMemoryHandleBitsPtr>&	failExtMemHandleBits) const
491 {
492 	const deUint32	flagCount	= deUint32(failCreateBits.size());
493 	TestLog&		log			= m_context.getTestContext().getLog();
494 	deUint32		entries		= 0;
495 
496 	DE_ASSERT(flagCount && flagCount == failUsageBits.size() && flagCount == failExtMemHandleBits.size());
497 
498 	log << TestLog::Section("Failed", "Failed subtests");
499 
500 	for (deUint32 i = 0; i < flagCount; ++i)
501 	{
502 		{
503 			log << TestLog::Section("VkBufferCreateFlags", "Buffer create flags");
504 			auto msg = log << TestLog::Message;
505 			entries = 0;
506 			for (const auto& createBit : *failCreateBits[i])
507 			{
508 				if (entries++) msg << " ";
509 				const VkBufferCreateFlags flags = BufferCreateBits::extract(createBit);
510 				if (flags == 0)
511 					msg << "0";
512 				else msg << getBufferCreateFlagsStr(flags);
513 			}
514 			msg << TestLog::EndMessage << TestLog::EndSection;
515 		}
516 
517 		{
518 			log << TestLog::Section("VkBufferUsageFlags", "Buffer usage flags");
519 			auto msg = log << TestLog::Message;
520 			entries = 0;
521 			for (const auto& usageBit : *failUsageBits[i])
522 			{
523 				if (entries++) msg << " ";
524 				msg << getBufferUsageFlagsStr(BufferUsageBits::extract(usageBit));
525 			}
526 			msg << TestLog::EndMessage << TestLog::EndSection;
527 		}
528 
529 		{
530 			log << TestLog::Section("VkExternalMemoryHandleTypeFlags", "External memory handle type flags");
531 			auto msg = log << TestLog::Message;
532 			entries = 0;
533 			for (const auto& extMemHandleTypeBit : *failExtMemHandleBits[i])
534 			{
535 				if (entries++) msg << " ";
536 				msg << getExternalMemoryHandleTypeFlagsStr(ExternalMemoryHandleBits::extract(extMemHandleTypeBit));
537 			}
538 			msg << TestLog::EndMessage << TestLog::EndSection;
539 		}
540 	}
541 
542 	log << TestLog::EndSection;
543 }
544 
getBufferMemoryRequirements2(VkMemoryRequirements & result,const DeviceInterface & vkd,VkDevice device,VkBuffer buffer) const545 void BufferMemoryRequirementsInstance::getBufferMemoryRequirements2	(VkMemoryRequirements&	result,
546 																	 const DeviceInterface&	vkd,
547 																	 VkDevice				device,
548 																	 VkBuffer				buffer) const
549 {
550 	VkMemoryDedicatedRequirements	dedicatedRequirements	=
551 	{
552 		VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,		// VkStructureType			sType;
553 		nullptr,												// const void*				pNext;
554 		VK_FALSE,												// VkBool32					prefersDedicatedAllocation
555 		VK_FALSE												// VkBool32					requiresDedicatedAllocation
556 	};
557 
558 	VkMemoryRequirements2			desiredRequirements		=
559 	{
560 		VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,				// VkStructureType			sType
561 		&dedicatedRequirements,									// void*					pNext
562 		result													// VkMemoryRequirements		memoryRequirements
563 	};
564 
565 	VkBufferMemoryRequirementsInfo2	requirementsInfo		=
566 	{
567 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2,	// VkStructureType			sType
568 		nullptr,												// const void*				pNext
569 		buffer													// VkBuffer					buffer
570 	};
571 
572 	vkd.getBufferMemoryRequirements2(device, &requirementsInfo, &desiredRequirements);
573 
574 	result = desiredRequirements.memoryRequirements;
575 }
576 
getBufferMemoryRequirements(VkMemoryRequirements & result,const DeviceInterface & vkd,VkDevice device,VkBuffer buffer) const577 void BufferMemoryRequirementsInstance::getBufferMemoryRequirements	(VkMemoryRequirements&	result,
578 																	 const DeviceInterface&	vkd,
579 																	 VkDevice				device,
580 																	 VkBuffer				buffer) const
581 {
582 	vkd.getBufferMemoryRequirements(device, buffer, &result);
583 }
584 
585 template<> void*
chainVkStructure(void * pNext,const VkExternalMemoryHandleTypeFlags & handleTypes) const586 BufferMemoryRequirementsInstance::chainVkStructure<VkExternalMemoryBufferCreateInfo> (void* pNext, const VkExternalMemoryHandleTypeFlags& handleTypes) const
587 {
588 	static VkExternalMemoryBufferCreateInfo	memInfo{};
589 	memInfo.sType		= VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO;
590 	memInfo.pNext		= pNext;
591 	memInfo.handleTypes	= handleTypes;
592 
593 	return &memInfo;
594 }
595 
chainVkStructure(void * pNext) const596 template<> void* BufferMemoryRequirementsInstance::chainVkStructure<VkVideoProfilesKHR> (void* pNext) const
597 {
598 	static const VkVideoProfileKHR		videoProfile
599 	{
600 		VK_STRUCTURE_TYPE_VIDEO_PROFILE_KHR,					// VkStructureType					sType;
601 		nullptr,												// void*							pNext;
602 		VK_VIDEO_CODEC_OPERATION_INVALID_BIT_KHR,				// VkVideoCodecOperationFlagBitsKHR	videoCodecOperation;
603 		VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR,			// VkVideoChromaSubsamplingFlagsKHR	chromaSubsampling;
604 		VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR,					// VkVideoComponentBitDepthFlagsKHR	lumaBitDepth;
605 		VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR					// VkVideoComponentBitDepthFlagsKHR	chromaBitDepth;
606 	};
607 
608 	 static VkVideoProfilesKHR	profiles;
609 	 profiles.sType			= VK_STRUCTURE_TYPE_VIDEO_PROFILES_KHR;
610 	 profiles.pNext			= pNext;
611 	 profiles.profileCount	= 1u;
612 	 profiles.pProfiles		= &videoProfile;
613 
614 	 return &profiles;
615 }
616 
iterate(void)617 TestStatus	BufferMemoryRequirementsInstance::iterate (void)
618 {
619 	const DeviceInterface&							vkd					= m_context.getDeviceInterface();
620 	const VkDevice									device				= m_context.getDevice();
621 	const deUint32									queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
622 	const Method									method				= m_config.useMethod2
623 																			? &BufferMemoryRequirementsInstance::getBufferMemoryRequirements2
624 																			: &BufferMemoryRequirementsInstance::getBufferMemoryRequirements;
625 
626 	deUint32										passCount			= 0;
627 	deUint32										failCount			= 0;
628 	std::vector<BufferCreateBitsPtr>				failCreateBits;
629 	std::vector<BufferUsageBitsPtr>					failUsageBits;
630 	std::vector<ExternalMemoryHandleBitsPtr>		failExtMemHandleBits;
631 
632 	DE_ASSERT(!m_config.createBits->empty());
633 	const VkBufferCreateFlags infoCreateFlags = *m_config.createBits;
634 	{
635 		DE_ASSERT(!m_config.usageFlags->empty());
636 		for (auto u = m_config.usageFlags->cbegin(); u != m_config.usageFlags->cend(); ++u)
637 		{
638 			const VkBufferUsageFlags infoUsageFlags = *(u->get());
639 
640 			DE_ASSERT(!m_config.extMemHandleFlags->empty());
641 			for (auto m = m_config.extMemHandleFlags->cbegin(); m != m_config.extMemHandleFlags->cend(); ++m)
642 			{
643 				const VkExternalMemoryHandleTypeFlags handleFlags = *(m->get());
644 
645 				void* pNext = nullptr;
646 
647 				if (m_config.fateBits->contains(BufferFateFlagBits::Video))
648 				{
649 					pNext = chainVkStructure<VkVideoProfilesKHR>(pNext);
650 				}
651 				if (m_config.incExtMemTypeFlags)
652 				{
653 					pNext = chainVkStructure<VkExternalMemoryBufferCreateInfo>(pNext, handleFlags);
654 				}
655 				VkBufferCreateInfo	createInfo
656 				{
657 					VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,					// VkStructureType					sType;
658 					pNext,													// const void*						pNext;
659 					infoCreateFlags,										// VkBufferCreateFlags				flags;
660 					4096u,													// VkDeviceSize						size;
661 					infoUsageFlags,											// VkBufferUsageFlags				usage;
662 					VK_SHARING_MODE_EXCLUSIVE,								// VkSharingMode					sharingMode;
663 					1u,														// uint32_t							queueFamilyIndexCount;
664 					&queueFamilyIndex,										// const uint32_t*					pQueueFamilyIndices;
665 				};
666 
667 				if (m_config.testSizeRequirements)
668 				{
669 					VkPhysicalDeviceMaintenance4PropertiesKHR	maintenance4Properties		=
670 					{
671 						VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES_KHR,	// VkStructureType	sType;
672 						DE_NULL,														// void*			pNext;
673 						0u																// VkDeviceSize		maxBufferSize;
674 					};
675 
676 					VkPhysicalDeviceProperties2					physicalDeviceProperties2	=
677 					{
678 						VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,	// VkStructureType				sType;
679 						&maintenance4Properties,						// void*						pNext;
680 						{},												// VkPhysicalDeviceProperties	properties;
681 					};
682 
683 					m_context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &physicalDeviceProperties2);
684 
685 					const VkDeviceSize							maxBufferSize				= maintenance4Properties.maxBufferSize;
686 					DE_ASSERT(maxBufferSize > 0);
687 					VkDeviceSize								N							= 0;
688 
689 					while ((1ull << N) + 1 < maxBufferSize)
690 					{
691 						createInfo.size = (1ull << N) + 1;
692 
693 						try
694 						{
695 							Move<VkBuffer> buffer = createBuffer(vkd, device, &createInfo);
696 
697 							VkMemoryRequirements reqs{};
698 							(this->*method)(reqs, vkd, device, *buffer);
699 
700 							if (reqs.size <= static_cast<VkDeviceSize>(deAlign64(static_cast<deInt64>(createInfo.size), static_cast<deInt64>(reqs.alignment))))
701 							{
702 								++passCount;
703 							} else
704 							{
705 								++failCount;
706 								failCreateBits.emplace_back(m_config.createBits);
707 								failUsageBits.emplace_back(*u);
708 								failExtMemHandleBits.emplace_back(*m);
709 							}
710 
711 							N++;
712 						}
713 						catch (const vk::OutOfMemoryError&)
714 						{
715 							break;
716 						}
717 					}
718 				}
719 				else
720 				{
721 					Move<VkBuffer> buffer = createBuffer(vkd, device, &createInfo);
722 
723 					VkMemoryRequirements reqs{};
724 					(this->*method)(reqs, vkd, device, *buffer);
725 					if (reqs.memoryTypeBits)
726 						++passCount;
727 					else
728 					{
729 						++failCount;
730 						failCreateBits.emplace_back(m_config.createBits);
731 						failUsageBits.emplace_back(*u);
732 						failExtMemHandleBits.emplace_back(*m);
733 					}
734 				}
735 			}
736 		}
737 	}
738 
739 	if (failCount)
740 	{
741 		logFailedSubtests(failCreateBits, failUsageBits, failExtMemHandleBits);
742 		return TestStatus::fail(std::to_string(failCount));
743 	}
744 
745 	return TestStatus::pass(std::to_string(passCount));
746 }
747 
748 } // unnamed namespace
749 
createBufferMemoryRequirementsTests(tcu::TestContext & testCtx)750 tcu::TestCaseGroup* createBufferMemoryRequirementsTests (tcu::TestContext& testCtx)
751 {
752 	cstr nilstr = "";
753 
754 	struct
755 	{
756 		bool		include;
757 		cstr		name;
758 	} const extMemTypeFlags[] { { false, "ext_mem_flags_excluded" }, { true, "ext_mem_flags_included" } };
759 
760 	struct
761 	{
762 		bool		method;
763 		cstr		name;
764 	} const methods[] { { false, "method1" }, { true, "method2" } };
765 
766 	std::vector<SharedPtr<BufferCreateBits>>	createBitPtrs;
767 	{
768 		std::vector<VkBufferCreateFlags>		hints;
769 		std::vector<BufferCreateBits>			createFlags;
770 		u::combine(createFlags,	AvailableBufferCreateBits, hints);
771 		updateBufferCreateFlags(createFlags);
772 		createBitPtrs.resize(createFlags.size());
773 		std::transform(createFlags.begin(), createFlags.end(), createBitPtrs.begin(),
774 					   [](BufferCreateBits& bits) { return BufferCreateBits::makeShared(std::move(bits)); });
775 	}
776 
777 	std::vector<SharedPtr<BufferFateBits>>	fateBitPtrs;
778 	{
779 		// An excerpt above has been disabled consciously for the sake of computational complexity.
780 		// Enabled block does the same things sequentially, it doesn't create cartesian product of combination of bits.
781 #if 0
782 		std::vector<BufferFateFlags>	hints;
783 		std::vector<BufferFateBits>		bufferFateFlags;
784 		u::combine(bufferFateFlags, AvailableBufferFateBits, hints);
785 		fateBitPtrs.resize(bufferFateFlags.size());
786 		std::transform(bufferFateFlags.begin(), bufferFateFlags.end(), fateBitPtrs.begin(),
787 					   [](BufferFateBits& bits) { return BufferFateBits::makeShared(std::move(bits)); });
788 #else
789 		fateBitPtrs.resize(AvailableBufferFateBits.size());
790 		std::transform(AvailableBufferFateBits.begin(), AvailableBufferFateBits.end(), fateBitPtrs.begin(),
791 					   [](const typename BufferFateBits::value_type& bit) { return BufferFateBits::makeShared(bit); });
792 #endif
793 	}
794 
795 	auto groupRoot = new TestCaseGroup(testCtx, "buffer_memory_requirements", "vkGetBufferMemoryRequirements*(...) routines tests.");
796 	for (const auto& createBits : createBitPtrs)
797 	{
798 		auto groupCreate = new TestCaseGroup(testCtx, bitsToString(*createBits, "create_").c_str(), nilstr);
799 		for (const auto& extMemTypeFlag : extMemTypeFlags)
800 		{
801 			auto groupExtMemTypeFlags = new TestCaseGroup(testCtx, extMemTypeFlag.name, nilstr);
802 			for (const auto& method : methods)
803 			{
804 				auto groupMethod = new TestCaseGroup(testCtx, method.name, nilstr);
805 				for (const auto& fateBits : fateBitPtrs)
806 				{
807 					for (const auto testSizeReq : {false, true})
808 					{
809 						TestConfig	config;
810 						config.fateBits				= fateBits;
811 						config.incExtMemTypeFlags	= extMemTypeFlag.include;
812 						config.createBits			= createBits;
813 						config.useMethod2			= method.method;
814 						config.testSizeRequirements	= testSizeReq;
815 						groupMethod->addChild(new MemoryRequirementsTest(testCtx, ((testSizeReq ? "size_req_" : "") + bitsToString(*fateBits)).c_str(), config));
816 					}
817 				}
818 				groupExtMemTypeFlags->addChild(groupMethod);
819 			}
820 			groupCreate->addChild(groupExtMemTypeFlags);
821 		}
822 		groupRoot->addChild(groupCreate);
823 	}
824 
825 	return groupRoot;
826 }
827 } // api
828 } // vkt
829