1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 Khronos Group
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
21 * \brief API Maintenance3 Check test - checks structs and function from VK_KHR_maintenance3
22 *//*--------------------------------------------------------------------*/
23 
24 #include "tcuTestLog.hpp"
25 
26 #include "vkQueryUtil.hpp"
27 
28 #include "vktApiMaintenance3Check.hpp"
29 #include "vktTestCase.hpp"
30 
31 #define VK_DESCRIPTOR_TYPE_LAST (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + 1)
32 
33 using namespace vk;
34 
35 namespace vkt
36 {
37 
38 namespace api
39 {
40 
41 namespace
42 {
43 using ::std::string;
44 using ::std::vector;
45 
46 typedef vk::VkPhysicalDeviceProperties DevProp1;
47 typedef vk::VkPhysicalDeviceProperties2  DevProp2;
48 typedef vk::VkPhysicalDeviceMaintenance3Properties MainDevProp3;
49 
50 
checkSupport(const Context & m_context)51 void										checkSupport							(const Context& m_context)
52 {
53 	const vector<string>					extensions								= m_context.getDeviceExtensions();
54 
55 	if (!isDeviceExtensionSupported(m_context.getUsedApiVersion(), m_context.getDeviceExtensions(), "VK_KHR_maintenance3"))
56 		TCU_THROW(NotSupportedError, "VK_KHR_maintenance3 extension is not supported");
57 }
58 
59 class Maintenance3StructTestInstance : public TestInstance
60 {
61 public:
Maintenance3StructTestInstance(Context & ctx)62 											Maintenance3StructTestInstance			(Context& ctx)
63 												: TestInstance						(ctx)
64 	{}
iterate(void)65 	virtual tcu::TestStatus					iterate									(void)
66 	{
67 		checkSupport(m_context);
68 		tcu::TestLog&						log										= m_context.getTestContext().getLog();
69 
70 		// these variables are equal to minimal values for maxMemoryAllocationSize and maxPerSetDescriptors
71 		const deUint32						maxMemoryAllocationSize					= 1073741824u;
72 		const deUint32						maxDescriptorsInSet						= 1024u;
73 
74 		// set values to be a bit smaller than required minimum values
75 		MainDevProp3 mainProp3 =
76 		{
77 			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES,				//VkStructureType						sType;
78 			DE_NULL,																//void*									pNext;
79 			maxDescriptorsInSet - 1u,												//deUint32								maxPerSetDescriptors;
80 			maxMemoryAllocationSize - 1u											//VkDeviceSize							maxMemoryAllocationSize;
81 		};
82 
83 		DevProp2 prop2;
84 		deMemset(&prop2, 0, sizeof(prop2)); // zero the structure
85 		prop2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
86 		prop2.pNext = &mainProp3;
87 
88 		m_context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &prop2);
89 
90 		if (mainProp3.maxMemoryAllocationSize < maxMemoryAllocationSize)
91 			return tcu::TestStatus::fail("Fail");
92 
93 		if (mainProp3.maxPerSetDescriptors < maxDescriptorsInSet)
94 			return tcu::TestStatus::fail("Fail");
95 
96 		log << tcu::TestLog::Message << "maxMemoryAllocationSize: "	<< mainProp3.maxMemoryAllocationSize	<< tcu::TestLog::EndMessage;
97 		log << tcu::TestLog::Message << "maxPerSetDescriptors: "	<< mainProp3.maxPerSetDescriptors		<< tcu::TestLog::EndMessage;
98 		return tcu::TestStatus::pass("Pass");
99 	}
100 };
101 
102 class Maintenance3StructTestCase : public TestCase
103 {
104 public:
Maintenance3StructTestCase(tcu::TestContext & testCtx)105 											Maintenance3StructTestCase				(tcu::TestContext&	testCtx)
106 												: TestCase(testCtx, "maintenance3_properties", "tests VkPhysicalDeviceMaintenance3Properties struct")
107 	{}
108 
~Maintenance3StructTestCase(void)109 	virtual									~Maintenance3StructTestCase				(void)
110 	{}
createInstance(Context & ctx) const111 	virtual TestInstance*					createInstance							(Context&	ctx) const
112 	{
113 		return new Maintenance3StructTestInstance(ctx);
114 	}
115 
116 private:
117 };
118 
119 class Maintenance3DescriptorTestInstance : public TestInstance
120 {
121 public:
Maintenance3DescriptorTestInstance(Context & ctx)122 											Maintenance3DescriptorTestInstance		(Context&	ctx)
123 												: TestInstance(ctx)
124 	{}
iterate(void)125 	virtual tcu::TestStatus					iterate									(void)
126 	{
127 		checkSupport(m_context);
128 
129 		// these variables are equal to minimal values for maxMemoryAllocationSize and maxPerSetDescriptors
130 		const deUint32						maxMemoryAllocationSize					= 1073741824u;
131 		const deUint32						maxDescriptorsInSet						= 1024u;
132 
133 		MainDevProp3						mainProp3								=
134 		{
135 			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES,				//VkStructureType						sType;
136 			DE_NULL,																//void*									pNext;
137 			maxDescriptorsInSet,													//deUint32								maxPerSetDescriptors;
138 			maxMemoryAllocationSize													//VkDeviceSize							maxMemoryAllocationSize;
139 		};
140 
141 		DevProp2							prop2									=
142 		{
143 			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,							//VkStructureType						sType;
144 			&mainProp3,																//void*									pNext;
145 			VkPhysicalDeviceProperties()											//VkPhysicalDeviceProperties			properties;
146 		};
147 
148 		DevProp1							prop1;
149 
150 		m_context.getInstanceInterface().getPhysicalDeviceProperties(m_context.getPhysicalDevice(), &prop1);
151 		m_context.getInstanceInterface().getPhysicalDeviceProperties2(m_context.getPhysicalDevice(), &prop2);
152 
153 		// setup for descriptors sets
154 		VkDescriptorSetLayoutBinding		descriptorSetLayoutBinding[VK_DESCRIPTOR_TYPE_LAST];
155 
156 		for (deUint32 ndx = 0u; ndx < VK_DESCRIPTOR_TYPE_LAST; ++ndx)
157 		{
158 			descriptorSetLayoutBinding[ndx].binding									= ndx;
159 			descriptorSetLayoutBinding[ndx].descriptorType							= static_cast<VkDescriptorType>(ndx);
160 			descriptorSetLayoutBinding[ndx].descriptorCount							= mainProp3.maxPerSetDescriptors;
161 			descriptorSetLayoutBinding[ndx].stageFlags								= VK_SHADER_STAGE_ALL;
162 			descriptorSetLayoutBinding[ndx].pImmutableSamplers						= DE_NULL;
163 		}
164 
165 		// VkDescriptorSetLayoutCreateInfo setup
166 		vk::VkDescriptorSetLayoutCreateInfo	pCreateInfo								=
167 		{
168 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,					//VkStructureType						sType;
169 			DE_NULL,																//const void*							pNext;
170 			0u,																		//VkDescriptorSetLayoutCreateFlags		flags;
171 			1u,																		//deUint32								bindingCount;
172 			DE_NULL																	//const VkDescriptorSetLayoutBinding*	pBindings;
173 		};
174 
175 		// VkDescriptorSetLayoutSupport setup
176 		vk::VkDescriptorSetLayoutSupport	pSupport								=
177 		{
178 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_SUPPORT,						//VkStructureType						sType;
179 			DE_NULL,																//void*									pNext;
180 			VK_FALSE																//VkBool32								supported;
181 		};
182 
183 		// check for single descriptors
184 		for (deUint32 ndx = 0u; ndx < VK_DESCRIPTOR_TYPE_LAST; ++ndx)
185 		{
186 			pCreateInfo.pBindings = &descriptorSetLayoutBinding[ndx];
187 			m_context.getDeviceInterface().getDescriptorSetLayoutSupport(m_context.getDevice(), &pCreateInfo, &pSupport);
188 
189 			if(extraLimitCheck(descriptorSetLayoutBinding, ndx, pCreateInfo.bindingCount, prop1))
190 			{
191 				if (pSupport.supported == VK_FALSE)
192 					return tcu::TestStatus::fail("fail");
193 			}
194 		}
195 
196 		// check for accumulated descriptors (all eleven types)
197 
198 		pCreateInfo.pBindings = &descriptorSetLayoutBinding[0u];
199 		pCreateInfo.bindingCount = static_cast<deUint32>(VK_DESCRIPTOR_TYPE_LAST);
200 
201 		deUint32 fraction = mainProp3.maxPerSetDescriptors / static_cast<deUint32>(VK_DESCRIPTOR_TYPE_LAST);
202 		deUint32 rest = mainProp3.maxPerSetDescriptors % static_cast<deUint32>(VK_DESCRIPTOR_TYPE_LAST);
203 
204 		for (deUint32 ndx = 0u; ndx < VK_DESCRIPTOR_TYPE_LAST; ++ndx)
205 			descriptorSetLayoutBinding[ndx].descriptorCount = fraction;
206 		descriptorSetLayoutBinding[0u].descriptorCount += rest;
207 
208 		m_context.getDeviceInterface().getDescriptorSetLayoutSupport(m_context.getDevice(), &pCreateInfo, &pSupport);
209 
210 		if (extraLimitCheck(descriptorSetLayoutBinding, 0u, pCreateInfo.bindingCount, prop1))
211 		{
212 			if (pSupport.supported == VK_FALSE)
213 				return tcu::TestStatus::fail("fail");
214 		}
215 
216 		return tcu::TestStatus::pass("Pass");
217 	}
218 
219 private:
extraLimitCheck(const VkDescriptorSetLayoutBinding * descriptorSetLayoutBinding,const deUint32 & curNdx,const deUint32 & size,const DevProp1 & prop1)220 	bool									extraLimitCheck							(const VkDescriptorSetLayoutBinding* descriptorSetLayoutBinding, const deUint32& curNdx, const deUint32& size, const DevProp1& prop1)
221 	{
222 		deUint32							maxPerStageDescriptorSamplers			= 0u;
223 		deUint32							maxPerStageDescriptorUniformBuffers		= 0u;
224 		deUint32							maxPerStageDescriptorStorageBuffers		= 0u;
225 		deUint32							maxPerStageDescriptorSampledImages		= 0u;
226 		deUint32							maxPerStageDescriptorStorageImages		= 0u;
227 		deUint32							maxPerStageDescriptorInputAttachments	= 0u;
228 
229 		for(deUint32 ndx = curNdx; ndx < curNdx + size; ++ndx)
230 		{
231 			if ((descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
232 				(descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER))
233 				maxPerStageDescriptorSamplers += descriptorSetLayoutBinding->descriptorCount;
234 
235 			if ((descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
236 					(descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC))
237 				maxPerStageDescriptorUniformBuffers += descriptorSetLayoutBinding->descriptorCount;
238 
239 			if ((descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
240 					(descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC))
241 				maxPerStageDescriptorStorageBuffers += descriptorSetLayoutBinding->descriptorCount;
242 
243 			if ((descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)	||
244 					(descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE)		||
245 					(descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER))
246 				maxPerStageDescriptorSampledImages += descriptorSetLayoutBinding->descriptorCount;
247 
248 			if ((descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
249 					(descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER))
250 				maxPerStageDescriptorStorageImages += descriptorSetLayoutBinding->descriptorCount;
251 
252 			if (descriptorSetLayoutBinding[ndx].descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
253 				maxPerStageDescriptorInputAttachments += descriptorSetLayoutBinding->descriptorCount;
254 		}
255 
256 		if (prop1.limits.maxPerStageDescriptorSamplers < maxPerStageDescriptorSamplers)
257 			return false;
258 		if (prop1.limits.maxPerStageDescriptorUniformBuffers < maxPerStageDescriptorUniformBuffers)
259 			return false;
260 		if (prop1.limits.maxPerStageDescriptorStorageBuffers < maxPerStageDescriptorStorageBuffers)
261 			return false;
262 		if (prop1.limits.maxPerStageDescriptorSampledImages < maxPerStageDescriptorSampledImages)
263 			return false;
264 		if (prop1.limits.maxPerStageDescriptorStorageImages < maxPerStageDescriptorStorageImages)
265 			return false;
266 		if (prop1.limits.maxPerStageDescriptorInputAttachments < maxPerStageDescriptorInputAttachments)
267 			return false;
268 
269 		return true;
270 	}
271 };
272 
273 class Maintenance3DescriptorTestCase : public TestCase
274 {
275 
276 public:
Maintenance3DescriptorTestCase(tcu::TestContext & testCtx)277 											Maintenance3DescriptorTestCase			(tcu::TestContext&	testCtx)
278 												: TestCase(testCtx, "descriptor_set", "tests vkGetDescriptorSetLayoutSupport struct")
279 	{}
~Maintenance3DescriptorTestCase(void)280 	virtual									~Maintenance3DescriptorTestCase			(void)
281 	{}
createInstance(Context & ctx) const282 	virtual TestInstance*					createInstance							(Context&	ctx) const
283 	{
284 		return new Maintenance3DescriptorTestInstance(ctx);
285 	}
286 
287 private:
288 };
289 
290 } // anonymous
291 
createMaintenance3Tests(tcu::TestContext & testCtx)292 	tcu::TestCaseGroup*						createMaintenance3Tests					(tcu::TestContext&	testCtx)
293 {
294 	de::MovePtr<tcu::TestCaseGroup>	main3Tests(new tcu::TestCaseGroup(testCtx, "maintenance3_check", "Maintenance3 Tests"));
295 	main3Tests->addChild(new Maintenance3StructTestCase(testCtx));
296 	main3Tests->addChild(new Maintenance3DescriptorTestCase(testCtx));
297 
298 	return main3Tests.release();
299 }
300 
301 } // api
302 } // vkt
303