| /*------------------------------------------------------------------------ |
| * 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 "vkRefUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| |
| using namespace vk; |
| |
| namespace vkt |
| { |
| namespace sparse |
| { |
| |
| struct QueueFamilyQueuesCount |
| { |
| QueueFamilyQueuesCount() : queueCount(0u) {}; |
| |
| deUint32 queueCount; |
| }; |
| |
| SparseResourcesBaseInstance::SparseResourcesBaseInstance (Context &context) |
| : TestInstance(context) |
| { |
| } |
| |
| void SparseResourcesBaseInstance::createDeviceSupportingQueues(const QueueRequirementsVec& queueRequirements) |
| { |
| const InstanceInterface& instance = m_context.getInstanceInterface(); |
| const DeviceInterface& deviceInterface = m_context.getDeviceInterface(); |
| const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice(); |
| |
| deUint32 queueFamilyPropertiesCount = 0u; |
| instance.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); |
| |
| instance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, &queueFamilyProperties[0]); |
| |
| if (queueFamilyPropertiesCount == 0u) |
| TCU_THROW(ResourceError, "Device reports an empty set of queue family properties"); |
| |
| typedef std::map<deUint32, QueueFamilyQueuesCount> SelectedQueuesMap; |
| typedef std::map<deUint32, std::vector<float> > QueuePrioritiesMap; |
| |
| 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; |
| 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) |
| { |
| VkDeviceQueueCreateInfo queueInfo; |
| deMemset(&queueInfo, 0, sizeof(queueInfo)); |
| |
| for (deUint32 queueNdx = 0; queueNdx < queueFamilyIter->second.queueCount; ++queueNdx) |
| { |
| queuePriorities[queueFamilyIter->first].push_back(1.0f); |
| } |
| |
| queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; |
| queueInfo.pNext = DE_NULL; |
| queueInfo.flags = (VkDeviceQueueCreateFlags)0u; |
| queueInfo.queueFamilyIndex = queueFamilyIter->first; |
| queueInfo.queueCount = queueFamilyIter->second.queueCount; |
| queueInfo.pQueuePriorities = &queuePriorities[queueFamilyIter->first][0]; |
| |
| queueInfos.push_back(queueInfo); |
| } |
| |
| VkDeviceCreateInfo deviceInfo; |
| deMemset(&deviceInfo, 0, sizeof(deviceInfo)); |
| |
| VkPhysicalDeviceFeatures deviceFeatures; |
| instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures); |
| |
| deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; |
| deviceInfo.pNext = DE_NULL; |
| deviceInfo.enabledExtensionCount = 0u; |
| deviceInfo.ppEnabledExtensionNames = DE_NULL; |
| deviceInfo.enabledLayerCount = 0u; |
| deviceInfo.ppEnabledLayerNames = DE_NULL; |
| deviceInfo.pEnabledFeatures = &deviceFeatures; |
| deviceInfo.queueCreateInfoCount = (deUint32)selectedQueueFamilies.size(); |
| deviceInfo.pQueueCreateInfos = &queueInfos[0]; |
| |
| m_logicalDevice = vk::createDevice(instance, physicalDevice, &deviceInfo); |
| |
| 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]; |
| |
| VkQueue queueHandle = 0; |
| deviceInterface.getDeviceQueue(*m_logicalDevice, queue.queueFamilyIndex, queue.queueIndex, &queueHandle); |
| |
| queue.queueHandle = queueHandle; |
| } |
| } |
| } |
| |
| const Queue& SparseResourcesBaseInstance::getQueue (const VkQueueFlags queueFlags, const deUint32 queueIndex) |
| { |
| return m_queues[queueFlags][queueIndex]; |
| } |
| |
| deUint32 SparseResourcesBaseInstance::findMatchingMemoryType (const InstanceInterface& instance, |
| const VkPhysicalDevice physicalDevice, |
| const VkMemoryRequirements& objectMemoryRequirements, |
| const MemoryRequirement& memoryRequirement) const |
| { |
| const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice); |
| |
| for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemoryProperties.memoryTypeCount; ++memoryTypeNdx) |
| { |
| if ((objectMemoryRequirements.memoryTypeBits & (1u << memoryTypeNdx)) != 0 && |
| memoryRequirement.matchesHeap(deviceMemoryProperties.memoryTypes[memoryTypeNdx].propertyFlags)) |
| { |
| return memoryTypeNdx; |
| } |
| } |
| |
| return NO_MATCH_FOUND; |
| } |
| |
| bool SparseResourcesBaseInstance::checkSparseSupportForImageType (const InstanceInterface& instance, |
| const VkPhysicalDevice physicalDevice, |
| const ImageType imageType) const |
| { |
| const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instance, physicalDevice); |
| |
| if (!deviceFeatures.sparseBinding) |
| return false; |
| |
| switch (mapImageType(imageType)) |
| { |
| case VK_IMAGE_TYPE_2D: |
| return deviceFeatures.sparseResidencyImage2D == VK_TRUE; |
| case VK_IMAGE_TYPE_3D: |
| return deviceFeatures.sparseResidencyImage3D == VK_TRUE; |
| default: |
| DE_ASSERT(0); |
| return false; |
| }; |
| } |
| |
| bool SparseResourcesBaseInstance::checkSparseSupportForImageFormat (const InstanceInterface& instance, |
| const VkPhysicalDevice physicalDevice, |
| const VkImageCreateInfo& imageInfo) const |
| { |
| const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec = getPhysicalDeviceSparseImageFormatProperties( |
| instance, physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.samples, imageInfo.usage, imageInfo.tiling); |
| |
| return sparseImageFormatPropVec.size() > 0u; |
| } |
| |
| bool SparseResourcesBaseInstance::checkImageFormatFeatureSupport (const vk::InstanceInterface& instance, |
| const vk::VkPhysicalDevice physicalDevice, |
| const vk::VkFormat format, |
| const vk::VkFormatFeatureFlags featureFlags) const |
| { |
| const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format); |
| |
| return (formatProperties.optimalTilingFeatures & featureFlags) == featureFlags; |
| } |
| |
| deUint32 SparseResourcesBaseInstance::getSparseAspectRequirementsIndex (const std::vector<VkSparseImageMemoryRequirements>& requirements, |
| const VkImageAspectFlags aspectFlags) const |
| { |
| for (deUint32 memoryReqNdx = 0; memoryReqNdx < requirements.size(); ++memoryReqNdx) |
| { |
| if (requirements[memoryReqNdx].formatProperties.aspectMask & aspectFlags) |
| { |
| return memoryReqNdx; |
| } |
| } |
| |
| return NO_MATCH_FOUND; |
| } |
| |
| deUint32 SparseResourcesBaseInstance::findMatchingQueueFamilyIndex (const QueueFamilyPropertiesVec& queueFamilyProperties, |
| const VkQueueFlags queueFlags, |
| const deUint32 startIndex) const |
| { |
| for (deUint32 queueNdx = startIndex; queueNdx < queueFamilyProperties.size(); ++queueNdx) |
| { |
| if ((queueFamilyProperties[queueNdx].queueFlags & queueFlags) == queueFlags) |
| { |
| return queueNdx; |
| } |
| } |
| |
| return NO_MATCH_FOUND; |
| } |
| |
| } // sparse |
| } // vkt |