• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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