Home | History | Annotate | Download | only in vulkan
      1 /*-------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2015 Google Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Vulkan test case base classes
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "vktTestCase.hpp"
     25 
     26 #include "vkRef.hpp"
     27 #include "vkRefUtil.hpp"
     28 #include "vkQueryUtil.hpp"
     29 #include "vkDeviceUtil.hpp"
     30 #include "vkMemUtil.hpp"
     31 #include "vkPlatform.hpp"
     32 #include "vkDebugReportUtil.hpp"
     33 
     34 #include "tcuCommandLine.hpp"
     35 
     36 #include "deMemory.h"
     37 
     38 namespace vkt
     39 {
     40 
     41 // Default device utilities
     42 
     43 using std::vector;
     44 using std::string;
     45 using namespace vk;
     46 
     47 vector<string> getValidationLayers (const vector<VkLayerProperties>& supportedLayers)
     48 {
     49 	static const char*	s_magicLayer		= "VK_LAYER_LUNARG_standard_validation";
     50 	static const char*	s_defaultLayers[]	=
     51 	{
     52 		"VK_LAYER_GOOGLE_threading",
     53 		"VK_LAYER_LUNARG_parameter_validation",
     54 		"VK_LAYER_LUNARG_device_limits",
     55 		"VK_LAYER_LUNARG_object_tracker",
     56 		"VK_LAYER_LUNARG_image",
     57 		"VK_LAYER_LUNARG_core_validation",
     58 		"VK_LAYER_LUNARG_swapchain",
     59 		"VK_LAYER_GOOGLE_unique_objects"
     60 	};
     61 
     62 	vector<string>		enabledLayers;
     63 
     64 	if (isLayerSupported(supportedLayers, 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, RequiredLayer(s_defaultLayers[ndx])))
     71 				enabledLayers.push_back(s_defaultLayers[ndx]);
     72 		}
     73 	}
     74 
     75 	return enabledLayers;
     76 }
     77 
     78 vector<string> getValidationLayers (const PlatformInterface& vkp)
     79 {
     80 	return getValidationLayers(enumerateInstanceLayerProperties(vkp));
     81 }
     82 
     83 vector<string> getValidationLayers (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
     84 {
     85 	return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice));
     86 }
     87 
     88 Move<VkInstance> createInstance (const PlatformInterface& vkp, const tcu::CommandLine& cmdLine)
     89 {
     90 	const bool		isValidationEnabled	= cmdLine.isValidationEnabled();
     91 	vector<string>	enabledExtensions;
     92 	vector<string>	enabledLayers;
     93 
     94 	if (isValidationEnabled)
     95 	{
     96 		if (isDebugReportSupported(vkp))
     97 			enabledExtensions.push_back("VK_EXT_debug_report");
     98 		else
     99 			TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported");
    100 
    101 		enabledLayers = getValidationLayers(vkp);
    102 		if (enabledLayers.empty())
    103 			TCU_THROW(NotSupportedError, "No validation layers found");
    104 	}
    105 
    106 	return createDefaultInstance(vkp, enabledLayers, enabledExtensions);
    107 }
    108 
    109 static deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
    110 {
    111 	const vector<VkQueueFamilyProperties>	queueProps	= getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice);
    112 
    113 	for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
    114 	{
    115 		if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps)
    116 			return (deUint32)queueNdx;
    117 	}
    118 
    119 	TCU_THROW(NotSupportedError, "No matching queue found");
    120 }
    121 
    122 Move<VkDevice> createDefaultDevice (const InstanceInterface&		vki,
    123 									VkPhysicalDevice				physicalDevice,
    124 									deUint32						queueIndex,
    125 									const VkPhysicalDeviceFeatures&	enabledFeatures,
    126 									const vector<string>&			enabledExtensions,
    127 									const tcu::CommandLine&			cmdLine)
    128 {
    129 	VkDeviceQueueCreateInfo		queueInfo;
    130 	VkDeviceCreateInfo			deviceInfo;
    131 	vector<string>				enabledLayers;
    132 	vector<const char*>			layerPtrs;
    133 	vector<const char*>			extensionPtrs;
    134 	const float					queuePriority	= 1.0f;
    135 
    136 	deMemset(&queueInfo,	0, sizeof(queueInfo));
    137 	deMemset(&deviceInfo,	0, sizeof(deviceInfo));
    138 
    139 	if (cmdLine.isValidationEnabled())
    140 	{
    141 		enabledLayers = getValidationLayers(vki, physicalDevice);
    142 		if (enabledLayers.empty())
    143 			TCU_THROW(NotSupportedError, "No validation layers found");
    144 	}
    145 
    146 	layerPtrs.resize(enabledLayers.size());
    147 
    148 	for (size_t ndx = 0; ndx < enabledLayers.size(); ++ndx)
    149 		layerPtrs[ndx] = enabledLayers[ndx].c_str();
    150 
    151 	extensionPtrs.resize(enabledExtensions.size());
    152 
    153 	for (size_t ndx = 0; ndx < enabledExtensions.size(); ++ndx)
    154 		extensionPtrs[ndx] = enabledExtensions[ndx].c_str();
    155 
    156 	queueInfo.sType							= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
    157 	queueInfo.pNext							= DE_NULL;
    158 	queueInfo.flags							= (VkDeviceQueueCreateFlags)0u;
    159 	queueInfo.queueFamilyIndex				= queueIndex;
    160 	queueInfo.queueCount					= 1u;
    161 	queueInfo.pQueuePriorities				= &queuePriority;
    162 
    163 	deviceInfo.sType						= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    164 	deviceInfo.pNext						= DE_NULL;
    165 	deviceInfo.queueCreateInfoCount			= 1u;
    166 	deviceInfo.pQueueCreateInfos			= &queueInfo;
    167 	deviceInfo.enabledExtensionCount		= (deUint32)extensionPtrs.size();
    168 	deviceInfo.ppEnabledExtensionNames		= (extensionPtrs.empty() ? DE_NULL : &extensionPtrs[0]);
    169 	deviceInfo.enabledLayerCount			= (deUint32)layerPtrs.size();
    170 	deviceInfo.ppEnabledLayerNames			= (layerPtrs.empty() ? DE_NULL : &layerPtrs[0]);
    171 	deviceInfo.pEnabledFeatures				= &enabledFeatures;
    172 
    173 	return createDevice(vki, physicalDevice, &deviceInfo);
    174 };
    175 
    176 class DefaultDevice
    177 {
    178 public:
    179 										DefaultDevice					(const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine);
    180 										~DefaultDevice					(void);
    181 
    182 	VkInstance							getInstance						(void) const	{ return *m_instance;					}
    183 	const InstanceInterface&			getInstanceInterface			(void) const	{ return m_instanceInterface;			}
    184 
    185 	VkPhysicalDevice					getPhysicalDevice				(void) const	{ return m_physicalDevice;				}
    186 	const VkPhysicalDeviceFeatures&		getDeviceFeatures				(void) const	{ return m_deviceFeatures;				}
    187 	VkDevice							getDevice						(void) const	{ return *m_device;						}
    188 	const DeviceInterface&				getDeviceInterface				(void) const	{ return m_deviceInterface;				}
    189 	const VkPhysicalDeviceProperties&	getDeviceProperties				(void) const	{ return m_deviceProperties;			}
    190 	const vector<string>&				getDeviceExtensions				(void) const	{ return m_deviceExtensions;			}
    191 
    192 	deUint32							getUniversalQueueFamilyIndex	(void) const	{ return m_universalQueueFamilyIndex;	}
    193 	VkQueue								getUniversalQueue				(void) const;
    194 
    195 private:
    196 	static VkPhysicalDeviceFeatures		filterDefaultDeviceFeatures		(const VkPhysicalDeviceFeatures& deviceFeatures);
    197 	static vector<string>				filterDefaultDeviceExtensions	(const vector<VkExtensionProperties>& deviceExtensions);
    198 
    199 	const Unique<VkInstance>			m_instance;
    200 	const InstanceDriver				m_instanceInterface;
    201 
    202 	const VkPhysicalDevice				m_physicalDevice;
    203 
    204 	const deUint32						m_universalQueueFamilyIndex;
    205 	const VkPhysicalDeviceFeatures		m_deviceFeatures;
    206 	const VkPhysicalDeviceProperties	m_deviceProperties;
    207 	const vector<string>				m_deviceExtensions;
    208 
    209 	const Unique<VkDevice>				m_device;
    210 	const DeviceDriver					m_deviceInterface;
    211 };
    212 
    213 DefaultDevice::DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine)
    214 	: m_instance					(createInstance(vkPlatform, cmdLine))
    215 	, m_instanceInterface			(vkPlatform, *m_instance)
    216 	, m_physicalDevice				(chooseDevice(m_instanceInterface, *m_instance, cmdLine))
    217 	, m_universalQueueFamilyIndex	(findQueueFamilyIndexWithCaps(m_instanceInterface, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT))
    218 	, m_deviceFeatures				(filterDefaultDeviceFeatures(getPhysicalDeviceFeatures(m_instanceInterface, m_physicalDevice)))
    219 	, m_deviceProperties			(getPhysicalDeviceProperties(m_instanceInterface, m_physicalDevice))
    220 	, m_deviceExtensions			(filterDefaultDeviceExtensions(enumerateDeviceExtensionProperties(m_instanceInterface, m_physicalDevice, DE_NULL)))
    221 	, m_device						(createDefaultDevice(m_instanceInterface, m_physicalDevice, m_universalQueueFamilyIndex, m_deviceFeatures, m_deviceExtensions, cmdLine))
    222 	, m_deviceInterface				(m_instanceInterface, *m_device)
    223 {
    224 }
    225 
    226 DefaultDevice::~DefaultDevice (void)
    227 {
    228 }
    229 
    230 VkQueue DefaultDevice::getUniversalQueue (void) const
    231 {
    232 	VkQueue	queue	= 0;
    233 	m_deviceInterface.getDeviceQueue(*m_device, m_universalQueueFamilyIndex, 0, &queue);
    234 	return queue;
    235 }
    236 
    237 VkPhysicalDeviceFeatures DefaultDevice::filterDefaultDeviceFeatures (const VkPhysicalDeviceFeatures& deviceFeatures)
    238 {
    239 	VkPhysicalDeviceFeatures enabledDeviceFeatures = deviceFeatures;
    240 
    241 	// Disable robustness by default, as it has an impact on performance on some HW.
    242 	enabledDeviceFeatures.robustBufferAccess = false;
    243 
    244 	return enabledDeviceFeatures;
    245 }
    246 
    247 vector<string> DefaultDevice::filterDefaultDeviceExtensions (const vector<VkExtensionProperties>& deviceExtensions)
    248 {
    249 	vector<string> enabledExtensions;
    250 
    251 	// The only extension we enable always (when supported) is
    252 	// VK_KHR_sampler_mirror_clamp_to_edge that is defined in
    253 	// the core spec and supported widely.
    254 	const char* const	mirrorClampToEdgeExt	= "VK_KHR_sampler_mirror_clamp_to_edge";
    255 	if (vk::isExtensionSupported(deviceExtensions, vk::RequiredExtension(mirrorClampToEdgeExt)))
    256 		enabledExtensions.push_back(mirrorClampToEdgeExt);
    257 
    258 	return enabledExtensions;
    259 }
    260 
    261 // Allocator utilities
    262 
    263 vk::Allocator* createAllocator (DefaultDevice* device)
    264 {
    265 	const VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(device->getInstanceInterface(), device->getPhysicalDevice());
    266 
    267 	// \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time)
    268 	return new SimpleAllocator(device->getDeviceInterface(), device->getDevice(), memoryProperties);
    269 }
    270 
    271 // Context
    272 
    273 Context::Context (tcu::TestContext&							testCtx,
    274 				  const vk::PlatformInterface&				platformInterface,
    275 				  vk::ProgramCollection<vk::ProgramBinary>&	progCollection)
    276 	: m_testCtx				(testCtx)
    277 	, m_platformInterface	(platformInterface)
    278 	, m_progCollection		(progCollection)
    279 	, m_device				(new DefaultDevice(m_platformInterface, testCtx.getCommandLine()))
    280 	, m_allocator			(createAllocator(m_device.get()))
    281 {
    282 }
    283 
    284 Context::~Context (void)
    285 {
    286 }
    287 
    288 vk::VkInstance							Context::getInstance					(void) const { return m_device->getInstance();					}
    289 const vk::InstanceInterface&			Context::getInstanceInterface			(void) const { return m_device->getInstanceInterface();			}
    290 vk::VkPhysicalDevice					Context::getPhysicalDevice				(void) const { return m_device->getPhysicalDevice();			}
    291 const vk::VkPhysicalDeviceFeatures&		Context::getDeviceFeatures				(void) const { return m_device->getDeviceFeatures();			}
    292 const vk::VkPhysicalDeviceProperties&	Context::getDeviceProperties			(void) const { return m_device->getDeviceProperties();			}
    293 const vector<string>&					Context::getDeviceExtensions			(void) const { return m_device->getDeviceExtensions();			}
    294 vk::VkDevice							Context::getDevice						(void) const { return m_device->getDevice();					}
    295 const vk::DeviceInterface&				Context::getDeviceInterface				(void) const { return m_device->getDeviceInterface();			}
    296 deUint32								Context::getUniversalQueueFamilyIndex	(void) const { return m_device->getUniversalQueueFamilyIndex();	}
    297 vk::VkQueue								Context::getUniversalQueue				(void) const { return m_device->getUniversalQueue();			}
    298 vk::Allocator&							Context::getDefaultAllocator			(void) const { return *m_allocator;								}
    299 
    300 // TestCase
    301 
    302 void TestCase::initPrograms (SourceCollections&) const
    303 {
    304 }
    305 
    306 } // vkt
    307