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 "vkMemUtil.hpp"
27 #include "vkRefUtil.hpp"
28 #include "vkTypeUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkDeviceUtil.hpp"
31
32 using namespace vk;
33
34 namespace vkt
35 {
36 namespace sparse
37 {
38 namespace
39 {
40
41 struct QueueFamilyQueuesCount
42 {
QueueFamilyQueuesCountvkt::sparse::__anon34630a780111::QueueFamilyQueuesCount43 QueueFamilyQueuesCount() : queueCount(0u) {};
44
45 deUint32 queueCount;
46 };
47
findMatchingQueueFamilyIndex(const std::vector<vk::VkQueueFamilyProperties> & queueFamilyProperties,const VkQueueFlags queueFlags,const deUint32 startIndex)48 deUint32 findMatchingQueueFamilyIndex (const std::vector<vk::VkQueueFamilyProperties>& queueFamilyProperties,
49 const VkQueueFlags queueFlags,
50 const deUint32 startIndex)
51 {
52 for (deUint32 queueNdx = startIndex; queueNdx < queueFamilyProperties.size(); ++queueNdx)
53 {
54 if ((queueFamilyProperties[queueNdx].queueFlags & queueFlags) == queueFlags)
55 return queueNdx;
56 }
57
58 return NO_MATCH_FOUND;
59 }
60
61 } // anonymous
62
createDeviceSupportingQueues(const QueueRequirementsVec & queueRequirements)63 void SparseResourcesBaseInstance::createDeviceSupportingQueues(const QueueRequirementsVec& queueRequirements)
64 {
65 typedef std::map<vk::VkQueueFlags, std::vector<Queue> > QueuesMap;
66 typedef std::map<deUint32, QueueFamilyQueuesCount> SelectedQueuesMap;
67 typedef std::map<deUint32, std::vector<float> > QueuePrioritiesMap;
68
69 std::vector<VkPhysicalDeviceGroupProperties> devGroupProperties;
70 std::vector<const char*> deviceExtensions;
71 VkDeviceGroupDeviceCreateInfo deviceGroupInfo =
72 {
73 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype
74 DE_NULL, //pNext
75 0, //physicalDeviceCount
76 DE_NULL //physicalDevices
77 };
78 m_physicalDevices.push_back(m_context.getPhysicalDevice());
79
80 // If requested, create an intance with device groups
81 if (m_useDeviceGroups)
82 {
83 const std::vector<std::string> requiredExtensions(1, "VK_KHR_device_group_creation");
84 m_deviceGroupInstance = createInstanceWithExtensions(m_context.getPlatformInterface(), m_context.getUsedApiVersion(), requiredExtensions);
85 devGroupProperties = enumeratePhysicalDeviceGroups(m_context.getInstanceInterface(), m_deviceGroupInstance.get());
86 m_numPhysicalDevices = devGroupProperties[m_deviceGroupIdx].physicalDeviceCount;
87
88 m_physicalDevices.clear();
89 for (size_t physDeviceID = 0; physDeviceID < m_numPhysicalDevices; physDeviceID++)
90 {
91 m_physicalDevices.push_back(devGroupProperties[m_deviceGroupIdx].physicalDevices[physDeviceID]);
92 }
93 if (m_numPhysicalDevices < 2)
94 TCU_THROW(NotSupportedError, "Sparse binding device group tests not supported with 1 physical device");
95
96 deviceGroupInfo.physicalDeviceCount = devGroupProperties[m_deviceGroupIdx].physicalDeviceCount;
97 deviceGroupInfo.pPhysicalDevices = devGroupProperties[m_deviceGroupIdx].physicalDevices;
98
99 if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_device_group"))
100 deviceExtensions.push_back("VK_KHR_device_group");
101 }
102
103 const VkInstance& instance(m_useDeviceGroups ? m_deviceGroupInstance.get() : m_context.getInstance());
104 InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
105 const VkPhysicalDevice physicalDevice = getPhysicalDevice();
106 deUint32 queueFamilyPropertiesCount = 0u;
107 instanceDriver.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, DE_NULL);
108
109 if(queueFamilyPropertiesCount == 0u)
110 TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
111
112 std::vector<VkQueueFamilyProperties> queueFamilyProperties;
113 queueFamilyProperties.resize(queueFamilyPropertiesCount);
114
115 instanceDriver.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, &queueFamilyProperties[0]);
116
117 if (queueFamilyPropertiesCount == 0u)
118 TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
119
120 SelectedQueuesMap selectedQueueFamilies;
121 QueuePrioritiesMap queuePriorities;
122
123 for (deUint32 queueReqNdx = 0; queueReqNdx < queueRequirements.size(); ++queueReqNdx)
124 {
125 const QueueRequirements& queueRequirement = queueRequirements[queueReqNdx];
126
127 deUint32 queueFamilyIndex = 0u;
128 deUint32 queuesFoundCount = 0u;
129
130 do
131 {
132 queueFamilyIndex = findMatchingQueueFamilyIndex(queueFamilyProperties, queueRequirement.queueFlags, queueFamilyIndex);
133
134 if (queueFamilyIndex == NO_MATCH_FOUND)
135 TCU_THROW(NotSupportedError, "No match found for queue requirements");
136
137 const deUint32 queuesPerFamilyCount = deMin32(queueFamilyProperties[queueFamilyIndex].queueCount, queueRequirement.queueCount - queuesFoundCount);
138
139 selectedQueueFamilies[queueFamilyIndex].queueCount = deMax32(queuesPerFamilyCount, selectedQueueFamilies[queueFamilyIndex].queueCount);
140
141 for (deUint32 queueNdx = 0; queueNdx < queuesPerFamilyCount; ++queueNdx)
142 {
143 Queue queue = {DE_NULL, 0, 0};
144 queue.queueFamilyIndex = queueFamilyIndex;
145 queue.queueIndex = queueNdx;
146
147 m_queues[queueRequirement.queueFlags].push_back(queue);
148 }
149
150 queuesFoundCount += queuesPerFamilyCount;
151
152 ++queueFamilyIndex;
153 } while (queuesFoundCount < queueRequirement.queueCount);
154 }
155
156 std::vector<VkDeviceQueueCreateInfo> queueInfos;
157
158 for (SelectedQueuesMap::iterator queueFamilyIter = selectedQueueFamilies.begin(); queueFamilyIter != selectedQueueFamilies.end(); ++queueFamilyIter)
159 {
160 for (deUint32 queueNdx = 0; queueNdx < queueFamilyIter->second.queueCount; ++queueNdx)
161 queuePriorities[queueFamilyIter->first].push_back(1.0f);
162
163 const VkDeviceQueueCreateInfo queueInfo =
164 {
165 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
166 DE_NULL, // const void* pNext;
167 (VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags;
168 queueFamilyIter->first, // uint32_t queueFamilyIndex;
169 queueFamilyIter->second.queueCount, // uint32_t queueCount;
170 &queuePriorities[queueFamilyIter->first][0], // const float* pQueuePriorities;
171 };
172
173 queueInfos.push_back(queueInfo);
174 }
175
176 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instanceDriver, physicalDevice);
177 const VkDeviceCreateInfo deviceInfo =
178 {
179 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
180 m_useDeviceGroups ? &deviceGroupInfo : DE_NULL, // const void* pNext;
181 (VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags;
182 static_cast<deUint32>(queueInfos.size()) , // uint32_t queueCreateInfoCount;
183 &queueInfos[0], // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
184 0u, // uint32_t enabledLayerCount;
185 DE_NULL, // const char* const* ppEnabledLayerNames;
186 deUint32(deviceExtensions.size()), // uint32_t enabledExtensionCount;
187 deviceExtensions.size() ? &deviceExtensions[0] : DE_NULL, // const char* const* ppEnabledExtensionNames;
188 &deviceFeatures, // const VkPhysicalDeviceFeatures* pEnabledFeatures;
189 };
190
191 m_logicalDevice = createDevice(m_context.getPlatformInterface(), instance, instanceDriver, physicalDevice, &deviceInfo);
192 m_deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), instance, *m_logicalDevice));
193 m_allocator = de::MovePtr<Allocator>(new SimpleAllocator(*m_deviceDriver, *m_logicalDevice, getPhysicalDeviceMemoryProperties(instanceDriver, physicalDevice)));
194
195 for (QueuesMap::iterator queuesIter = m_queues.begin(); queuesIter != m_queues.end(); ++queuesIter)
196 {
197 for (deUint32 queueNdx = 0u; queueNdx < queuesIter->second.size(); ++queueNdx)
198 {
199 Queue& queue = queuesIter->second[queueNdx];
200
201 queue.queueHandle = getDeviceQueue(*m_deviceDriver, *m_logicalDevice, queue.queueFamilyIndex, queue.queueIndex);
202 }
203 }
204 }
205
getQueue(const VkQueueFlags queueFlags,const deUint32 queueIndex) const206 const Queue& SparseResourcesBaseInstance::getQueue (const VkQueueFlags queueFlags, const deUint32 queueIndex) const
207 {
208 return m_queues.find(queueFlags)->second[queueIndex];
209 }
210
211 } // sparse
212 } // vkt
213