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 "vkRefUtil.hpp"
26 #include "vkQueryUtil.hpp"
27 
28 using namespace vk;
29 
30 namespace vkt
31 {
32 namespace sparse
33 {
34 
35 struct QueueFamilyQueuesCount
36 {
QueueFamilyQueuesCountvkt::sparse::QueueFamilyQueuesCount37 	QueueFamilyQueuesCount() : queueCount(0u), counter(0u) {};
38 
39 	deUint32		queueCount;
40 	deUint32		counter;
41 };
42 
SparseResourcesBaseInstance(Context & context)43 SparseResourcesBaseInstance::SparseResourcesBaseInstance (Context &context)
44 	: TestInstance(context)
45 {
46 }
47 
createDeviceSupportingQueues(const QueueRequirementsVec & queueRequirements)48 bool SparseResourcesBaseInstance::createDeviceSupportingQueues (const QueueRequirementsVec&	queueRequirements)
49 {
50 	const InstanceInterface&	instance		= m_context.getInstanceInterface();
51 	const DeviceInterface&		deviceInterface = m_context.getDeviceInterface();
52 	const VkPhysicalDevice		physicalDevice	= m_context.getPhysicalDevice();
53 
54 	deUint32 queueFamilyPropertiesCount = 0u;
55 	instance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, DE_NULL);
56 
57 	if (queueFamilyPropertiesCount == 0u)
58 	{
59 		return false;
60 	}
61 
62 	std::vector<VkQueueFamilyProperties> queueFamilyProperties;
63 	queueFamilyProperties.resize(queueFamilyPropertiesCount);
64 
65 	instance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, &queueFamilyProperties[0]);
66 
67 	typedef std::map<deUint32, QueueFamilyQueuesCount>	SelectedQueuesMap;
68 	typedef std::map<deUint32, std::vector<float> >		QueuePrioritiesMap;
69 
70 	SelectedQueuesMap	selectedQueueFamilies;
71 	QueuePrioritiesMap	queuePriorities;
72 
73 	for (deUint32 queueReqNdx = 0; queueReqNdx < queueRequirements.size(); ++queueReqNdx)
74 	{
75 		const QueueRequirements queueRequirement = queueRequirements[queueReqNdx];
76 		const deUint32			queueFamilyIndex = findMatchingQueueFamilyIndex(queueFamilyProperties, queueRequirement.queueFlags);
77 
78 		if (queueFamilyIndex == NO_MATCH_FOUND)
79 		{
80 			return false;
81 		}
82 
83 		selectedQueueFamilies[queueFamilyIndex].queueCount += queueRequirement.queueCount;
84 		for (deUint32 queueNdx = 0; queueNdx < queueRequirement.queueCount; ++queueNdx)
85 		{
86 			queuePriorities[queueFamilyIndex].push_back(1.0f);
87 		}
88 	}
89 
90 	std::vector<VkDeviceQueueCreateInfo> queueInfos;
91 
92 	for (SelectedQueuesMap::iterator queueFamilyIter = selectedQueueFamilies.begin(); queueFamilyIter != selectedQueueFamilies.end(); ++queueFamilyIter)
93 	{
94 		VkDeviceQueueCreateInfo queueInfo;
95 		deMemset(&queueInfo, 0, sizeof(queueInfo));
96 
97 		queueInfo.sType				= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
98 		queueInfo.pNext				= DE_NULL;
99 		queueInfo.flags				= (VkDeviceQueueCreateFlags)0u;
100 		queueInfo.queueFamilyIndex	= queueFamilyIter->first;
101 		queueInfo.queueCount		= queueFamilyIter->second.queueCount;
102 		queueInfo.pQueuePriorities  = &queuePriorities[queueFamilyIter->first][0];
103 
104 		queueInfos.push_back(queueInfo);
105 	}
106 
107 	VkDeviceCreateInfo deviceInfo;
108 	deMemset(&deviceInfo, 0, sizeof(deviceInfo));
109 
110 	VkPhysicalDeviceFeatures deviceFeatures;
111 	instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
112 
113 	deviceInfo.sType					= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
114 	deviceInfo.pNext					= DE_NULL;
115 	deviceInfo.enabledExtensionCount	= 0u;
116 	deviceInfo.ppEnabledExtensionNames	= DE_NULL;
117 	deviceInfo.enabledLayerCount		= 0u;
118 	deviceInfo.ppEnabledLayerNames		= DE_NULL;
119 	deviceInfo.pEnabledFeatures			= &deviceFeatures;
120 	deviceInfo.queueCreateInfoCount		= (deUint32)selectedQueueFamilies.size();
121 	deviceInfo.pQueueCreateInfos		= &queueInfos[0];
122 
123 	m_logicalDevice = vk::createDevice(instance, physicalDevice, &deviceInfo);
124 
125 	for (deUint32 queueReqNdx = 0; queueReqNdx < queueRequirements.size(); ++queueReqNdx)
126 	{
127 		const QueueRequirements queueRequirement = queueRequirements[queueReqNdx];
128 		const deUint32			queueFamilyIndex = findMatchingQueueFamilyIndex(queueFamilyProperties, queueRequirement.queueFlags);
129 
130 		if (queueFamilyIndex == NO_MATCH_FOUND)
131 		{
132 			return false;
133 		}
134 
135 		for (deUint32 queueNdx = 0; queueNdx < queueRequirement.queueCount; ++queueNdx)
136 		{
137 			VkQueue	queueHandle = 0;
138 			deviceInterface.getDeviceQueue(*m_logicalDevice, queueFamilyIndex, selectedQueueFamilies[queueFamilyIndex].counter++, &queueHandle);
139 
140 			Queue queue;
141 			queue.queueHandle		= queueHandle;
142 			queue.queueFamilyIndex	= queueFamilyIndex;
143 
144 			m_queues[queueRequirement.queueFlags].push_back(queue);
145 		}
146 	}
147 
148 	return true;
149 }
150 
getQueue(const VkQueueFlags queueFlags,const deUint32 queueIndex)151 const Queue& SparseResourcesBaseInstance::getQueue (const VkQueueFlags queueFlags, const deUint32 queueIndex)
152 {
153 	return m_queues[queueFlags][queueIndex];
154 }
155 
findMatchingMemoryType(const VkPhysicalDeviceMemoryProperties & deviceMemoryProperties,const VkMemoryRequirements & objectMemoryRequirements,const MemoryRequirement & memoryRequirement) const156 deUint32 SparseResourcesBaseInstance::findMatchingMemoryType (const VkPhysicalDeviceMemoryProperties&	deviceMemoryProperties,
157 															  const VkMemoryRequirements&				objectMemoryRequirements,
158 															  const MemoryRequirement&					memoryRequirement) const
159 {
160 	for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemoryProperties.memoryTypeCount; ++memoryTypeNdx)
161 	{
162 		if ((objectMemoryRequirements.memoryTypeBits & (1u << memoryTypeNdx)) != 0 &&
163 			memoryRequirement.matchesHeap(deviceMemoryProperties.memoryTypes[memoryTypeNdx].propertyFlags))
164 		{
165 			return memoryTypeNdx;
166 		}
167 	}
168 
169 	return NO_MATCH_FOUND;
170 }
171 
findMatchingQueueFamilyIndex(const QueueFamilyPropertiesVec & queueFamilyProperties,const VkQueueFlags queueFlags) const172 deUint32 SparseResourcesBaseInstance::findMatchingQueueFamilyIndex (const QueueFamilyPropertiesVec& queueFamilyProperties,
173 																	const VkQueueFlags				queueFlags)	const
174 {
175 	for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
176 	{
177 		if ((queueFamilyProperties[queueNdx].queueFlags & queueFlags) == queueFlags)
178 		{
179 			return queueNdx;
180 		}
181 	}
182 
183 	return NO_MATCH_FOUND;
184 }
185 
186 } // sparse
187 } // vkt
188