• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  * Copyright (c) 2019 Valve Corporation.
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 Auxiliar functions to help create custom devices and instances.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vkRefUtil.hpp"
26 #include "vkQueryUtil.hpp"
27 #include "vkDeviceUtil.hpp"
28 #include "vkDebugReportUtil.hpp"
29 #include "vkMemUtil.hpp"
30 #include "tcuCommandLine.hpp"
31 #include "vktCustomInstancesDevices.hpp"
32 
33 #include <algorithm>
34 #include <memory>
35 #include <set>
36 
37 using std::vector;
38 using std::string;
39 using vk::Move;
40 using vk::VkInstance;
41 #ifndef CTS_USES_VULKANSC
42 using vk::InstanceDriver;
43 using vk::DebugReportRecorder;
44 using vk::VkDebugReportCallbackCreateInfoEXT;
45 using vk::VkDebugReportCallbackEXT;
46 #else
47 using vk::InstanceDriverSC;
48 #endif // CTS_USES_VULKANSC
49 
50 namespace vkt
51 {
52 
53 namespace
54 {
55 
getValidationLayers(const vector<vk::VkLayerProperties> & supportedLayers)56 vector<const char*> getValidationLayers (const vector<vk::VkLayerProperties>& supportedLayers)
57 {
58 	static const char*	s_magicLayer		= "VK_LAYER_KHRONOS_validation";
59 	static const char*	s_defaultLayers[]	=
60 	{
61 		"VK_LAYER_LUNARG_standard_validation",		// Deprecated by at least Vulkan SDK 1.1.121.
62 		"VK_LAYER_GOOGLE_threading",				// Deprecated by at least Vulkan SDK 1.1.121.
63 		"VK_LAYER_LUNARG_parameter_validation",		// Deprecated by at least Vulkan SDK 1.1.121.
64 		"VK_LAYER_LUNARG_device_limits",
65 		"VK_LAYER_LUNARG_object_tracker",			// Deprecated by at least Vulkan SDK 1.1.121.
66 		"VK_LAYER_LUNARG_image",
67 		"VK_LAYER_LUNARG_core_validation",			// Deprecated by at least Vulkan SDK 1.1.121.
68 		"VK_LAYER_LUNARG_swapchain",
69 		"VK_LAYER_GOOGLE_unique_objects"			// Deprecated by at least Vulkan SDK 1.1.121.
70 	};
71 
72 	vector<const char*>	enabledLayers;
73 
74 	if (vk::isLayerSupported(supportedLayers, vk::RequiredLayer(s_magicLayer)))
75 		enabledLayers.push_back(s_magicLayer);
76 	else
77 	{
78 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_defaultLayers); ++ndx)
79 		{
80 			if (isLayerSupported(supportedLayers, vk::RequiredLayer(s_defaultLayers[ndx])))
81 				enabledLayers.push_back(s_defaultLayers[ndx]);
82 		}
83 	}
84 
85 	return enabledLayers;
86 }
87 
88 } // anonymous
89 
90 
getValidationLayers(const vk::PlatformInterface & vkp)91 vector<const char*> getValidationLayers (const vk::PlatformInterface& vkp)
92 {
93 	return getValidationLayers(enumerateInstanceLayerProperties(vkp));
94 }
95 
getValidationLayers(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice)96 vector<const char*> getValidationLayers (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice)
97 {
98 	return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice));
99 }
100 
101 #ifndef CTS_USES_VULKANSC
CustomInstance(Context & context,Move<VkInstance> instance,std::unique_ptr<vk::DebugReportRecorder> & recorder)102 CustomInstance::CustomInstance(Context& context, Move<VkInstance> instance, std::unique_ptr<vk::DebugReportRecorder>& recorder)
103 #else
104 CustomInstance::CustomInstance(Context& context, Move<VkInstance> instance)
105 #endif // CTS_USES_VULKANSC
106 	: m_context		(&context)
107 #ifndef CTS_USES_VULKANSC
108 	, m_recorder	(recorder.release())
109 #endif // CTS_USES_VULKANSC
110 	, m_instance	(instance)
111 #ifndef CTS_USES_VULKANSC
112 	, m_driver		(new InstanceDriver(context.getPlatformInterface(), *m_instance))
113 	, m_callback	(m_recorder ? m_recorder->createCallback(*m_driver, *m_instance) : Move<VkDebugReportCallbackEXT>())
114 #else
115 	, m_driver		(new InstanceDriverSC(context.getPlatformInterface(), *m_instance, context.getTestContext().getCommandLine(), context.getResourceInterface()))
116 #endif // CTS_USES_VULKANSC
117 {
118 }
119 
CustomInstance()120 CustomInstance::CustomInstance ()
121 	: m_context		(nullptr)
122 #ifndef CTS_USES_VULKANSC
123 	, m_recorder	(nullptr)
124 #endif // CTS_USES_VULKANSC
125 	, m_instance	()
126 	, m_driver		(nullptr)
127 #ifndef CTS_USES_VULKANSC
128 	, m_callback	()
129 #endif // CTS_USES_VULKANSC
130 {
131 }
132 
CustomInstance(CustomInstance && other)133 CustomInstance::CustomInstance (CustomInstance&& other)
134 	: CustomInstance()
135 {
136 	this->swap(other);
137 }
138 
~CustomInstance()139 CustomInstance::~CustomInstance ()
140 {
141 	collectMessages();
142 }
143 
operator =(CustomInstance && other)144 CustomInstance&	CustomInstance::operator= (CustomInstance&& other)
145 {
146 	CustomInstance destroyer;
147 	destroyer.swap(other);
148 	this->swap(destroyer);
149 	return *this;
150 }
151 
swap(CustomInstance & other)152 void CustomInstance::swap (CustomInstance& other)
153 {
154 	std::swap(m_context, other.m_context);
155 #ifndef CTS_USES_VULKANSC
156 	m_recorder.swap(other.m_recorder);
157 #endif // CTS_USES_VULKANSC
158 	Move<VkInstance> aux = m_instance; m_instance = other.m_instance; other.m_instance = aux;
159 	m_driver.swap(other.m_driver);
160 #ifndef CTS_USES_VULKANSC
161 	Move<VkDebugReportCallbackEXT> aux2 = m_callback; m_callback = other.m_callback; other.m_callback = aux2;
162 #endif // CTS_USES_VULKANSC
163 }
164 
operator VkInstance() const165 CustomInstance::operator VkInstance () const
166 {
167 	return *m_instance;
168 }
169 
getDriver() const170 const vk::InstanceDriver& CustomInstance::getDriver() const
171 {
172 	return *m_driver;
173 }
174 
collectMessages()175 void CustomInstance::collectMessages ()
176 {
177 #ifndef CTS_USES_VULKANSC
178 	if (m_recorder)
179 		collectAndReportDebugMessages(*m_recorder, *m_context);
180 #endif // CTS_USES_VULKANSC
181 }
182 
UncheckedInstance()183 UncheckedInstance::UncheckedInstance ()
184 	: m_context		(nullptr)
185 #ifndef CTS_USES_VULKANSC
186 	, m_recorder	(nullptr)
187 #endif // CTS_USES_VULKANSC
188 	, m_allocator	(nullptr)
189 	, m_instance	(DE_NULL)
190 	, m_driver		(nullptr)
191 #ifndef CTS_USES_VULKANSC
192 	, m_callback	()
193 #endif // CTS_USES_VULKANSC
194 {
195 }
196 
197 #ifndef CTS_USES_VULKANSC
UncheckedInstance(Context & context,vk::VkInstance instance,const vk::VkAllocationCallbacks * pAllocator,std::unique_ptr<DebugReportRecorder> & recorder)198 UncheckedInstance::UncheckedInstance (Context& context, vk::VkInstance instance, const vk::VkAllocationCallbacks* pAllocator, std::unique_ptr<DebugReportRecorder>& recorder)
199 #else
200 UncheckedInstance::UncheckedInstance(Context& context, vk::VkInstance instance, const vk::VkAllocationCallbacks* pAllocator)
201 #endif // CTS_USES_VULKANSC
202 
203 	: m_context		(&context)
204 #ifndef CTS_USES_VULKANSC
205 	, m_recorder	(recorder.release())
206 #endif // CTS_USES_VULKANSC
207 	, m_allocator	(pAllocator)
208 	, m_instance	(instance)
209 #ifndef CTS_USES_VULKANSC
210 	, m_driver((m_instance != DE_NULL) ? new InstanceDriver(context.getPlatformInterface(), m_instance) : nullptr)
211 	, m_callback	((m_driver && m_recorder) ? m_recorder->createCallback(*m_driver, m_instance) : Move<VkDebugReportCallbackEXT>())
212 #else
213 	, m_driver((m_instance != DE_NULL) ? new InstanceDriverSC(context.getPlatformInterface(), m_instance, context.getTestContext().getCommandLine(), context.getResourceInterface()) : nullptr)
214 #endif // CTS_USES_VULKANSC
215 {
216 }
217 
~UncheckedInstance()218 UncheckedInstance::~UncheckedInstance ()
219 {
220 #ifndef CTS_USES_VULKANSC
221 	if (m_recorder)
222 		collectAndReportDebugMessages(*m_recorder, *m_context);
223 #endif // CTS_USES_VULKANSC
224 
225 	if (m_instance != DE_NULL)
226 	{
227 #ifndef CTS_USES_VULKANSC
228 		m_callback = vk::Move<vk::VkDebugReportCallbackEXT>();
229 		m_recorder.reset(nullptr);
230 #endif // CTS_USES_VULKANSC
231 		m_driver->destroyInstance(m_instance, m_allocator);
232 	}
233 }
234 
swap(UncheckedInstance & other)235 void UncheckedInstance::swap (UncheckedInstance& other)
236 {
237 	std::swap(m_context, other.m_context);
238 #ifndef CTS_USES_VULKANSC
239 	m_recorder.swap(other.m_recorder);
240 #endif // CTS_USES_VULKANSC
241 	std::swap(m_allocator, other.m_allocator);
242 	vk::VkInstance aux = m_instance; m_instance = other.m_instance; other.m_instance = aux;
243 	m_driver.swap(other.m_driver);
244 #ifndef CTS_USES_VULKANSC
245 	Move<VkDebugReportCallbackEXT> aux2 = m_callback; m_callback = other.m_callback; other.m_callback = aux2;
246 #endif // CTS_USES_VULKANSC
247 }
248 
UncheckedInstance(UncheckedInstance && other)249 UncheckedInstance::UncheckedInstance (UncheckedInstance&& other)
250 	: UncheckedInstance()
251 {
252 	this->swap(other);
253 }
254 
operator =(UncheckedInstance && other)255 UncheckedInstance& UncheckedInstance::operator= (UncheckedInstance&& other)
256 {
257 	UncheckedInstance destroyer;
258 	destroyer.swap(other);
259 	this->swap(destroyer);
260 	return *this;
261 }
262 
operator vk::VkInstance() const263 UncheckedInstance::operator vk::VkInstance () const
264 {
265 	return m_instance;
266 }
operator bool() const267 UncheckedInstance::operator bool () const
268 {
269 	return (m_instance != DE_NULL);
270 }
271 
createCustomInstanceWithExtensions(Context & context,const std::vector<std::string> & extensions,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)272 CustomInstance createCustomInstanceWithExtensions (Context& context, const std::vector<std::string>& extensions, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers)
273 {
274 	vector<const char*>	enabledLayers;
275 	vector<string>		enabledLayersStr;
276 	const auto&			cmdLine					= context.getTestContext().getCommandLine();
277 	const bool			validationRequested		= (cmdLine.isValidationEnabled() && allowLayers);
278 #ifndef CTS_USES_VULKANSC
279 	const bool			printValidationErrors	= cmdLine.printValidationErrors();
280 #endif // CTS_USES_VULKANSC
281 
282 	if (validationRequested)
283 	{
284 		enabledLayers = getValidationLayers(context.getPlatformInterface());
285 		enabledLayersStr = vector<string>(begin(enabledLayers), end(enabledLayers));
286 	}
287 
288 	const bool validationEnabled = !enabledLayers.empty();
289 
290 	// Filter extension list and throw NotSupported if a required extension is not supported.
291 	const deUint32									apiVersion			= context.getUsedApiVersion();
292 	const vk::PlatformInterface&					vkp					= context.getPlatformInterface();
293 	const vector<vk::VkExtensionProperties>			availableExtensions	= vk::enumerateInstanceExtensionProperties(vkp, DE_NULL);
294 	std::set<string>								usedExtensions;
295 
296 	// Get list of available extension names.
297 	vector<string> availableExtensionNames;
298 	for (const auto& ext : availableExtensions)
299 		availableExtensionNames.push_back(ext.extensionName);
300 
301 	// Filter duplicates and remove core extensions.
302 	for (const auto& ext : extensions)
303 	{
304 		if (!vk::isCoreInstanceExtension(apiVersion, ext))
305 			usedExtensions.insert(ext);
306 	}
307 
308 	// Add debug extension if validation is enabled.
309 	if (validationEnabled)
310 		usedExtensions.insert("VK_EXT_debug_report");
311 
312 	// Check extension support.
313 	for (const auto& ext : usedExtensions)
314 	{
315 		if (!vk::isInstanceExtensionSupported(apiVersion, availableExtensionNames, ext))
316 			TCU_THROW(NotSupportedError, ext + " is not supported");
317 	}
318 
319 #ifndef CTS_USES_VULKANSC
320 	std::unique_ptr<DebugReportRecorder> debugReportRecorder;
321 	if (validationEnabled)
322 		debugReportRecorder.reset(new DebugReportRecorder(printValidationErrors));
323 #endif // CTS_USES_VULKANSC
324 
325 	// Create custom instance.
326 	const vector<string> usedExtensionsVec(begin(usedExtensions), end(usedExtensions));
327 #ifndef CTS_USES_VULKANSC
328 	Move<VkInstance> instance = vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, usedExtensionsVec, cmdLine, debugReportRecorder.get(), pAllocator);
329 	return CustomInstance(context, instance, debugReportRecorder);
330 #else
331 	Move<VkInstance> instance = vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, usedExtensionsVec, cmdLine, pAllocator);
332 	return CustomInstance(context, instance);
333 #endif // CTS_USES_VULKANSC
334 }
335 
createCustomInstanceWithExtension(Context & context,const std::string & extension,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)336 CustomInstance createCustomInstanceWithExtension (Context& context, const std::string& extension, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers)
337 {
338 	return createCustomInstanceWithExtensions(context, std::vector<std::string>(1, extension), pAllocator, allowLayers);
339 }
340 
createCustomInstanceFromContext(Context & context,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)341 CustomInstance createCustomInstanceFromContext (Context& context, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers)
342 {
343 	return createCustomInstanceWithExtensions(context, std::vector<std::string>(), pAllocator, allowLayers);
344 }
345 
346 const char kDebugReportExt[] = "VK_EXT_debug_report";
347 
addDebugReportExt(const vk::PlatformInterface & vkp,const vk::VkInstanceCreateInfo & createInfo)348 vector<const char*> addDebugReportExt(const vk::PlatformInterface& vkp, const vk::VkInstanceCreateInfo& createInfo)
349 {
350 	if (!isDebugReportSupported(vkp))
351 		TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported");
352 
353 	vector<const char*> actualExtensions;
354 	if (createInfo.enabledExtensionCount != 0u)
355 	{
356 		for (deUint32 i = 0u; i < createInfo.enabledExtensionCount; ++i)
357 			actualExtensions.push_back(createInfo.ppEnabledExtensionNames[i]);
358 	}
359 
360 	if (std::find_if(begin(actualExtensions), end(actualExtensions), [](const char* name) { return (strcmp(name, kDebugReportExt) == 0); })
361 		== end(actualExtensions))
362 	{
363 		actualExtensions.push_back(kDebugReportExt);
364 	}
365 
366 	return actualExtensions;
367 }
368 
createCustomInstanceFromInfo(Context & context,const vk::VkInstanceCreateInfo * instanceCreateInfo,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)369 CustomInstance createCustomInstanceFromInfo (Context& context, const vk::VkInstanceCreateInfo* instanceCreateInfo, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers)
370 {
371 	vector<const char*>						enabledLayers;
372 	vector<const char*>						enabledExtensions;
373 	vk::VkInstanceCreateInfo				createInfo				= *instanceCreateInfo;
374 	const auto&								cmdLine					= context.getTestContext().getCommandLine();
375 	const bool								validationEnabled		= cmdLine.isValidationEnabled();
376 #ifndef CTS_USES_VULKANSC
377 	const bool								printValidationErrors	= cmdLine.printValidationErrors();
378 #endif // CTS_USES_VULKANSC
379 	const vk::PlatformInterface&			vkp						= context.getPlatformInterface();
380 #ifndef CTS_USES_VULKANSC
381 	std::unique_ptr<DebugReportRecorder>	recorder;
382 	VkDebugReportCallbackCreateInfoEXT		callbackInfo;
383 #endif // CTS_USES_VULKANSC
384 
385 	if (validationEnabled && allowLayers)
386 	{
387 		// Activate some layers if requested.
388 		if (createInfo.enabledLayerCount == 0u)
389 		{
390 			enabledLayers = getValidationLayers(vkp);
391 			createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size());
392 			createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
393 		}
394 
395 		// Make sure the debug report extension is enabled when validation is enabled.
396 		enabledExtensions = addDebugReportExt(vkp, createInfo);
397 		createInfo.enabledExtensionCount = static_cast<deUint32>(enabledExtensions.size());
398 		createInfo.ppEnabledExtensionNames = enabledExtensions.data();
399 
400 #ifndef CTS_USES_VULKANSC
401 		recorder.reset(new DebugReportRecorder(printValidationErrors));
402 		callbackInfo		= recorder->makeCreateInfo();
403 		callbackInfo.pNext	= createInfo.pNext;
404 		createInfo.pNext	= &callbackInfo;
405 #endif // CTS_USES_VULKANSC
406 	}
407 
408 #ifndef CTS_USES_VULKANSC
409 	return CustomInstance(context, vk::createInstance(vkp, &createInfo, pAllocator), recorder);
410 #else
411 	return CustomInstance(context, vk::createInstance(vkp, &createInfo, pAllocator));
412 #endif // CTS_USES_VULKANSC
413 }
414 
createUncheckedInstance(Context & context,const vk::VkInstanceCreateInfo * instanceCreateInfo,const vk::VkAllocationCallbacks * pAllocator,UncheckedInstance * instance,bool allowLayers)415 vk::VkResult createUncheckedInstance (Context& context, const vk::VkInstanceCreateInfo* instanceCreateInfo, const vk::VkAllocationCallbacks* pAllocator, UncheckedInstance* instance, bool allowLayers)
416 {
417 	vector<const char*>						enabledLayers;
418 	vector<const char*>						enabledExtensions;
419 	vk::VkInstanceCreateInfo				createInfo				= *instanceCreateInfo;
420 	const auto&								cmdLine					= context.getTestContext().getCommandLine();
421 	const bool								validationEnabled		= cmdLine.isValidationEnabled();
422 #ifndef CTS_USES_VULKANSC
423 	const bool								printValidationErrors	= cmdLine.printValidationErrors();
424 #endif // CTS_USES_VULKANSC
425 	const vk::PlatformInterface&			vkp						= context.getPlatformInterface();
426 	const bool								addLayers				= (validationEnabled && allowLayers);
427 #ifndef CTS_USES_VULKANSC
428 	std::unique_ptr<DebugReportRecorder>	recorder;
429 #endif // CTS_USES_VULKANSC
430 
431 	if (addLayers)
432 	{
433 		// Activate some layers if requested.
434 		if (createInfo.enabledLayerCount == 0u)
435 		{
436 			enabledLayers = getValidationLayers(vkp);
437 			createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size());
438 			createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
439 		}
440 
441 		// Make sure the debug report extension is enabled when validation is enabled.
442 		enabledExtensions = addDebugReportExt(vkp, createInfo);
443 		createInfo.enabledExtensionCount = static_cast<deUint32>(enabledExtensions.size());
444 		createInfo.ppEnabledExtensionNames = enabledExtensions.data();
445 
446 #ifndef CTS_USES_VULKANSC
447 		recorder.reset(new DebugReportRecorder(printValidationErrors));
448 		// No need to add VkDebugReportCallbackCreateInfoEXT to VkInstanceCreateInfo since we
449 		// don't want to check for errors at instance creation. This is intended since we use
450 		// UncheckedInstance to try to create invalid instances for driver stability
451 #endif // CTS_USES_VULKANSC
452 	}
453 
454 	vk::VkInstance	raw_instance = DE_NULL;
455 	vk::VkResult	result = vkp.createInstance(&createInfo, pAllocator, &raw_instance);
456 
457 #ifndef CTS_USES_VULKANSC
458 	*instance = UncheckedInstance(context, raw_instance, pAllocator, recorder);
459 #else
460 	*instance = UncheckedInstance(context, raw_instance, pAllocator);
461 #endif // CTS_USES_VULKANSC
462 
463 	return result;
464 }
465 
createCustomDevice(bool validationEnabled,const vk::PlatformInterface & vkp,vk::VkInstance instance,const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const vk::VkDeviceCreateInfo * pCreateInfo,const vk::VkAllocationCallbacks * pAllocator)466 vk::Move<vk::VkDevice> createCustomDevice (bool validationEnabled, const vk::PlatformInterface& vkp, vk::VkInstance instance, const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, const vk::VkDeviceCreateInfo* pCreateInfo, const vk::VkAllocationCallbacks* pAllocator)
467 {
468 	vector<const char*>		enabledLayers;
469 	vk::VkDeviceCreateInfo	createInfo		= *pCreateInfo;
470 
471 	if (createInfo.enabledLayerCount == 0u && validationEnabled)
472 	{
473 		enabledLayers = getValidationLayers(vki, physicalDevice);
474 		createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size());
475 		createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
476 	}
477 
478 #ifdef CTS_USES_VULKANSC
479 	// Add fault callback if there isn't one already.
480 	VkFaultCallbackInfo					faultCallbackInfo		=
481 	{
482 		VK_STRUCTURE_TYPE_FAULT_CALLBACK_INFO,					//	VkStructureType				sType;
483 		DE_NULL,												//	void*						pNext;
484 		0U,														//	uint32_t					faultCount;
485 		nullptr,												//	VkFaultData*				pFaults;
486 		Context::faultCallbackFunction							//	PFN_vkFaultCallbackFunction	pfnFaultCallback;
487 	};
488 
489 	if (!findStructureInChain(createInfo.pNext, getStructureType<VkFaultCallbackInfo>()))
490 	{
491 		// XXX workaround incorrect constness on faultCallbackInfo.pNext.
492 		faultCallbackInfo.pNext = const_cast<void *>(createInfo.pNext);
493 		createInfo.pNext = &faultCallbackInfo;
494 	}
495 #endif // CTS_USES_VULKANSC
496 
497 	return createDevice(vkp, instance, vki, physicalDevice, &createInfo, pAllocator);
498 }
499 
createUncheckedDevice(bool validationEnabled,const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const vk::VkDeviceCreateInfo * pCreateInfo,const vk::VkAllocationCallbacks * pAllocator,vk::VkDevice * pDevice)500 vk::VkResult createUncheckedDevice (bool validationEnabled, const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, const vk::VkDeviceCreateInfo* pCreateInfo, const vk::VkAllocationCallbacks* pAllocator, vk::VkDevice* pDevice)
501 {
502 	vector<const char*>		enabledLayers;
503 	vk::VkDeviceCreateInfo	createInfo		= *pCreateInfo;
504 
505 	if (createInfo.enabledLayerCount == 0u && validationEnabled)
506 	{
507 		enabledLayers = getValidationLayers(vki, physicalDevice);
508 		createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size());
509 		createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
510 	}
511 
512 #ifdef CTS_USES_VULKANSC
513 	// Add fault callback if there isn't one already.
514 	VkFaultCallbackInfo					faultCallbackInfo		=
515 	{
516 		VK_STRUCTURE_TYPE_FAULT_CALLBACK_INFO,					//	VkStructureType				sType;
517 		DE_NULL,												//	void*						pNext;
518 		0U,														//	uint32_t					faultCount;
519 		nullptr,												//	VkFaultData*				pFaults;
520 		Context::faultCallbackFunction							//	PFN_vkFaultCallbackFunction	pfnFaultCallback;
521 	};
522 
523 	if (!findStructureInChain(createInfo.pNext, getStructureType<VkFaultCallbackInfo>()))
524 	{
525 		// XXX workaround incorrect constness on faultCallbackInfo.pNext.
526 		faultCallbackInfo.pNext = const_cast<void *>(createInfo.pNext);
527 		createInfo.pNext = &faultCallbackInfo;
528 	}
529 #endif // CTS_USES_VULKANSC
530 
531 	return vki.createDevice(physicalDevice, &createInfo, pAllocator, pDevice);
532 }
533 
CustomInstanceWrapper(Context & context)534 CustomInstanceWrapper::CustomInstanceWrapper(Context& context)
535 	: instance(vkt::createCustomInstanceFromContext(context))
536 {
537 }
538 
CustomInstanceWrapper(Context & context,const std::vector<std::string> extensions)539 CustomInstanceWrapper::CustomInstanceWrapper(Context& context, const std::vector<std::string> extensions)
540 	: instance(vkt::createCustomInstanceWithExtensions(context, extensions))
541 {
542 }
checkSupport(Context & context,const VideoCodecOperationFlags videoCodecOperation)543 void VideoDevice::checkSupport (Context&						context,
544 								const VideoCodecOperationFlags	videoCodecOperation)
545 {
546 #ifndef CTS_USES_VULKANSC
547 	DE_ASSERT(videoCodecOperation != 0 && isVideoOperation(videoCodecOperation));
548 
549 	if (isVideoOperation(videoCodecOperation))
550 		context.requireDeviceFunctionality("VK_KHR_video_queue");
551 
552 	if (isVideoEncodeOperation(videoCodecOperation))
553 		context.requireDeviceFunctionality("VK_KHR_video_encode_queue");
554 
555 	if (isVideoDecodeOperation(videoCodecOperation))
556 		context.requireDeviceFunctionality("VK_KHR_video_decode_queue");
557 
558 	if ((videoCodecOperation & vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT) != 0)
559 		context.requireDeviceFunctionality("VK_EXT_video_encode_h264");
560 
561 	if ((videoCodecOperation & vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT) != 0)
562 		context.requireDeviceFunctionality("VK_EXT_video_encode_h265");
563 
564 	if ((videoCodecOperation & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) != 0)
565 		context.requireDeviceFunctionality("VK_KHR_video_decode_h264");
566 
567 	if ((videoCodecOperation & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) != 0)
568 		context.requireDeviceFunctionality("VK_KHR_video_decode_h265");
569 #else
570 	DE_UNREF(context);
571 	DE_UNREF(videoCodecOperation);
572 #endif
573 }
574 
VideoDevice(Context & context)575 VideoDevice::VideoDevice (Context& context)
576 	: m_context				(context)
577 	, m_logicalDevice		()
578 	, m_deviceDriver		()
579 	, m_allocator			()
580 	, m_queueFamilyTransfer	(VK_QUEUE_FAMILY_IGNORED)
581 	, m_queueFamilyDecode	(VK_QUEUE_FAMILY_IGNORED)
582 	, m_queueFamilyEncode	(VK_QUEUE_FAMILY_IGNORED)
583 #ifndef CTS_USES_VULKANSC
584 	, m_videoCodecOperation	(vk::VK_VIDEO_CODEC_OPERATION_NONE_KHR)
585 #else
586 	, m_videoCodecOperation	(~0u)
587 #endif
588 {
589 }
590 
VideoDevice(Context & context,const VideoCodecOperationFlags videoCodecOperation,const VideoDeviceFlags videoDeviceFlags)591 VideoDevice::VideoDevice (Context&							context,
592 						  const VideoCodecOperationFlags	videoCodecOperation,
593 						  const VideoDeviceFlags			videoDeviceFlags)
594 	: VideoDevice	(context)
595 {
596 #ifndef CTS_USES_VULKANSC
597 	const vk::VkQueueFlags	queueFlagsRequired	= getQueueFlags(videoCodecOperation);
598 	const vk::VkDevice		result				= getDeviceSupportingQueue(queueFlagsRequired, videoCodecOperation, videoDeviceFlags);
599 
600 	DE_ASSERT(result != DE_NULL);
601 	DE_UNREF(result);
602 #else
603 	DE_UNREF(videoCodecOperation);
604 	DE_UNREF(videoDeviceFlags);
605 #endif
606 }
607 
~VideoDevice(void)608 VideoDevice::~VideoDevice (void)
609 {
610 }
611 
getQueueFlags(const VideoCodecOperationFlags videoCodecOperation)612 vk::VkQueueFlags VideoDevice::getQueueFlags (const VideoCodecOperationFlags videoCodecOperation)
613 {
614 #ifndef CTS_USES_VULKANSC
615 	const vk::VkQueueFlags	queueFlagsRequired	= (isVideoEncodeOperation(videoCodecOperation) ? vk::VK_QUEUE_VIDEO_ENCODE_BIT_KHR : 0)
616 												| (isVideoDecodeOperation(videoCodecOperation) ? vk::VK_QUEUE_VIDEO_DECODE_BIT_KHR : 0);
617 
618 	return queueFlagsRequired;
619 #else
620 	DE_UNREF(videoCodecOperation);
621 
622 	return 0;
623 #endif
624 }
625 
isVideoEncodeOperation(const VideoCodecOperationFlags videoCodecOperationFlags)626 bool VideoDevice::isVideoEncodeOperation (const VideoCodecOperationFlags videoCodecOperationFlags)
627 {
628 #ifndef CTS_USES_VULKANSC
629 	const vk::VkVideoCodecOperationFlagsKHR	encodeOperations	= vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT
630 																| vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT;
631 
632 	return (encodeOperations & videoCodecOperationFlags) != 0;
633 #else
634 	DE_UNREF(videoCodecOperationFlags);
635 
636 	return false;
637 #endif
638 }
639 
isVideoDecodeOperation(const VideoCodecOperationFlags videoCodecOperationFlags)640 bool VideoDevice::isVideoDecodeOperation (const VideoCodecOperationFlags videoCodecOperationFlags)
641 {
642 #ifndef CTS_USES_VULKANSC
643 	const vk::VkVideoCodecOperationFlagsKHR	decodeOperations	= vk::VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR
644 																| vk::VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR;
645 
646 	return (decodeOperations & videoCodecOperationFlags) != 0;
647 #else
648 	DE_UNREF(videoCodecOperationFlags);
649 
650 	return false;
651 #endif
652 }
653 
isVideoOperation(const VideoCodecOperationFlags videoCodecOperationFlags)654 bool VideoDevice::isVideoOperation (const VideoCodecOperationFlags videoCodecOperationFlags)
655 {
656 #ifndef CTS_USES_VULKANSC
657 	return isVideoDecodeOperation(videoCodecOperationFlags) || isVideoEncodeOperation(videoCodecOperationFlags);
658 #else
659 	DE_UNREF(videoCodecOperationFlags);
660 
661 	return false;
662 #endif
663 }
664 
addVideoDeviceExtensions(std::vector<const char * > & deviceExtensions,const uint32_t apiVersion,const vk::VkQueueFlags queueFlagsRequired,const VideoCodecOperationFlags videoCodecOperationFlags)665 void VideoDevice::addVideoDeviceExtensions (std::vector<const char*>&		deviceExtensions,
666 											const uint32_t					apiVersion,
667 											const vk::VkQueueFlags			queueFlagsRequired,
668 											const VideoCodecOperationFlags	videoCodecOperationFlags)
669 {
670 #ifndef CTS_USES_VULKANSC
671 	static const char videoQueue[]			= "VK_KHR_video_queue";
672 	static const char videoEncodeQueue[]	= "VK_KHR_video_encode_queue";
673 	static const char videoDecodeQueue[]	= "VK_KHR_video_decode_queue";
674 	static const char videoEncodeH264[]		= "VK_EXT_video_encode_h264";
675 	static const char videoEncodeH265[]		= "VK_EXT_video_encode_h265";
676 	static const char videoDecodeH264[]		= "VK_KHR_video_decode_h264";
677 	static const char videoDecodeH265[]		= "VK_KHR_video_decode_h265";
678 
679 	if (!vk::isCoreDeviceExtension(apiVersion, videoQueue))
680 		deviceExtensions.push_back(videoQueue);
681 
682 	if ((queueFlagsRequired & vk::VK_QUEUE_VIDEO_ENCODE_BIT_KHR) != 0)
683 		if (!vk::isCoreDeviceExtension(apiVersion, videoEncodeQueue))
684 			deviceExtensions.push_back(videoEncodeQueue);
685 
686 	if ((queueFlagsRequired & vk::VK_QUEUE_VIDEO_DECODE_BIT_KHR) != 0)
687 		if (!vk::isCoreDeviceExtension(apiVersion, videoDecodeQueue))
688 			deviceExtensions.push_back(videoDecodeQueue);
689 
690 	if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_EXT) != 0)
691 		if (!vk::isCoreDeviceExtension(apiVersion, videoEncodeH264))
692 			deviceExtensions.push_back(videoEncodeH264);
693 
694 	if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_EXT) != 0)
695 		if (!vk::isCoreDeviceExtension(apiVersion, videoEncodeH265))
696 			deviceExtensions.push_back(videoEncodeH265);
697 
698 	if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR) != 0)
699 		if (!vk::isCoreDeviceExtension(apiVersion, videoDecodeH265))
700 			deviceExtensions.push_back(videoDecodeH265);
701 
702 	if ((videoCodecOperationFlags & vk::VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR) != 0)
703 		if (!vk::isCoreDeviceExtension(apiVersion, videoDecodeH264))
704 			deviceExtensions.push_back(videoDecodeH264);
705 #else
706 	DE_UNREF(deviceExtensions);
707 	DE_UNREF(apiVersion);
708 	DE_UNREF(queueFlagsRequired);
709 	DE_UNREF(videoCodecOperationFlags);
710 #endif
711 }
712 
getDeviceSupportingQueue(const vk::VkQueueFlags queueFlagsRequired,const VideoCodecOperationFlags videoCodecOperationFlags,const VideoDevice::VideoDeviceFlags videoDeviceFlags)713 vk::VkDevice VideoDevice::getDeviceSupportingQueue (const vk::VkQueueFlags					queueFlagsRequired,
714 													const VideoCodecOperationFlags			videoCodecOperationFlags,
715 													const VideoDevice::VideoDeviceFlags		videoDeviceFlags)
716 {
717 #ifndef CTS_USES_VULKANSC
718 	if (*m_logicalDevice == DE_NULL)
719 	{
720 		DE_ASSERT(static_cast<deUint32>(queueFlagsRequired) != 0u);
721 		DE_ASSERT(static_cast<deUint32>(videoCodecOperationFlags) != 0u);
722 
723 		if (!createDeviceSupportingQueue(queueFlagsRequired, videoCodecOperationFlags, videoDeviceFlags))
724 			TCU_THROW(NotSupportedError, "Cannot create device with required parameters");
725 	}
726 
727 	return *m_logicalDevice;
728 #else
729 	DE_UNREF(queueFlagsRequired);
730 	DE_UNREF(videoCodecOperationFlags);
731 	DE_UNREF(videoDeviceFlags);
732 
733 	TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
734 #endif
735 }
736 
createDeviceSupportingQueue(const vk::VkQueueFlags queueFlagsRequired,const VideoCodecOperationFlags videoCodecOperationFlags,const VideoDeviceFlags videoDeviceFlags)737 bool VideoDevice::createDeviceSupportingQueue (const vk::VkQueueFlags			queueFlagsRequired,
738 											   const VideoCodecOperationFlags	videoCodecOperationFlags,
739 											   const VideoDeviceFlags			videoDeviceFlags)
740 {
741 #ifndef CTS_USES_VULKANSC
742 	const vk::PlatformInterface&								vkp											= m_context.getPlatformInterface();
743 	const vk::InstanceInterface&								vki											= m_context.getInstanceInterface();
744 	const vk::VkPhysicalDevice									physicalDevice								= m_context.getPhysicalDevice();
745 	const vk::VkInstance										instance									= m_context.getInstance();
746 	const deUint32												apiVersion									= m_context.getUsedApiVersion();
747 	const bool													validationEnabled							= m_context.getTestContext().getCommandLine().isValidationEnabled();
748 	const bool													queryWithStatusForDecodeSupport				= (videoDeviceFlags & VIDEO_DEVICE_FLAG_QUERY_WITH_STATUS_FOR_DECODE_SUPPORT) != 0;
749 	const bool													requireYCBCRorNotSupported					= (videoDeviceFlags & VIDEO_DEVICE_FLAG_REQUIRE_YCBCR_OR_NOT_SUPPORTED) != 0;
750 	const bool													requireSync2orNotSupported					= (videoDeviceFlags & VIDEO_DEVICE_FLAG_REQUIRE_SYNC2_OR_NOT_SUPPORTED) != 0;
751 	const float													queueFamilyPriority							= 1.0f;
752 	deUint32													queueFamilyPropertiesCount					= 0u;
753 	deUint32													queueFamilyTransfer							= VK_QUEUE_FAMILY_IGNORED;
754 	deUint32													queueFamilyDecode							= VK_QUEUE_FAMILY_IGNORED;
755 	deUint32													queueFamilyEncode							= VK_QUEUE_FAMILY_IGNORED;
756 	vk::VkQueueFlags											queueFlagsFound								= 0;
757 	vector<vk::VkQueueFamilyProperties2>						queueFamilyProperties2;
758 	vector<vk::VkQueueFamilyVideoPropertiesKHR>				videoQueueFamilyProperties2;
759 	vector<vk::VkQueueFamilyQueryResultStatusPropertiesKHR>	VkQueueFamilyQueryResultStatusPropertiesKHR;
760 	vector<const char*>											deviceExtensions;
761 	vector<vk::VkDeviceQueueCreateInfo>							queueInfos;
762 
763 	DE_ASSERT(queueFlagsRequired != 0);
764 	DE_ASSERT(videoCodecOperationFlags != 0);
765 
766 	vki.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount, DE_NULL);
767 
768 	if(queueFamilyPropertiesCount == 0u)
769 		TCU_FAIL("Device reports an empty set of queue family properties");
770 
771 	queueFamilyProperties2.resize(queueFamilyPropertiesCount);
772 	videoQueueFamilyProperties2.resize(queueFamilyPropertiesCount);
773 	VkQueueFamilyQueryResultStatusPropertiesKHR.resize(queueFamilyPropertiesCount);
774 
775 	for (size_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
776 	{
777 		queueFamilyProperties2[ndx].sType											= vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2;
778 		queueFamilyProperties2[ndx].pNext											= &videoQueueFamilyProperties2[ndx];
779 		videoQueueFamilyProperties2[ndx].sType										= vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_VIDEO_PROPERTIES_KHR;
780 		videoQueueFamilyProperties2[ndx].pNext										= &VkQueueFamilyQueryResultStatusPropertiesKHR[ndx];
781 		videoQueueFamilyProperties2[ndx].videoCodecOperations						= 0;
782 		VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].sType						= vk::VK_STRUCTURE_TYPE_QUEUE_FAMILY_QUERY_RESULT_STATUS_PROPERTIES_KHR;
783 		VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].pNext						= DE_NULL;
784 		VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].queryResultStatusSupport	= DE_FALSE;
785 	}
786 
787 	vki.getPhysicalDeviceQueueFamilyProperties2(physicalDevice, &queueFamilyPropertiesCount, queueFamilyProperties2.data());
788 
789 	if (queueFamilyPropertiesCount != queueFamilyProperties2.size())
790 		TCU_FAIL("Device returns less queue families than initially reported");
791 
792 	for (uint32_t ndx = 0; ndx < queueFamilyPropertiesCount; ++ndx)
793 	{
794 		const vk::VkQueueFamilyProperties&	queueFamilyProperties	= queueFamilyProperties2[ndx].queueFamilyProperties;
795 		const vk::VkQueueFlags				usefulQueueFlags		= queueFamilyProperties.queueFlags & queueFlagsRequired & ~queueFlagsFound;
796 
797 		if (usefulQueueFlags != 0)
798 		{
799 			bool	assigned	= false;
800 
801 			if ((usefulQueueFlags & vk::VK_QUEUE_TRANSFER_BIT) != 0 && queueFamilyTransfer == VK_QUEUE_FAMILY_IGNORED)
802 			{
803 				queueFamilyTransfer	= ndx;
804 				assigned			= true;
805 			}
806 
807 			if ((videoQueueFamilyProperties2[ndx].videoCodecOperations & videoCodecOperationFlags) != 0)
808 			{
809 				if ((usefulQueueFlags & vk::VK_QUEUE_VIDEO_DECODE_BIT_KHR) != 0 && queueFamilyDecode == VK_QUEUE_FAMILY_IGNORED)
810 				{
811 					if (!queryWithStatusForDecodeSupport || (queryWithStatusForDecodeSupport && VkQueueFamilyQueryResultStatusPropertiesKHR[ndx].queryResultStatusSupport))
812 					{
813 						queueFamilyDecode	= ndx;
814 						assigned			= true;
815 					}
816 				}
817 
818 				if ((usefulQueueFlags & vk::VK_QUEUE_VIDEO_ENCODE_BIT_KHR) != 0 && queueFamilyEncode == VK_QUEUE_FAMILY_IGNORED)
819 				{
820 					queueFamilyEncode	= ndx;
821 					assigned			= true;
822 				}
823 			}
824 
825 			if (assigned)
826 			{
827 				const vk::VkDeviceQueueCreateInfo	queueInfo =
828 				{
829 					vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,	//  VkStructureType				sType;
830 					DE_NULL,										//  const void*					pNext;
831 					(vk::VkDeviceQueueCreateFlags)0u,				//  VkDeviceQueueCreateFlags	flags;
832 					ndx,											//  deUint32					queueFamilyIndex;
833 					1u,												//  deUint32					queueCount;
834 					&queueFamilyPriority,							//  const float*				pQueuePriorities;
835 				};
836 
837 				if (queueFamilyProperties.queueCount == 0)
838 					TCU_FAIL("Video queue returned queueCount is zero");
839 
840 				queueInfos.push_back(queueInfo);
841 
842 				queueFlagsFound |= usefulQueueFlags;
843 
844 				if (queueFlagsFound == queueFlagsRequired)
845 					break;
846 			}
847 		}
848 	}
849 
850 	if (queueFlagsFound != queueFlagsRequired)
851 		return false;
852 
853 	addVideoDeviceExtensions(deviceExtensions, apiVersion, queueFlagsRequired, videoCodecOperationFlags);
854 
855 	if (requireYCBCRorNotSupported)
856 		if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_sampler_ycbcr_conversion"))
857 			deviceExtensions.push_back("VK_KHR_sampler_ycbcr_conversion");
858 
859 	if (requireSync2orNotSupported)
860 		if (!vk::isCoreDeviceExtension(apiVersion, "VK_KHR_synchronization2"))
861 			deviceExtensions.push_back("VK_KHR_synchronization2");
862 
863 	vk::VkPhysicalDeviceSynchronization2FeaturesKHR		synchronization2Features		=
864 	{
865 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SYNCHRONIZATION_2_FEATURES_KHR,	//  VkStructureType	sType;
866 		DE_NULL,																//  void*			pNext;
867 		DE_FALSE,																//  VkBool32		synchronization2;
868 	};
869 	vk::VkPhysicalDeviceSamplerYcbcrConversionFeatures	samplerYcbcrConversionFeatures	=
870 	{
871 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES,	//  VkStructureType	sType;
872 		DE_NULL,																	//  void*			pNext;
873 		DE_FALSE,																	//  VkBool32		samplerYcbcrConversion;
874 	};
875 	vk::VkPhysicalDeviceFeatures2						features2						=
876 	{
877 		vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2,	//  VkStructureType				sType;
878 		DE_NULL,											//  void*						pNext;
879 		vk::VkPhysicalDeviceFeatures(),						//  VkPhysicalDeviceFeatures	features;
880 	};
881 
882 	if (requireYCBCRorNotSupported)
883 		appendStructurePtrToVulkanChain((const void**)&features2.pNext, &samplerYcbcrConversionFeatures);
884 
885 	if (requireSync2orNotSupported)
886 		appendStructurePtrToVulkanChain((const void**)&features2.pNext, &synchronization2Features);
887 
888 	vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
889 
890 	if (requireYCBCRorNotSupported && samplerYcbcrConversionFeatures.samplerYcbcrConversion == DE_FALSE)
891 		TCU_THROW(NotSupportedError, "samplerYcbcrConversionFeatures.samplerYcbcrConversion is required");
892 
893 	if (requireSync2orNotSupported && synchronization2Features.synchronization2 == DE_FALSE)
894 		TCU_THROW(NotSupportedError, "synchronization2Features.synchronization2 is required");
895 
896 	features2.features.robustBufferAccess = DE_FALSE;
897 
898 	const vk::VkDeviceCreateInfo						deviceCreateInfo				=
899 	{
900 		vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,	//  VkStructureType					sType;
901 		&features2,									//  const void*						pNext;
902 		(vk::VkDeviceCreateFlags)0,					//  VkDeviceCreateFlags				flags;
903 		static_cast<uint32_t>(queueInfos.size()),	//  deUint32						queueCreateInfoCount;
904 		de::dataOrNull(queueInfos),					//  const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
905 		0u,											//  deUint32						enabledLayerCount;
906 		DE_NULL,									//  const char* const*				ppEnabledLayerNames;
907 		deUint32(deviceExtensions.size()),			//  deUint32						enabledExtensionCount;
908 		de::dataOrNull(deviceExtensions),			//  const char* const*				ppEnabledExtensionNames;
909 		DE_NULL,									//  const VkPhysicalDeviceFeatures*	pEnabledFeatures;
910 	};
911 
912 	m_logicalDevice			= createCustomDevice(validationEnabled, vkp, instance, vki, physicalDevice, &deviceCreateInfo);
913 	m_deviceDriver			= de::MovePtr<vk::DeviceDriver>(new vk::DeviceDriver(vkp, instance, *m_logicalDevice, apiVersion));
914 	m_allocator				= de::MovePtr<vk::Allocator>(new vk::SimpleAllocator(*m_deviceDriver, *m_logicalDevice, getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
915 	m_queueFamilyTransfer	= queueFamilyTransfer;
916 	m_queueFamilyDecode		= queueFamilyDecode;
917 	m_queueFamilyEncode		= queueFamilyEncode;
918 	m_videoCodecOperation	= videoCodecOperationFlags;
919 
920 	return true;
921 #else
922 	DE_UNREF(queueFlagsRequired);
923 	DE_UNREF(videoCodecOperationFlags);
924 	DE_UNREF(videoDeviceFlags);
925 
926 	TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
927 #endif
928 }
929 
getDeviceDriver(void)930 const vk::DeviceDriver& VideoDevice::getDeviceDriver (void)
931 {
932 #ifndef CTS_USES_VULKANSC
933 	DE_ASSERT(m_deviceDriver.get() != DE_NULL);
934 
935 	return *m_deviceDriver;
936 #else
937 	TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
938 #endif
939 }
940 
getQueueFamilyIndexTransfer(void) const941 deUint32 VideoDevice::getQueueFamilyIndexTransfer (void) const
942 {
943 #ifndef CTS_USES_VULKANSC
944 	DE_ASSERT(m_queueFamilyTransfer != VK_QUEUE_FAMILY_IGNORED);
945 
946 	return m_queueFamilyTransfer;
947 #else
948 	TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
949 #endif
950 }
951 
getQueueFamilyIndexDecode(void) const952 deUint32 VideoDevice::getQueueFamilyIndexDecode (void) const
953 {
954 #ifndef CTS_USES_VULKANSC
955 	DE_ASSERT(m_queueFamilyDecode != VK_QUEUE_FAMILY_IGNORED);
956 
957 	return m_queueFamilyDecode;
958 #else
959 	TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
960 #endif
961 }
962 
getQueueFamilyIndexEncode(void) const963 deUint32 VideoDevice::getQueueFamilyIndexEncode (void) const
964 {
965 #ifndef CTS_USES_VULKANSC
966 	DE_ASSERT(m_queueFamilyEncode != VK_QUEUE_FAMILY_IGNORED);
967 
968 	return m_queueFamilyEncode;
969 #else
970 	TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
971 #endif
972 }
973 
getQueueFamilyVideo(void) const974 deUint32 VideoDevice::getQueueFamilyVideo (void) const
975 {
976 #ifndef CTS_USES_VULKANSC
977 	const bool encode = isVideoEncodeOperation(m_videoCodecOperation);
978 	const bool decode = isVideoDecodeOperation(m_videoCodecOperation);
979 
980 	DE_ASSERT((encode && !decode) || (!encode && decode));
981 	DE_UNREF(decode);
982 
983 	return encode ? getQueueFamilyIndexEncode() : getQueueFamilyIndexDecode();
984 #else
985 	TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
986 #endif
987 }
988 
getAllocator(void)989 vk::Allocator& VideoDevice::getAllocator (void)
990 {
991 #ifndef CTS_USES_VULKANSC
992 	DE_ASSERT(m_allocator != DE_NULL);
993 
994 	return *m_allocator;
995 #else
996 	TCU_THROW(NotSupportedError, "Video is not supported for Vulkan SC");
997 #endif
998 }
999 
1000 }
1001