1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group 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  vktSparseResourcesBase.cpp
21  * \brief Sparse Resources Base Instance
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktSparseResourcesBase.hpp"
25 #include "vktSparseResourcesTestsUtil.hpp"
26 #include "vktCustomInstancesDevices.hpp"
27 #include "vkMemUtil.hpp"
28 #include "vkRefUtil.hpp"
29 #include "vkTypeUtil.hpp"
30 #include "vkQueryUtil.hpp"
31 #include "vkDeviceUtil.hpp"
32 
33 using namespace vk;
34 
35 namespace vkt
36 {
37 namespace sparse
38 {
39 namespace
40 {
41 
42 struct QueueFamilyQueuesCount
43 {
QueueFamilyQueuesCountvkt::sparse::__anon8aadb8cf0111::QueueFamilyQueuesCount44 	QueueFamilyQueuesCount() : queueCount(0u) {};
45 
46 	deUint32 queueCount;
47 };
48 
findMatchingQueueFamilyIndex(const std::vector<VkQueueFamilyProperties> & queueFamilyProperties,const VkQueueFlags queueFlags,const deUint32 startIndex)49 deUint32 findMatchingQueueFamilyIndex	(const std::vector<VkQueueFamilyProperties>&	queueFamilyProperties,
50 										 const VkQueueFlags								queueFlags,
51 										 const deUint32									startIndex)
52 {
53 	for (deUint32 queueNdx = startIndex; queueNdx < queueFamilyProperties.size(); ++queueNdx)
54 	{
55 		if ((queueFamilyProperties[queueNdx].queueFlags & queueFlags) == queueFlags)
56 			return queueNdx;
57 	}
58 
59 	return NO_MATCH_FOUND;
60 }
61 
62 } // anonymous
63 
createDeviceSupportingQueues(const QueueRequirementsVec & queueRequirements)64 void SparseResourcesBaseInstance::createDeviceSupportingQueues(const QueueRequirementsVec& queueRequirements)
65 {
66 	typedef std::map<VkQueueFlags, std::vector<Queue> >	QueuesMap;
67 	typedef std::map<deUint32, QueueFamilyQueuesCount>	SelectedQueuesMap;
68 	typedef std::map<deUint32, std::vector<float> >		QueuePrioritiesMap;
69 
70 	std::vector<VkPhysicalDeviceGroupProperties>		devGroupProperties;
71 	std::vector<const char*>							deviceExtensions;
72 	VkDeviceGroupDeviceCreateInfo						deviceGroupInfo =
73 	{
74 		VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR,		//stype
75 		DE_NULL,													//pNext
76 		0,															//physicalDeviceCount
77 		DE_NULL														//physicalDevices
78 	};
79 	m_physicalDevices.push_back(m_context.getPhysicalDevice());
80 
81 	// If requested, create an intance with device groups
82 	if (m_useDeviceGroups)
83 	{
84 		const std::vector<std::string>	requiredExtensions(1, "VK_KHR_device_group_creation");
85 		m_deviceGroupInstance	=		createCustomInstanceWithExtensions(m_context, requiredExtensions);
86 		devGroupProperties		=		enumeratePhysicalDeviceGroups(m_context.getInstanceInterface(), m_deviceGroupInstance);
87 		m_numPhysicalDevices	=		devGroupProperties[m_deviceGroupIdx].physicalDeviceCount;
88 
89 		m_physicalDevices.clear();
90 		for (size_t physDeviceID = 0; physDeviceID < m_numPhysicalDevices; physDeviceID++)
91 		{
92 			m_physicalDevices.push_back(devGroupProperties[m_deviceGroupIdx].physicalDevices[physDeviceID]);
93 		}
94 		if (m_numPhysicalDevices < 2)
95 			TCU_THROW(NotSupportedError, "Sparse binding device group tests not supported with 1 physical device");
96 
97 		deviceGroupInfo.physicalDeviceCount = devGroupProperties[m_deviceGroupIdx].physicalDeviceCount;
98 		deviceGroupInfo.pPhysicalDevices = devGroupProperties[m_deviceGroupIdx].physicalDevices;
99 
100 		if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_device_group"))
101 			deviceExtensions.push_back("VK_KHR_device_group");
102 	}
103 
104 	const VkInstance&					instance(m_useDeviceGroups ? m_deviceGroupInstance : m_context.getInstance());
105 	InstanceDriver						instanceDriver(m_context.getPlatformInterface(), instance);
106 	const VkPhysicalDevice				physicalDevice = getPhysicalDevice();
107 	deUint32 queueFamilyPropertiesCount = 0u;
108 	instanceDriver.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, DE_NULL);
109 
110 	if(queueFamilyPropertiesCount == 0u)
111 		TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
112 
113 	std::vector<VkQueueFamilyProperties> queueFamilyProperties;
114 	queueFamilyProperties.resize(queueFamilyPropertiesCount);
115 
116 	instanceDriver.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, &queueFamilyProperties[0]);
117 
118 	if (queueFamilyPropertiesCount == 0u)
119 		TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
120 
121 	SelectedQueuesMap	selectedQueueFamilies;
122 	QueuePrioritiesMap	queuePriorities;
123 
124 	for (deUint32 queueReqNdx = 0; queueReqNdx < queueRequirements.size(); ++queueReqNdx)
125 	{
126 		const QueueRequirements& queueRequirement = queueRequirements[queueReqNdx];
127 
128 		deUint32 queueFamilyIndex	= 0u;
129 		deUint32 queuesFoundCount	= 0u;
130 
131 		do
132 		{
133 			queueFamilyIndex = findMatchingQueueFamilyIndex(queueFamilyProperties, queueRequirement.queueFlags, queueFamilyIndex);
134 
135 			if (queueFamilyIndex == NO_MATCH_FOUND)
136 				TCU_THROW(NotSupportedError, "No match found for queue requirements");
137 
138 			const deUint32 queuesPerFamilyCount = deMin32(queueFamilyProperties[queueFamilyIndex].queueCount, queueRequirement.queueCount - queuesFoundCount);
139 
140 			selectedQueueFamilies[queueFamilyIndex].queueCount = deMax32(queuesPerFamilyCount, selectedQueueFamilies[queueFamilyIndex].queueCount);
141 
142 			for (deUint32 queueNdx = 0; queueNdx < queuesPerFamilyCount; ++queueNdx)
143 			{
144 				Queue queue				= {DE_NULL, 0, 0};
145 				queue.queueFamilyIndex	= queueFamilyIndex;
146 				queue.queueIndex		= queueNdx;
147 
148 				m_queues[queueRequirement.queueFlags].push_back(queue);
149 			}
150 
151 			queuesFoundCount += queuesPerFamilyCount;
152 
153 			++queueFamilyIndex;
154 		} while (queuesFoundCount < queueRequirement.queueCount);
155 	}
156 
157 	std::vector<VkDeviceQueueCreateInfo> queueInfos;
158 
159 	for (SelectedQueuesMap::iterator queueFamilyIter = selectedQueueFamilies.begin(); queueFamilyIter != selectedQueueFamilies.end(); ++queueFamilyIter)
160 	{
161 		for (deUint32 queueNdx = 0; queueNdx < queueFamilyIter->second.queueCount; ++queueNdx)
162 			queuePriorities[queueFamilyIter->first].push_back(1.0f);
163 
164 		const VkDeviceQueueCreateInfo queueInfo =
165 		{
166 			VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,		// VkStructureType			sType;
167 			DE_NULL,										// const void*				pNext;
168 			(VkDeviceQueueCreateFlags)0u,					// VkDeviceQueueCreateFlags	flags;
169 			queueFamilyIter->first,							// uint32_t					queueFamilyIndex;
170 			queueFamilyIter->second.queueCount,				// uint32_t					queueCount;
171 			&queuePriorities[queueFamilyIter->first][0],	// const float*				pQueuePriorities;
172 		};
173 
174 		queueInfos.push_back(queueInfo);
175 	}
176 
177 	const VkPhysicalDeviceFeatures	deviceFeatures	= getPhysicalDeviceFeatures(instanceDriver, physicalDevice);
178 	const VkDeviceCreateInfo		deviceInfo		=
179 	{
180 		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,						// VkStructureType					sType;
181 		m_useDeviceGroups ? &deviceGroupInfo : DE_NULL,				// const void*						pNext;
182 		(VkDeviceCreateFlags)0,										// VkDeviceCreateFlags				flags;
183 		static_cast<deUint32>(queueInfos.size())	,				// uint32_t							queueCreateInfoCount;
184 		&queueInfos[0],												// const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
185 		0u,															// uint32_t							enabledLayerCount;
186 		DE_NULL,													// const char* const*				ppEnabledLayerNames;
187 		deUint32(deviceExtensions.size()),							// uint32_t							enabledExtensionCount;
188 		deviceExtensions.size() ? &deviceExtensions[0] : DE_NULL,	// const char* const*				ppEnabledExtensionNames;
189 		&deviceFeatures,											// const VkPhysicalDeviceFeatures*	pEnabledFeatures;
190 	};
191 
192 	m_logicalDevice = createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(), m_context.getPlatformInterface(), instance, instanceDriver, physicalDevice, &deviceInfo);
193 	m_deviceDriver	= de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), instance, *m_logicalDevice));
194 	m_allocator		= de::MovePtr<Allocator>(new SimpleAllocator(*m_deviceDriver, *m_logicalDevice, getPhysicalDeviceMemoryProperties(instanceDriver, physicalDevice)));
195 
196 	for (QueuesMap::iterator queuesIter = m_queues.begin(); queuesIter != m_queues.end(); ++queuesIter)
197 	{
198 		for (deUint32 queueNdx = 0u; queueNdx < queuesIter->second.size(); ++queueNdx)
199 		{
200 			Queue& queue = queuesIter->second[queueNdx];
201 
202 			queue.queueHandle = getDeviceQueue(*m_deviceDriver, *m_logicalDevice, queue.queueFamilyIndex, queue.queueIndex);
203 		}
204 	}
205 }
206 
getQueue(const VkQueueFlags queueFlags,const deUint32 queueIndex) const207 const Queue& SparseResourcesBaseInstance::getQueue (const VkQueueFlags queueFlags, const deUint32 queueIndex) const
208 {
209 	return m_queues.find(queueFlags)->second[queueIndex];
210 }
211 
212 } // sparse
213 } // vkt
214