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