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 { 43 QueueFamilyQueuesCount() : queueCount(0u) {}; 44 45 deUint32 queueCount; 46 }; 47 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 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 206 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