| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2016 The Khronos Group Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file vktSparseResourcesBase.cpp |
| * \brief Sparse Resources Base Instance |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktSparseResourcesBase.hpp" |
| #include "vktSparseResourcesTestsUtil.hpp" |
| #include "vktCustomInstancesDevices.hpp" |
| #include "vkMemUtil.hpp" |
| #include "vkRefUtil.hpp" |
| #include "vkTypeUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkDeviceUtil.hpp" |
| |
| using namespace vk; |
| |
| namespace vkt |
| { |
| namespace sparse |
| { |
| namespace |
| { |
| |
| struct QueueFamilyQueuesCount |
| { |
| QueueFamilyQueuesCount() : queueCount(0u) {} |
| |
| deUint32 queueCount; |
| }; |
| |
| deUint32 findMatchingQueueFamilyIndex (const std::vector<VkQueueFamilyProperties>& queueFamilyProperties, |
| const VkQueueFlags queueFlags, |
| const deUint32 startIndex) |
| { |
| for (deUint32 queueNdx = startIndex; queueNdx < queueFamilyProperties.size(); ++queueNdx) |
| { |
| if ((queueFamilyProperties[queueNdx].queueFlags & queueFlags) == queueFlags) |
| return queueNdx; |
| } |
| |
| return NO_MATCH_FOUND; |
| } |
| |
| } // anonymous |
| |
| void SparseResourcesBaseInstance::createDeviceSupportingQueues(const QueueRequirementsVec& queueRequirements) |
| { |
| typedef std::map<VkQueueFlags, std::vector<Queue> > QueuesMap; |
| typedef std::map<deUint32, QueueFamilyQueuesCount> SelectedQueuesMap; |
| typedef std::map<deUint32, std::vector<float> > QueuePrioritiesMap; |
| |
| std::vector<VkPhysicalDeviceGroupProperties> devGroupProperties; |
| std::vector<const char*> deviceExtensions; |
| VkDeviceGroupDeviceCreateInfo deviceGroupInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO_KHR, //stype |
| DE_NULL, //pNext |
| 0, //physicalDeviceCount |
| DE_NULL //physicalDevices |
| }; |
| m_physicalDevices.push_back(m_context.getPhysicalDevice()); |
| |
| // If requested, create an intance with device groups |
| if (m_useDeviceGroups) |
| { |
| const std::vector<std::string> requiredExtensions(1, "VK_KHR_device_group_creation"); |
| m_deviceGroupInstance = createCustomInstanceWithExtensions(m_context, requiredExtensions); |
| devGroupProperties = enumeratePhysicalDeviceGroups(m_context.getInstanceInterface(), m_deviceGroupInstance); |
| m_numPhysicalDevices = devGroupProperties[m_deviceGroupIdx].physicalDeviceCount; |
| |
| m_physicalDevices.clear(); |
| for (size_t physDeviceID = 0; physDeviceID < m_numPhysicalDevices; physDeviceID++) |
| { |
| m_physicalDevices.push_back(devGroupProperties[m_deviceGroupIdx].physicalDevices[physDeviceID]); |
| } |
| if (m_numPhysicalDevices < 2) |
| TCU_THROW(NotSupportedError, "Sparse binding device group tests not supported with 1 physical device"); |
| |
| deviceGroupInfo.physicalDeviceCount = devGroupProperties[m_deviceGroupIdx].physicalDeviceCount; |
| deviceGroupInfo.pPhysicalDevices = devGroupProperties[m_deviceGroupIdx].physicalDevices; |
| |
| if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_device_group")) |
| deviceExtensions.push_back("VK_KHR_device_group"); |
| } |
| |
| const VkInstance& instance(m_useDeviceGroups ? m_deviceGroupInstance : m_context.getInstance()); |
| InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance); |
| const VkPhysicalDevice physicalDevice = getPhysicalDevice(); |
| deUint32 queueFamilyPropertiesCount = 0u; |
| instanceDriver.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, DE_NULL); |
| |
| if(queueFamilyPropertiesCount == 0u) |
| TCU_THROW(ResourceError, "Device reports an empty set of queue family properties"); |
| |
| std::vector<VkQueueFamilyProperties> queueFamilyProperties; |
| queueFamilyProperties.resize(queueFamilyPropertiesCount); |
| |
| instanceDriver.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, &queueFamilyProperties[0]); |
| |
| if (queueFamilyPropertiesCount == 0u) |
| TCU_THROW(ResourceError, "Device reports an empty set of queue family properties"); |
| |
| SelectedQueuesMap selectedQueueFamilies; |
| QueuePrioritiesMap queuePriorities; |
| |
| for (deUint32 queueReqNdx = 0; queueReqNdx < queueRequirements.size(); ++queueReqNdx) |
| { |
| const QueueRequirements& queueRequirement = queueRequirements[queueReqNdx]; |
| |
| deUint32 queueFamilyIndex = 0u; |
| deUint32 queuesFoundCount = 0u; |
| |
| do |
| { |
| queueFamilyIndex = findMatchingQueueFamilyIndex(queueFamilyProperties, queueRequirement.queueFlags, queueFamilyIndex); |
| |
| if (queueFamilyIndex == NO_MATCH_FOUND) |
| TCU_THROW(NotSupportedError, "No match found for queue requirements"); |
| |
| const deUint32 queuesPerFamilyCount = deMin32(queueFamilyProperties[queueFamilyIndex].queueCount, queueRequirement.queueCount - queuesFoundCount); |
| |
| selectedQueueFamilies[queueFamilyIndex].queueCount = deMax32(queuesPerFamilyCount, selectedQueueFamilies[queueFamilyIndex].queueCount); |
| |
| for (deUint32 queueNdx = 0; queueNdx < queuesPerFamilyCount; ++queueNdx) |
| { |
| Queue queue = {DE_NULL, 0, 0}; |
| queue.queueFamilyIndex = queueFamilyIndex; |
| queue.queueIndex = queueNdx; |
| |
| m_queues[queueRequirement.queueFlags].push_back(queue); |
| } |
| |
| queuesFoundCount += queuesPerFamilyCount; |
| |
| ++queueFamilyIndex; |
| } while (queuesFoundCount < queueRequirement.queueCount); |
| } |
| |
| std::vector<VkDeviceQueueCreateInfo> queueInfos; |
| |
| for (SelectedQueuesMap::iterator queueFamilyIter = selectedQueueFamilies.begin(); queueFamilyIter != selectedQueueFamilies.end(); ++queueFamilyIter) |
| { |
| for (deUint32 queueNdx = 0; queueNdx < queueFamilyIter->second.queueCount; ++queueNdx) |
| queuePriorities[queueFamilyIter->first].push_back(1.0f); |
| |
| const VkDeviceQueueCreateInfo queueInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| (VkDeviceQueueCreateFlags)0u, // VkDeviceQueueCreateFlags flags; |
| queueFamilyIter->first, // uint32_t queueFamilyIndex; |
| queueFamilyIter->second.queueCount, // uint32_t queueCount; |
| &queuePriorities[queueFamilyIter->first][0], // const float* pQueuePriorities; |
| }; |
| |
| queueInfos.push_back(queueInfo); |
| } |
| |
| const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instanceDriver, physicalDevice); |
| const VkDeviceCreateInfo deviceInfo = |
| { |
| VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType; |
| m_useDeviceGroups ? &deviceGroupInfo : DE_NULL, // const void* pNext; |
| (VkDeviceCreateFlags)0, // VkDeviceCreateFlags flags; |
| static_cast<deUint32>(queueInfos.size()) , // uint32_t queueCreateInfoCount; |
| &queueInfos[0], // const VkDeviceQueueCreateInfo* pQueueCreateInfos; |
| 0u, // uint32_t enabledLayerCount; |
| DE_NULL, // const char* const* ppEnabledLayerNames; |
| deUint32(deviceExtensions.size()), // uint32_t enabledExtensionCount; |
| deviceExtensions.size() ? &deviceExtensions[0] : DE_NULL, // const char* const* ppEnabledExtensionNames; |
| &deviceFeatures, // const VkPhysicalDeviceFeatures* pEnabledFeatures; |
| }; |
| |
| m_logicalDevice = createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(), m_context.getPlatformInterface(), instance, instanceDriver, physicalDevice, &deviceInfo); |
| m_deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), instance, *m_logicalDevice)); |
| m_allocator = de::MovePtr<Allocator>(new SimpleAllocator(*m_deviceDriver, *m_logicalDevice, getPhysicalDeviceMemoryProperties(instanceDriver, physicalDevice))); |
| |
| for (QueuesMap::iterator queuesIter = m_queues.begin(); queuesIter != m_queues.end(); ++queuesIter) |
| { |
| for (deUint32 queueNdx = 0u; queueNdx < queuesIter->second.size(); ++queueNdx) |
| { |
| Queue& queue = queuesIter->second[queueNdx]; |
| |
| queue.queueHandle = getDeviceQueue(*m_deviceDriver, *m_logicalDevice, queue.queueFamilyIndex, queue.queueIndex); |
| } |
| } |
| } |
| |
| const Queue& SparseResourcesBaseInstance::getQueue (const VkQueueFlags queueFlags, const deUint32 queueIndex) const |
| { |
| return m_queues.find(queueFlags)->second[queueIndex]; |
| } |
| |
| } // sparse |
| } // vkt |