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::__anon57133a6f0111::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,bool requireShaderImageAtomicInt64Features,bool requireMaintenance5)64 void SparseResourcesBaseInstance::createDeviceSupportingQueues(const QueueRequirementsVec& queueRequirements, bool requireShaderImageAtomicInt64Features, bool requireMaintenance5)
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, //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 { "VK_KHR_device_group_creation", "VK_KHR_get_physical_device_properties2" };
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 else
104 {
105 m_context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
106 }
107
108 const VkInstance& instance(m_useDeviceGroups ? m_deviceGroupInstance : m_context.getInstance());
109 InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
110 const VkPhysicalDevice physicalDevice = getPhysicalDevice();
111 deUint32 queueFamilyPropertiesCount = 0u;
112 instanceDriver.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, DE_NULL);
113
114 if(queueFamilyPropertiesCount == 0u)
115 TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
116
117 std::vector<VkQueueFamilyProperties> queueFamilyProperties;
118 queueFamilyProperties.resize(queueFamilyPropertiesCount);
119
120 instanceDriver.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, &queueFamilyProperties[0]);
121
122 if (queueFamilyPropertiesCount == 0u)
123 TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
124
125 SelectedQueuesMap selectedQueueFamilies;
126 QueuePrioritiesMap queuePriorities;
127
128 for (deUint32 queueReqNdx = 0; queueReqNdx < queueRequirements.size(); ++queueReqNdx)
129 {
130 const QueueRequirements& queueRequirement = queueRequirements[queueReqNdx];
131
132 deUint32 queueFamilyIndex = 0u;
133 deUint32 queuesFoundCount = 0u;
134
135 do
136 {
137 queueFamilyIndex = findMatchingQueueFamilyIndex(queueFamilyProperties, queueRequirement.queueFlags, queueFamilyIndex);
138
139 if (queueFamilyIndex == NO_MATCH_FOUND)
140 TCU_THROW(NotSupportedError, "No match found for queue requirements");
141
142 const deUint32 queuesPerFamilyCount = deMin32(queueFamilyProperties[queueFamilyIndex].queueCount, queueRequirement.queueCount - queuesFoundCount);
143
144 selectedQueueFamilies[queueFamilyIndex].queueCount = deMax32(queuesPerFamilyCount, selectedQueueFamilies[queueFamilyIndex].queueCount);
145
146 for (deUint32 queueNdx = 0; queueNdx < queuesPerFamilyCount; ++queueNdx)
147 {
148 Queue queue = {DE_NULL, 0, 0};
149 queue.queueFamilyIndex = queueFamilyIndex;
150 queue.queueIndex = queueNdx;
151
152 m_queues[queueRequirement.queueFlags].push_back(queue);
153 }
154
155 queuesFoundCount += queuesPerFamilyCount;
156
157 ++queueFamilyIndex;
158 } while (queuesFoundCount < queueRequirement.queueCount);
159 }
160
161 std::vector<VkDeviceQueueCreateInfo> queueInfos;
162
163 for (SelectedQueuesMap::iterator queueFamilyIter = selectedQueueFamilies.begin(); queueFamilyIter != selectedQueueFamilies.end(); ++queueFamilyIter)
164 {
165 for (deUint32 queueNdx = 0; queueNdx < queueFamilyIter->second.queueCount; ++queueNdx)
166 queuePriorities[queueFamilyIter->first].push_back(1.0f);
167
168 const VkDeviceQueueCreateInfo queueInfo =
169 {
170 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
171 DE_NULL, // const void* pNext;
172 (VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags;
173 queueFamilyIter->first, // uint32_t queueFamilyIndex;
174 queueFamilyIter->second.queueCount, // uint32_t queueCount;
175 &queuePriorities[queueFamilyIter->first][0], // const float* pQueuePriorities;
176 };
177
178 queueInfos.push_back(queueInfo);
179 }
180
181 vk::VkPhysicalDeviceShaderImageAtomicInt64FeaturesEXT shaderImageAtomicInt64Features = m_context.getShaderImageAtomicInt64FeaturesEXT();
182 vk::VkPhysicalDeviceMaintenance5FeaturesKHR maintenance5Features = m_context.getMaintenance5Features();
183 shaderImageAtomicInt64Features.pNext = nullptr;
184 maintenance5Features.pNext = nullptr;
185
186 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instanceDriver, physicalDevice);
187 vk::VkPhysicalDeviceFeatures2 deviceFeatures2 = getPhysicalDeviceFeatures2(instanceDriver, physicalDevice);
188
189 const bool useFeatures2 = (requireShaderImageAtomicInt64Features || requireMaintenance5);
190
191 void* pNext = nullptr;
192
193 if (useFeatures2)
194 {
195 pNext = &deviceFeatures2;
196
197 if (m_useDeviceGroups)
198 {
199 deviceGroupInfo.pNext = deviceFeatures2.pNext;
200 deviceFeatures2.pNext = &deviceGroupInfo;
201 }
202
203 if (requireShaderImageAtomicInt64Features)
204 {
205 shaderImageAtomicInt64Features.pNext = deviceFeatures2.pNext;
206 deviceFeatures2.pNext = &shaderImageAtomicInt64Features;
207
208 deviceExtensions.push_back("VK_EXT_shader_image_atomic_int64");
209 }
210
211 if (requireMaintenance5)
212 {
213 maintenance5Features.pNext = deviceFeatures2.pNext;
214 deviceFeatures2.pNext = &maintenance5Features;
215
216 deviceExtensions.push_back("VK_KHR_maintenance5");
217 }
218 }
219 else if (m_useDeviceGroups)
220 {
221 pNext = &deviceGroupInfo;
222 }
223 const VkDeviceCreateInfo deviceInfo =
224 {
225 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
226 pNext, // const void* pNext;
227 (VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags;
228 static_cast<deUint32>(queueInfos.size()) , // uint32_t queueCreateInfoCount;
229 &queueInfos[0], // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
230 0u, // uint32_t enabledLayerCount;
231 DE_NULL, // const char* const* ppEnabledLayerNames;
232 deUint32(deviceExtensions.size()), // uint32_t enabledExtensionCount;
233 deviceExtensions.size() ? &deviceExtensions[0] : DE_NULL, // const char* const* ppEnabledExtensionNames;
234 useFeatures2 ? nullptr : &deviceFeatures, // const VkPhysicalDeviceFeatures* pEnabledFeatures;
235 };
236
237 m_logicalDevice = createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(), m_context.getPlatformInterface(), instance, instanceDriver, physicalDevice, &deviceInfo);
238 m_deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), instance, *m_logicalDevice, m_context.getUsedApiVersion()));
239 m_allocator = de::MovePtr<Allocator>(new SimpleAllocator(*m_deviceDriver, *m_logicalDevice, getPhysicalDeviceMemoryProperties(instanceDriver, physicalDevice)));
240
241 for (QueuesMap::iterator queuesIter = m_queues.begin(); queuesIter != m_queues.end(); ++queuesIter)
242 {
243 for (deUint32 queueNdx = 0u; queueNdx < queuesIter->second.size(); ++queueNdx)
244 {
245 Queue& queue = queuesIter->second[queueNdx];
246
247 queue.queueHandle = getDeviceQueue(*m_deviceDriver, *m_logicalDevice, queue.queueFamilyIndex, queue.queueIndex);
248 }
249 }
250 }
251
getQueue(const VkQueueFlags queueFlags,const deUint32 queueIndex) const252 const Queue& SparseResourcesBaseInstance::getQueue (const VkQueueFlags queueFlags, const deUint32 queueIndex) const
253 {
254 return m_queues.find(queueFlags)->second[queueIndex];
255 }
256
257 } // sparse
258 } // vkt
259