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::__anon3d60ccc50111::QueueFamilyQueuesCount44 QueueFamilyQueuesCount() : queueCount(0u)
45 {
46 }
47
48 uint32_t queueCount;
49 };
50
findMatchingQueueFamilyIndex(const std::vector<VkQueueFamilyProperties> & queueFamilyProperties,const VkQueueFlags queueFlags,const uint32_t startIndex)51 uint32_t findMatchingQueueFamilyIndex(const std::vector<VkQueueFamilyProperties> &queueFamilyProperties,
52 const VkQueueFlags queueFlags, const uint32_t startIndex)
53 {
54 for (uint32_t queueNdx = startIndex; queueNdx < queueFamilyProperties.size(); ++queueNdx)
55 {
56 if ((queueFamilyProperties[queueNdx].queueFlags & queueFlags) == queueFlags)
57 return queueNdx;
58 }
59
60 return NO_MATCH_FOUND;
61 }
62
findSpecificQueueFamilyIndex(const std::vector<VkQueueFamilyProperties> & queueFamilyProperties,const VkQueueFlags requestedFlags,const uint32_t startIndex)63 uint32_t findSpecificQueueFamilyIndex(const std::vector<VkQueueFamilyProperties> &queueFamilyProperties,
64 const VkQueueFlags requestedFlags, const uint32_t startIndex)
65 {
66 for (uint32_t queueNdx = startIndex; queueNdx < queueFamilyProperties.size(); ++queueNdx)
67 {
68 const VkQueueFlags queueFlags = queueFamilyProperties[queueNdx].queueFlags;
69 const VkQueueFlags coreFlags = (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT);
70 const VkQueueFlags coreQueueFlags = queueFlags & coreFlags;
71 const VkQueueFlags coreRequestedFlags = requestedFlags & coreFlags;
72
73 bool isUniversal = (coreQueueFlags & VK_QUEUE_GRAPHICS_BIT) != 0;
74 bool needUniversal = (coreRequestedFlags & VK_QUEUE_GRAPHICS_BIT) != 0;
75
76 if (isUniversal && needUniversal)
77 return queueNdx;
78
79 if ((coreQueueFlags == coreRequestedFlags) && ((queueFlags & requestedFlags) == requestedFlags))
80 return queueNdx;
81 }
82
83 return NO_MATCH_FOUND;
84 }
85
86 } // namespace
87
createDeviceSupportingQueues(const QueueRequirementsVec & queueRequirements,bool requireShaderImageAtomicInt64Features,bool requireMaintenance5)88 void SparseResourcesBaseInstance::createDeviceSupportingQueues(const QueueRequirementsVec &queueRequirements,
89 bool requireShaderImageAtomicInt64Features,
90 bool requireMaintenance5)
91 {
92 typedef std::map<VkQueueFlags, std::vector<Queue>> QueuesMap;
93 typedef std::map<uint32_t, QueueFamilyQueuesCount> SelectedQueuesMap;
94 typedef std::map<uint32_t, std::vector<float>> QueuePrioritiesMap;
95
96 std::vector<VkPhysicalDeviceGroupProperties> devGroupProperties;
97 std::vector<const char *> deviceExtensions;
98 VkDeviceGroupDeviceCreateInfo deviceGroupInfo = {
99 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO, //stype
100 nullptr, //pNext
101 0, //physicalDeviceCount
102 nullptr //physicalDevices
103 };
104 m_physicalDevices.push_back(m_context.getPhysicalDevice());
105
106 // If requested, create an intance with device groups
107 if (m_useDeviceGroups)
108 {
109 const std::vector<std::string> requiredExtensions{"VK_KHR_device_group_creation",
110 "VK_KHR_get_physical_device_properties2"};
111 m_deviceGroupInstance = createCustomInstanceWithExtensions(m_context, requiredExtensions);
112 devGroupProperties = enumeratePhysicalDeviceGroups(m_context.getInstanceInterface(), m_deviceGroupInstance);
113 m_numPhysicalDevices = devGroupProperties[m_deviceGroupIdx].physicalDeviceCount;
114
115 m_physicalDevices.clear();
116 for (size_t physDeviceID = 0; physDeviceID < m_numPhysicalDevices; physDeviceID++)
117 {
118 m_physicalDevices.push_back(devGroupProperties[m_deviceGroupIdx].physicalDevices[physDeviceID]);
119 }
120 if (m_numPhysicalDevices < 2)
121 TCU_THROW(NotSupportedError, "Sparse binding device group tests not supported with 1 physical device");
122
123 deviceGroupInfo.physicalDeviceCount = devGroupProperties[m_deviceGroupIdx].physicalDeviceCount;
124 deviceGroupInfo.pPhysicalDevices = devGroupProperties[m_deviceGroupIdx].physicalDevices;
125
126 if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_device_group"))
127 deviceExtensions.push_back("VK_KHR_device_group");
128 }
129 else
130 {
131 m_context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
132 }
133
134 const VkInstance &instance(m_useDeviceGroups ? m_deviceGroupInstance : m_context.getInstance());
135 InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
136 const VkPhysicalDevice physicalDevice = getPhysicalDevice();
137 uint32_t queueFamilyPropertiesCount = 0u;
138 instanceDriver.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, nullptr);
139
140 if (queueFamilyPropertiesCount == 0u)
141 TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
142
143 std::vector<VkQueueFamilyProperties> queueFamilyProperties;
144 queueFamilyProperties.resize(queueFamilyPropertiesCount);
145
146 instanceDriver.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount,
147 &queueFamilyProperties[0]);
148
149 if (queueFamilyPropertiesCount == 0u)
150 TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
151
152 SelectedQueuesMap selectedQueueFamilies;
153 QueuePrioritiesMap queuePriorities;
154
155 for (uint32_t queueReqNdx = 0; queueReqNdx < queueRequirements.size(); ++queueReqNdx)
156 {
157 const QueueRequirements &queueRequirement = queueRequirements[queueReqNdx];
158
159 uint32_t queueFamilyIndex = 0u;
160 uint32_t queuesFoundCount = 0u;
161
162 do
163 {
164 queueFamilyIndex =
165 m_forceSpecificQueue ?
166 findSpecificQueueFamilyIndex(queueFamilyProperties, queueRequirement.queueFlags, queueFamilyIndex) :
167 findMatchingQueueFamilyIndex(queueFamilyProperties, queueRequirement.queueFlags, queueFamilyIndex);
168
169 if (queueFamilyIndex == NO_MATCH_FOUND)
170 TCU_THROW(NotSupportedError, "No match found for queue requirements");
171
172 const uint32_t queuesPerFamilyCount = deMin32(queueFamilyProperties[queueFamilyIndex].queueCount,
173 queueRequirement.queueCount - queuesFoundCount);
174
175 selectedQueueFamilies[queueFamilyIndex].queueCount =
176 deMax32(queuesPerFamilyCount, selectedQueueFamilies[queueFamilyIndex].queueCount);
177
178 for (uint32_t queueNdx = 0; queueNdx < queuesPerFamilyCount; ++queueNdx)
179 {
180 Queue queue = {nullptr, 0, 0};
181 queue.queueFamilyIndex = queueFamilyIndex;
182 queue.queueIndex = queueNdx;
183
184 m_queues[queueRequirement.queueFlags].push_back(queue);
185 }
186
187 queuesFoundCount += queuesPerFamilyCount;
188
189 ++queueFamilyIndex;
190 } while (queuesFoundCount < queueRequirement.queueCount);
191 }
192
193 std::vector<VkDeviceQueueCreateInfo> queueInfos;
194
195 for (SelectedQueuesMap::iterator queueFamilyIter = selectedQueueFamilies.begin();
196 queueFamilyIter != selectedQueueFamilies.end(); ++queueFamilyIter)
197 {
198 for (uint32_t queueNdx = 0; queueNdx < queueFamilyIter->second.queueCount; ++queueNdx)
199 queuePriorities[queueFamilyIter->first].push_back(1.0f);
200
201 const VkDeviceQueueCreateInfo queueInfo = {
202 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
203 nullptr, // const void* pNext;
204 (VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags;
205 queueFamilyIter->first, // uint32_t queueFamilyIndex;
206 queueFamilyIter->second.queueCount, // uint32_t queueCount;
207 &queuePriorities[queueFamilyIter->first][0], // const float* pQueuePriorities;
208 };
209
210 queueInfos.push_back(queueInfo);
211 }
212
213 vk::VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT shaderImageAtomicInt64Features =
214 m_context.getShaderImageAtomicInt64FeaturesEXT();
215 vk::VkPhysicalDeviceMaintenance5FeaturesKHR maintenance5Features = m_context.getMaintenance5Features();
216 shaderImageAtomicInt64Features.pNext = nullptr;
217 maintenance5Features.pNext = nullptr;
218
219 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instanceDriver, physicalDevice);
220 vk::VkPhysicalDeviceFeatures2 deviceFeatures2 = getPhysicalDeviceFeatures2(instanceDriver, physicalDevice);
221
222 const bool useFeatures2 = (requireShaderImageAtomicInt64Features || requireMaintenance5);
223
224 void *pNext = nullptr;
225
226 if (useFeatures2)
227 {
228 pNext = &deviceFeatures2;
229
230 if (m_useDeviceGroups)
231 {
232 deviceGroupInfo.pNext = deviceFeatures2.pNext;
233 deviceFeatures2.pNext = &deviceGroupInfo;
234 }
235
236 if (requireShaderImageAtomicInt64Features)
237 {
238 shaderImageAtomicInt64Features.pNext = deviceFeatures2.pNext;
239 deviceFeatures2.pNext = &shaderImageAtomicInt64Features;
240
241 deviceExtensions.push_back("VK_EXT_shader_image_atomic_int64");
242 }
243
244 if (requireMaintenance5)
245 {
246 maintenance5Features.pNext = deviceFeatures2.pNext;
247 deviceFeatures2.pNext = &maintenance5Features;
248
249 deviceExtensions.push_back("VK_KHR_maintenance5");
250 }
251 }
252 else if (m_useDeviceGroups)
253 {
254 pNext = &deviceGroupInfo;
255 }
256 const VkDeviceCreateInfo deviceInfo = {
257 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
258 pNext, // const void* pNext;
259 (VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags;
260 static_cast<uint32_t>(queueInfos.size()), // uint32_t queueCreateInfoCount;
261 &queueInfos[0], // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
262 0u, // uint32_t enabledLayerCount;
263 nullptr, // const char* const* ppEnabledLayerNames;
264 uint32_t(deviceExtensions.size()), // uint32_t enabledExtensionCount;
265 deviceExtensions.size() ? &deviceExtensions[0] : nullptr, // const char* const* ppEnabledExtensionNames;
266 useFeatures2 ? nullptr : &deviceFeatures, // const VkPhysicalDeviceFeatures* pEnabledFeatures;
267 };
268
269 m_logicalDevice =
270 createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(),
271 m_context.getPlatformInterface(), instance, instanceDriver, physicalDevice, &deviceInfo);
272 m_deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), instance,
273 *m_logicalDevice, m_context.getUsedApiVersion(),
274 m_context.getTestContext().getCommandLine()));
275 m_allocator = de::MovePtr<Allocator>(new SimpleAllocator(
276 *m_deviceDriver, *m_logicalDevice, getPhysicalDeviceMemoryProperties(instanceDriver, physicalDevice)));
277
278 for (QueuesMap::iterator queuesIter = m_queues.begin(); queuesIter != m_queues.end(); ++queuesIter)
279 {
280 for (uint32_t queueNdx = 0u; queueNdx < queuesIter->second.size(); ++queueNdx)
281 {
282 Queue &queue = queuesIter->second[queueNdx];
283
284 queue.queueHandle =
285 getDeviceQueue(*m_deviceDriver, *m_logicalDevice, queue.queueFamilyIndex, queue.queueIndex);
286 }
287 }
288 }
289
getQueue(const VkQueueFlags queueFlags,const uint32_t queueIndex) const290 const Queue &SparseResourcesBaseInstance::getQueue(const VkQueueFlags queueFlags, const uint32_t queueIndex) const
291 {
292 return m_queues.find(queueFlags)->second[queueIndex];
293 }
294
295 } // namespace sparse
296 } // namespace vkt
297