vktSparseResourcesBase.cpp revision 0abb8ae884208e3355eb68bde6cedab1dd7b773c
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 "vkRefUtil.hpp"
27#include "vkQueryUtil.hpp"
28
29using namespace vk;
30
31namespace vkt
32{
33namespace sparse
34{
35
36struct QueueFamilyQueuesCount
37{
38	QueueFamilyQueuesCount() : queueCount(0u), counter(0u) {};
39
40	deUint32		queueCount;
41	deUint32		counter;
42};
43
44SparseResourcesBaseInstance::SparseResourcesBaseInstance (Context &context)
45	: TestInstance(context)
46{
47}
48
49void SparseResourcesBaseInstance::createDeviceSupportingQueues(const QueueRequirementsVec& queueRequirements)
50{
51	const InstanceInterface&	instance		= m_context.getInstanceInterface();
52	const DeviceInterface&		deviceInterface = m_context.getDeviceInterface();
53	const VkPhysicalDevice		physicalDevice	= m_context.getPhysicalDevice();
54
55	deUint32 queueFamilyPropertiesCount = 0u;
56	instance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, DE_NULL);
57
58	if(queueFamilyPropertiesCount == 0u)
59		TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
60
61	std::vector<VkQueueFamilyProperties> queueFamilyProperties;
62	queueFamilyProperties.resize(queueFamilyPropertiesCount);
63
64	instance.getPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueFamilyPropertiesCount, &queueFamilyProperties[0]);
65
66	if (queueFamilyPropertiesCount == 0u)
67		TCU_THROW(ResourceError, "Device reports an empty set of queue family properties");
68
69	typedef std::map<deUint32, QueueFamilyQueuesCount>	SelectedQueuesMap;
70	typedef std::map<deUint32, std::vector<float> >		QueuePrioritiesMap;
71
72	SelectedQueuesMap	selectedQueueFamilies;
73	QueuePrioritiesMap	queuePriorities;
74
75	for (deUint32 queueReqNdx = 0; queueReqNdx < queueRequirements.size(); ++queueReqNdx)
76	{
77		const QueueRequirements queueRequirement = queueRequirements[queueReqNdx];
78		const deUint32			queueFamilyIndex = findMatchingQueueFamilyIndex(queueFamilyProperties, queueRequirement.queueFlags);
79
80		if (queueFamilyIndex == NO_MATCH_FOUND)
81			TCU_THROW(NotSupportedError, "No match found for queue requirements");
82
83		selectedQueueFamilies[queueFamilyIndex].queueCount += queueRequirement.queueCount;
84		for (deUint32 queueNdx = 0; queueNdx < queueRequirement.queueCount; ++queueNdx)
85		{
86			queuePriorities[queueFamilyIndex].push_back(1.0f);
87		}
88	}
89
90	std::vector<VkDeviceQueueCreateInfo> queueInfos;
91
92	for (SelectedQueuesMap::iterator queueFamilyIter = selectedQueueFamilies.begin(); queueFamilyIter != selectedQueueFamilies.end(); ++queueFamilyIter)
93	{
94		VkDeviceQueueCreateInfo queueInfo;
95		deMemset(&queueInfo, 0, sizeof(queueInfo));
96
97		queueInfo.sType				= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
98		queueInfo.pNext				= DE_NULL;
99		queueInfo.flags				= (VkDeviceQueueCreateFlags)0u;
100		queueInfo.queueFamilyIndex	= queueFamilyIter->first;
101		queueInfo.queueCount		= queueFamilyIter->second.queueCount;
102		queueInfo.pQueuePriorities  = &queuePriorities[queueFamilyIter->first][0];
103
104		queueInfos.push_back(queueInfo);
105	}
106
107	VkDeviceCreateInfo deviceInfo;
108	deMemset(&deviceInfo, 0, sizeof(deviceInfo));
109
110	VkPhysicalDeviceFeatures deviceFeatures;
111	instance.getPhysicalDeviceFeatures(physicalDevice, &deviceFeatures);
112
113	deviceInfo.sType					= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
114	deviceInfo.pNext					= DE_NULL;
115	deviceInfo.enabledExtensionCount	= 0u;
116	deviceInfo.ppEnabledExtensionNames	= DE_NULL;
117	deviceInfo.enabledLayerCount		= 0u;
118	deviceInfo.ppEnabledLayerNames		= DE_NULL;
119	deviceInfo.pEnabledFeatures			= &deviceFeatures;
120	deviceInfo.queueCreateInfoCount		= (deUint32)selectedQueueFamilies.size();
121	deviceInfo.pQueueCreateInfos		= &queueInfos[0];
122
123	m_logicalDevice = vk::createDevice(instance, physicalDevice, &deviceInfo);
124
125	for (deUint32 queueReqNdx = 0; queueReqNdx < queueRequirements.size(); ++queueReqNdx)
126	{
127		const QueueRequirements queueRequirement = queueRequirements[queueReqNdx];
128		const deUint32			queueFamilyIndex = findMatchingQueueFamilyIndex(queueFamilyProperties, queueRequirement.queueFlags);
129
130		if (queueFamilyIndex == NO_MATCH_FOUND)
131			TCU_THROW(NotSupportedError, "No match found for queue requirements");
132
133		for (deUint32 queueNdx = 0; queueNdx < queueRequirement.queueCount; ++queueNdx)
134		{
135			VkQueue	queueHandle = 0;
136			deviceInterface.getDeviceQueue(*m_logicalDevice, queueFamilyIndex, selectedQueueFamilies[queueFamilyIndex].counter++, &queueHandle);
137
138			Queue queue;
139			queue.queueHandle		= queueHandle;
140			queue.queueFamilyIndex	= queueFamilyIndex;
141
142			m_queues[queueRequirement.queueFlags].push_back(queue);
143		}
144	}
145}
146
147const Queue& SparseResourcesBaseInstance::getQueue (const VkQueueFlags queueFlags, const deUint32 queueIndex)
148{
149	return m_queues[queueFlags][queueIndex];
150}
151
152deUint32 SparseResourcesBaseInstance::findMatchingMemoryType (const InstanceInterface&		instance,
153															  const VkPhysicalDevice		physicalDevice,
154															  const VkMemoryRequirements&	objectMemoryRequirements,
155															  const MemoryRequirement&		memoryRequirement) const
156{
157	const VkPhysicalDeviceMemoryProperties deviceMemoryProperties = getPhysicalDeviceMemoryProperties(instance, physicalDevice);
158
159	for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemoryProperties.memoryTypeCount; ++memoryTypeNdx)
160	{
161		if ((objectMemoryRequirements.memoryTypeBits & (1u << memoryTypeNdx)) != 0 &&
162			memoryRequirement.matchesHeap(deviceMemoryProperties.memoryTypes[memoryTypeNdx].propertyFlags))
163		{
164			return memoryTypeNdx;
165		}
166	}
167
168	return NO_MATCH_FOUND;
169}
170
171bool SparseResourcesBaseInstance::checkSparseSupportForImageType (const InstanceInterface&	instance,
172																	const VkPhysicalDevice		physicalDevice,
173																	const ImageType				imageType) const
174{
175	const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(instance, physicalDevice);
176
177	if (!deviceFeatures.sparseBinding)
178		return false;
179
180	switch (mapImageType(imageType))
181	{
182		case VK_IMAGE_TYPE_2D:
183			return deviceFeatures.sparseResidencyImage2D == VK_TRUE;
184		case VK_IMAGE_TYPE_3D:
185			return deviceFeatures.sparseResidencyImage3D == VK_TRUE;
186		default:
187			DE_ASSERT(0);
188			return false;
189	};
190}
191
192bool SparseResourcesBaseInstance::checkSparseSupportForImageFormat (const InstanceInterface&	instance,
193																	const VkPhysicalDevice		physicalDevice,
194																	const VkImageCreateInfo&	imageInfo) const
195{
196	const std::vector<VkSparseImageFormatProperties> sparseImageFormatPropVec = getPhysicalDeviceSparseImageFormatProperties(
197		instance, physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.samples, imageInfo.usage, imageInfo.tiling);
198
199	return sparseImageFormatPropVec.size() > 0u;
200}
201
202bool SparseResourcesBaseInstance::checkImageFormatFeatureSupport (const vk::InstanceInterface&		instance,
203																  const vk::VkPhysicalDevice		physicalDevice,
204																  const vk::VkFormat				format,
205																  const vk::VkFormatFeatureFlags	featureFlags) const
206{
207	const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format);
208
209	return (formatProperties.optimalTilingFeatures & featureFlags) == featureFlags;
210}
211
212deUint32 SparseResourcesBaseInstance::getSparseAspectRequirementsIndex (const std::vector<VkSparseImageMemoryRequirements>&	requirements,
213																		const VkImageAspectFlags							aspectFlags) const
214{
215	for (deUint32 memoryReqNdx = 0; memoryReqNdx < requirements.size(); ++memoryReqNdx)
216	{
217		if (requirements[memoryReqNdx].formatProperties.aspectMask & aspectFlags)
218		{
219			return memoryReqNdx;
220		}
221	}
222
223	return NO_MATCH_FOUND;
224}
225
226deUint32 SparseResourcesBaseInstance::findMatchingQueueFamilyIndex (const QueueFamilyPropertiesVec& queueFamilyProperties,
227																	const VkQueueFlags				queueFlags)	const
228{
229	for (deUint32 queueNdx = 0; queueNdx < queueFamilyProperties.size(); ++queueNdx)
230	{
231		if ((queueFamilyProperties[queueNdx].queueFlags & queueFlags) == queueFlags)
232		{
233			return queueNdx;
234		}
235	}
236
237	return NO_MATCH_FOUND;
238}
239
240} // sparse
241} // vkt
242