• 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 "tcuCommandLine.hpp"
29 #include "vktCustomInstancesDevices.hpp"
30 
31 #include <algorithm>
32 
33 using std::vector;
34 using std::string;
35 using vk::Move;
36 using vk::VkInstance;
37 using vk::InstanceDriver;
38 using vk::DebugReportRecorder;
39 
40 namespace vkt
41 {
42 
43 namespace
44 {
45 
getValidationLayers(const vector<vk::VkLayerProperties> & supportedLayers)46 vector<const char*> getValidationLayers (const vector<vk::VkLayerProperties>& supportedLayers)
47 {
48 	static const char*	s_magicLayer		= "VK_LAYER_KHRONOS_validation";
49 	static const char*	s_defaultLayers[]	=
50 	{
51 		"VK_LAYER_LUNARG_standard_validation",		// Deprecated by at least Vulkan SDK 1.1.121.
52 		"VK_LAYER_GOOGLE_threading",				// Deprecated by at least Vulkan SDK 1.1.121.
53 		"VK_LAYER_LUNARG_parameter_validation",		// Deprecated by at least Vulkan SDK 1.1.121.
54 		"VK_LAYER_LUNARG_device_limits",
55 		"VK_LAYER_LUNARG_object_tracker",			// Deprecated by at least Vulkan SDK 1.1.121.
56 		"VK_LAYER_LUNARG_image",
57 		"VK_LAYER_LUNARG_core_validation",			// Deprecated by at least Vulkan SDK 1.1.121.
58 		"VK_LAYER_LUNARG_swapchain",
59 		"VK_LAYER_GOOGLE_unique_objects"			// Deprecated by at least Vulkan SDK 1.1.121.
60 	};
61 
62 	vector<const char*>	enabledLayers;
63 
64 	if (vk::isLayerSupported(supportedLayers, vk::RequiredLayer(s_magicLayer)))
65 		enabledLayers.push_back(s_magicLayer);
66 	else
67 	{
68 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_defaultLayers); ++ndx)
69 		{
70 			if (isLayerSupported(supportedLayers, vk::RequiredLayer(s_defaultLayers[ndx])))
71 				enabledLayers.push_back(s_defaultLayers[ndx]);
72 		}
73 	}
74 
75 	return enabledLayers;
76 }
77 
78 } // anonymous
79 
80 
getValidationLayers(const vk::PlatformInterface & vkp)81 vector<const char*> getValidationLayers (const vk::PlatformInterface& vkp)
82 {
83 	return getValidationLayers(enumerateInstanceLayerProperties(vkp));
84 }
85 
getValidationLayers(const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice)86 vector<const char*> getValidationLayers (const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice)
87 {
88 	return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice));
89 }
90 
CustomInstance(Context & context,Move<VkInstance> instance,bool enableDebugReportRecorder,bool printValidationErrors)91 CustomInstance::CustomInstance (Context& context, Move<VkInstance> instance, bool enableDebugReportRecorder, bool printValidationErrors)
92 	: m_context		(&context)
93 	, m_instance	(instance)
94 	, m_driver		(new InstanceDriver(context.getPlatformInterface(), *m_instance))
95 	, m_recorder	(enableDebugReportRecorder ? (new DebugReportRecorder(*m_driver, *m_instance, printValidationErrors)) : nullptr)
96 {
97 }
98 
CustomInstance()99 CustomInstance::CustomInstance ()
100 	: m_context		(nullptr)
101 	, m_instance	()
102 	, m_driver		(nullptr)
103 	, m_recorder	(nullptr)
104 {
105 }
106 
CustomInstance(CustomInstance && other)107 CustomInstance::CustomInstance (CustomInstance&& other)
108 	: CustomInstance()
109 {
110 	this->swap(other);
111 }
112 
~CustomInstance()113 CustomInstance::~CustomInstance ()
114 {
115 	collectMessages();
116 }
117 
operator =(CustomInstance && other)118 CustomInstance&	CustomInstance::operator= (CustomInstance&& other)
119 {
120 	CustomInstance destroyer;
121 	destroyer.swap(other);
122 	this->swap(destroyer);
123 	return *this;
124 }
125 
swap(CustomInstance & other)126 void CustomInstance::swap (CustomInstance& other)
127 {
128 	std::swap(m_context, other.m_context);
129 	Move<VkInstance> aux = m_instance; m_instance = other.m_instance; other.m_instance = aux;
130 	m_driver.swap(other.m_driver);
131 	m_recorder.swap(other.m_recorder);
132 }
133 
operator VkInstance() const134 CustomInstance::operator VkInstance () const
135 {
136 	return *m_instance;
137 }
138 
getDriver() const139 const vk::InstanceDriver& CustomInstance::getDriver() const
140 {
141 	return *m_driver;
142 }
143 
collectMessages()144 void CustomInstance::collectMessages ()
145 {
146 	if (m_recorder)
147 		collectAndReportDebugMessages(*m_recorder, *m_context);
148 }
149 
UncheckedInstance()150 UncheckedInstance::UncheckedInstance ()
151 	: m_context		(nullptr)
152 	, m_allocator	(nullptr)
153 	, m_instance	(DE_NULL)
154 	, m_driver		(nullptr)
155 	, m_recorder	(nullptr)
156 {
157 }
158 
UncheckedInstance(Context & context,vk::VkInstance instance,const vk::VkAllocationCallbacks * pAllocator,bool enableDebugReportRecorder,bool printValidationErrors)159 UncheckedInstance::UncheckedInstance (Context& context, vk::VkInstance instance, const vk::VkAllocationCallbacks* pAllocator, bool enableDebugReportRecorder, bool printValidationErrors)
160 	: m_context		(&context)
161 	, m_allocator	(pAllocator)
162 	, m_instance	(instance)
163 	, m_driver		((m_instance != DE_NULL) ? new InstanceDriver(context.getPlatformInterface(), m_instance) : nullptr)
164 	, m_recorder	((enableDebugReportRecorder && m_instance != DE_NULL) ? (new DebugReportRecorder(*m_driver, m_instance, printValidationErrors)) : nullptr)
165 {
166 }
167 
~UncheckedInstance()168 UncheckedInstance::~UncheckedInstance ()
169 {
170 	if (m_recorder)
171 		collectAndReportDebugMessages(*m_recorder, *m_context);
172 
173 	if (m_instance != DE_NULL)
174 	{
175 		m_recorder.reset(nullptr);
176 		m_driver->destroyInstance(m_instance, m_allocator);
177 	}
178 }
179 
swap(UncheckedInstance & other)180 void UncheckedInstance::swap (UncheckedInstance& other)
181 {
182 	std::swap(m_context, other.m_context);
183 	std::swap(m_allocator, other.m_allocator);
184 	vk::VkInstance aux = m_instance; m_instance = other.m_instance; other.m_instance = aux;
185 	m_driver.swap(other.m_driver);
186 	m_recorder.swap(other.m_recorder);
187 }
188 
UncheckedInstance(UncheckedInstance && other)189 UncheckedInstance::UncheckedInstance (UncheckedInstance&& other)
190 	: UncheckedInstance()
191 {
192 	this->swap(other);
193 }
194 
operator =(UncheckedInstance && other)195 UncheckedInstance& UncheckedInstance::operator= (UncheckedInstance&& other)
196 {
197 	UncheckedInstance destroyer;
198 	destroyer.swap(other);
199 	this->swap(destroyer);
200 	return *this;
201 }
202 
operator vk::VkInstance() const203 UncheckedInstance::operator vk::VkInstance () const
204 {
205 	return m_instance;
206 }
operator bool() const207 UncheckedInstance::operator bool () const
208 {
209 	return (m_instance != DE_NULL);
210 }
211 
createCustomInstanceWithExtensions(Context & context,const std::vector<std::string> & extensions,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)212 CustomInstance createCustomInstanceWithExtensions (Context& context, const std::vector<std::string>& extensions, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers)
213 {
214 	vector<const char*>	enabledLayers;
215 	vector<string>		enabledLayersStr;
216 	const auto&			cmdLine					= context.getTestContext().getCommandLine();
217 	const bool			validationEnabled		= (cmdLine.isValidationEnabled() && allowLayers);
218 	const bool			printValidationErrors	= cmdLine.printValidationErrors();
219 
220 	if (validationEnabled)
221 	{
222 		enabledLayers = getValidationLayers(context.getPlatformInterface());
223 		enabledLayersStr = vector<string>(begin(enabledLayers), end(enabledLayers));
224 	}
225 
226 	// Filter extension list and throw NotSupported if a required extension is not supported.
227 	const deUint32									apiVersion			= context.getUsedApiVersion();
228 	const vk::PlatformInterface&					vkp					= context.getPlatformInterface();
229 	const std::vector<vk::VkExtensionProperties>	availableExtensions	= vk::enumerateInstanceExtensionProperties(vkp, DE_NULL);
230 	vector<string>									extensionPtrs;
231 
232 	vector<string> availableExtensionNames;
233 	for (const auto& ext : availableExtensions)
234 		availableExtensionNames.push_back(ext.extensionName);
235 
236 	for (const auto& ext : extensions)
237 	{
238 		if (!vk::isInstanceExtensionSupported(apiVersion, availableExtensionNames, ext))
239 			TCU_THROW(NotSupportedError, ext + " is not supported");
240 
241 		if (!vk::isCoreInstanceExtension(apiVersion, ext))
242 			extensionPtrs.push_back(ext);
243 	}
244 
245 	Move<VkInstance> instance = vk::createDefaultInstance(vkp, apiVersion, enabledLayersStr, extensionPtrs, pAllocator);
246 	return CustomInstance(context, instance, validationEnabled, printValidationErrors);
247 }
248 
createCustomInstanceWithExtension(Context & context,const std::string & extension,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)249 CustomInstance createCustomInstanceWithExtension (Context& context, const std::string& extension, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers)
250 {
251 	return createCustomInstanceWithExtensions(context, std::vector<std::string>(1, extension), pAllocator, allowLayers);
252 }
253 
createCustomInstanceFromContext(Context & context,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)254 CustomInstance createCustomInstanceFromContext (Context& context, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers)
255 {
256 	return createCustomInstanceWithExtensions(context, std::vector<std::string>(), pAllocator, allowLayers);
257 }
258 
259 const char kDebugReportExt[] = "VK_EXT_debug_report";
260 
addDebugReportExt(const vk::PlatformInterface & vkp,const vk::VkInstanceCreateInfo & createInfo)261 vector<const char*> addDebugReportExt(const vk::PlatformInterface& vkp, const vk::VkInstanceCreateInfo& createInfo)
262 {
263 	if (!isDebugReportSupported(vkp))
264 		TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported");
265 
266 	vector<const char*> actualExtensions;
267 	if (createInfo.enabledExtensionCount != 0u)
268 	{
269 		for (deUint32 i = 0u; i < createInfo.enabledExtensionCount; ++i)
270 			actualExtensions.push_back(createInfo.ppEnabledExtensionNames[i]);
271 	}
272 
273 	if (std::find_if(begin(actualExtensions), end(actualExtensions), [](const char* name) { return (strcmp(name, kDebugReportExt) == 0); })
274 		== end(actualExtensions))
275 	{
276 		actualExtensions.push_back(kDebugReportExt);
277 	}
278 
279 	return actualExtensions;
280 }
281 
createCustomInstanceFromInfo(Context & context,const vk::VkInstanceCreateInfo * instanceCreateInfo,const vk::VkAllocationCallbacks * pAllocator,bool allowLayers)282 CustomInstance createCustomInstanceFromInfo (Context& context, const vk::VkInstanceCreateInfo* instanceCreateInfo, const vk::VkAllocationCallbacks* pAllocator, bool allowLayers)
283 {
284 	vector<const char*>				enabledLayers;
285 	vector<const char*>				enabledExtensions;
286 	vk::VkInstanceCreateInfo		createInfo				= *instanceCreateInfo;
287 	const auto&						cmdLine					= context.getTestContext().getCommandLine();
288 	const bool						validationEnabled		= cmdLine.isValidationEnabled();
289 	const bool						printValidationErrors	= cmdLine.printValidationErrors();
290 	const vk::PlatformInterface&	vkp						= context.getPlatformInterface();
291 
292 	if (validationEnabled && allowLayers)
293 	{
294 		// Activate some layers if requested.
295 		if (createInfo.enabledLayerCount == 0u)
296 		{
297 			enabledLayers = getValidationLayers(vkp);
298 			createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size());
299 			createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
300 		}
301 
302 		// Make sure the debug report extension is enabled when validation is enabled.
303 		enabledExtensions = addDebugReportExt(vkp, createInfo);
304 		createInfo.enabledExtensionCount = static_cast<deUint32>(enabledExtensions.size());
305 		createInfo.ppEnabledExtensionNames = enabledExtensions.data();
306 	}
307 
308 	return CustomInstance(context, vk::createInstance(vkp, &createInfo, pAllocator), validationEnabled, printValidationErrors);
309 }
310 
createUncheckedInstance(Context & context,const vk::VkInstanceCreateInfo * instanceCreateInfo,const vk::VkAllocationCallbacks * pAllocator,UncheckedInstance * instance,bool allowLayers)311 vk::VkResult createUncheckedInstance (Context& context, const vk::VkInstanceCreateInfo* instanceCreateInfo, const vk::VkAllocationCallbacks* pAllocator, UncheckedInstance* instance, bool allowLayers)
312 {
313 	vector<const char*>				enabledLayers;
314 	vector<const char*>				enabledExtensions;
315 	vk::VkInstanceCreateInfo		createInfo				= *instanceCreateInfo;
316 	const auto&						cmdLine					= context.getTestContext().getCommandLine();
317 	const bool						validationEnabled		= cmdLine.isValidationEnabled();
318 	const bool						printValidationErrors	= cmdLine.printValidationErrors();
319 	const vk::PlatformInterface&	vkp						= context.getPlatformInterface();
320 	const bool						addLayers				= (validationEnabled && allowLayers);
321 
322 	if (addLayers)
323 	{
324 		// Activate some layers if requested.
325 		if (createInfo.enabledLayerCount == 0u)
326 		{
327 			enabledLayers = getValidationLayers(vkp);
328 			createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size());
329 			createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
330 		}
331 
332 		// Make sure the debug report extension is enabled when validation is enabled.
333 		enabledExtensions = addDebugReportExt(vkp, createInfo);
334 		createInfo.enabledExtensionCount = static_cast<deUint32>(enabledExtensions.size());
335 		createInfo.ppEnabledExtensionNames = enabledExtensions.data();
336 	}
337 
338 	vk::VkInstance	raw_instance = DE_NULL;
339 	vk::VkResult	result = vkp.createInstance(&createInfo, pAllocator, &raw_instance);
340 
341 	*instance = UncheckedInstance(context, raw_instance, pAllocator, addLayers, printValidationErrors);
342 
343 	return result;
344 }
345 
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)346 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)
347 {
348 	vector<const char*>		enabledLayers;
349 	vk::VkDeviceCreateInfo	createInfo		= *pCreateInfo;
350 
351 	if (createInfo.enabledLayerCount == 0u && validationEnabled)
352 	{
353 		enabledLayers = getValidationLayers(vki, physicalDevice);
354 		createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size());
355 		createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
356 	}
357 
358 	return createDevice(vkp, instance, vki, physicalDevice, &createInfo, pAllocator);
359 }
360 
createUncheckedDevice(bool validationEnabled,const vk::InstanceInterface & vki,vk::VkPhysicalDevice physicalDevice,const vk::VkDeviceCreateInfo * pCreateInfo,const vk::VkAllocationCallbacks * pAllocator,vk::VkDevice * pDevice)361 vk::VkResult createUncheckedDevice (bool validationEnabled, const vk::InstanceInterface& vki, vk::VkPhysicalDevice physicalDevice, const vk::VkDeviceCreateInfo* pCreateInfo, const vk::VkAllocationCallbacks* pAllocator, vk::VkDevice* pDevice)
362 {
363 	vector<const char*>		enabledLayers;
364 	vk::VkDeviceCreateInfo	createInfo		= *pCreateInfo;
365 
366 	if (createInfo.enabledLayerCount == 0u && validationEnabled)
367 	{
368 		enabledLayers = getValidationLayers(vki, physicalDevice);
369 		createInfo.enabledLayerCount = static_cast<deUint32>(enabledLayers.size());
370 		createInfo.ppEnabledLayerNames = (enabledLayers.empty() ? DE_NULL : enabledLayers.data());
371 	}
372 
373 	return vki.createDevice(physicalDevice, &createInfo, pAllocator, pDevice);
374 }
375 
376 
377 }
378