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 "vkMemUtil.hpp"
26 #include "vkRefUtil.hpp"
27 #include "vkTypeUtil.hpp"
28 #include "vkQueryUtil.hpp"
29
30 using namespace vk;
31
32 namespace vkt
33 {
34 namespace sparse
35 {
36 namespace
37 {
38
39 struct QueueFamilyQueuesCount
40 {
QueueFamilyQueuesCountvkt::sparse::__anon56dd63ee0111::QueueFamilyQueuesCount41 QueueFamilyQueuesCount() : queueCount(0u) {};
42
43 deUint32 queueCount;
44 };
45
46 static const deUint32 NO_MATCH_FOUND = ~0u;
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 const InstanceInterface& instance = m_context.getInstanceInterface();
70 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
71
72 deUint32 queueFamilyPropertiesCount = 0u;
73 instance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, DE_NULL);
74
75 if(queueFamilyPropertiesCount == 0u)
76 TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
77
78 std::vector<VkQueueFamilyProperties> queueFamilyProperties;
79 queueFamilyProperties.resize(queueFamilyPropertiesCount);
80
81 instance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, &queueFamilyProperties[0]);
82
83 if (queueFamilyPropertiesCount == 0u)
84 TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
85
86 SelectedQueuesMap selectedQueueFamilies;
87 QueuePrioritiesMap queuePriorities;
88
89 for (deUint32 queueReqNdx = 0; queueReqNdx < queueRequirements.size(); ++queueReqNdx)
90 {
91 const QueueRequirements& queueRequirement = queueRequirements[queueReqNdx];
92
93 deUint32 queueFamilyIndex = 0u;
94 deUint32 queuesFoundCount = 0u;
95
96 do
97 {
98 queueFamilyIndex = findMatchingQueueFamilyIndex(queueFamilyProperties, queueRequirement.queueFlags, queueFamilyIndex);
99
100 if (queueFamilyIndex == NO_MATCH_FOUND)
101 TCU_THROW(NotSupportedError, "No match found for queue requirements");
102
103 const deUint32 queuesPerFamilyCount = deMin32(queueFamilyProperties[queueFamilyIndex].queueCount, queueRequirement.queueCount - queuesFoundCount);
104
105 selectedQueueFamilies[queueFamilyIndex].queueCount = deMax32(queuesPerFamilyCount, selectedQueueFamilies[queueFamilyIndex].queueCount);
106
107 for (deUint32 queueNdx = 0; queueNdx < queuesPerFamilyCount; ++queueNdx)
108 {
109 Queue queue;
110 queue.queueFamilyIndex = queueFamilyIndex;
111 queue.queueIndex = queueNdx;
112
113 m_queues[queueRequirement.queueFlags].push_back(queue);
114 }
115
116 queuesFoundCount += queuesPerFamilyCount;
117
118 ++queueFamilyIndex;
119 } while (queuesFoundCount < queueRequirement.queueCount);
120 }
121
122 std::vector<VkDeviceQueueCreateInfo> queueInfos;
123
124 for (SelectedQueuesMap::iterator queueFamilyIter = selectedQueueFamilies.begin(); queueFamilyIter != selectedQueueFamilies.end(); ++queueFamilyIter)
125 {
126 for (deUint32 queueNdx = 0; queueNdx < queueFamilyIter->second.queueCount; ++queueNdx)
127 queuePriorities[queueFamilyIter->first].push_back(1.0f);
128
129 const VkDeviceQueueCreateInfo queueInfo =
130 {
131 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
132 DE_NULL, // const void* pNext;
133 (VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags;
134 queueFamilyIter->first, // uint32_t queueFamilyIndex;
135 queueFamilyIter->second.queueCount, // uint32_t queueCount;
136 &queuePriorities[queueFamilyIter->first][0], // const float* pQueuePriorities;
137 };
138
139 queueInfos.push_back(queueInfo);
140 }
141
142 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instance, physicalDevice);
143 const VkDeviceCreateInfo deviceInfo =
144 {
145 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
146 DE_NULL, // const void* pNext;
147 (VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags;
148 static_cast<deUint32>(queueInfos.size()), // uint32_t queueCreateInfoCount;
149 &queueInfos[0], // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
150 0u, // uint32_t enabledLayerCount;
151 DE_NULL, // const char* const* ppEnabledLayerNames;
152 0u, // uint32_t enabledExtensionCount;
153 DE_NULL, // const char* const* ppEnabledExtensionNames;
154 &deviceFeatures, // const VkPhysicalDeviceFeatures* pEnabledFeatures;
155 };
156
157 m_logicalDevice = createDevice(instance, physicalDevice, &deviceInfo);
158 m_deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(instance, *m_logicalDevice));
159 m_allocator = de::MovePtr<Allocator>(new SimpleAllocator(*m_deviceDriver, *m_logicalDevice, getPhysicalDeviceMemoryProperties(instance, physicalDevice)));
160
161 for (QueuesMap::iterator queuesIter = m_queues.begin(); queuesIter != m_queues.end(); ++queuesIter)
162 {
163 for (deUint32 queueNdx = 0u; queueNdx < queuesIter->second.size(); ++queueNdx)
164 {
165 Queue& queue = queuesIter->second[queueNdx];
166
167 VkQueue queueHandle = 0;
168 m_deviceDriver->getDeviceQueue(*m_logicalDevice, queue.queueFamilyIndex, queue.queueIndex, &queueHandle);
169
170 queue.queueHandle = queueHandle;
171 }
172 }
173 }
174
getQueue(const VkQueueFlags queueFlags,const deUint32 queueIndex) const175 const Queue& SparseResourcesBaseInstance::getQueue (const VkQueueFlags queueFlags, const deUint32 queueIndex) const
176 {
177 return m_queues.find(queueFlags)->second[queueIndex];
178 }
179
180 } // sparse
181 } // vkt
182