• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 Google 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
21  * \brief Descriptor pool tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktApiDescriptorPoolTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 
27 #include "vkDefs.hpp"
28 #include "vkRef.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkPlatform.hpp"
31 #include "vkDeviceUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 
34 #include "tcuCommandLine.hpp"
35 #include "tcuTestLog.hpp"
36 #include "tcuPlatform.hpp"
37 
38 #include "deUniquePtr.hpp"
39 #include "deSharedPtr.hpp"
40 #include "deInt32.h"
41 #include "deSTLUtil.hpp"
42 
43 #define VK_DESCRIPTOR_TYPE_LAST (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + 1)
44 
45 namespace vkt
46 {
47 namespace api
48 {
49 
50 namespace
51 {
52 
53 using namespace std;
54 using namespace vk;
55 
56 struct ResetDescriptorPoolTestParams
57 {
ResetDescriptorPoolTestParamsvkt::api::__anon1e539a410111::ResetDescriptorPoolTestParams58 	ResetDescriptorPoolTestParams	(deUint32 numIterations, bool freeDescriptorSets = false)
59 		: m_numIterations		(numIterations)
60 		, m_freeDescriptorSets	(freeDescriptorSets)
61 	{}
62 
63 	deUint32	m_numIterations;
64 	bool		m_freeDescriptorSets;
65 };
66 
checkSupportFreeDescriptorSets(Context & context,const ResetDescriptorPoolTestParams params)67 void checkSupportFreeDescriptorSets (Context& context, const ResetDescriptorPoolTestParams params)
68 {
69 #ifdef CTS_USES_VULKANSC
70 	if(params.m_freeDescriptorSets && context.getDeviceVulkanSC10Properties().recycleDescriptorSetMemory == VK_FALSE )
71 		TCU_THROW(NotSupportedError, "vkFreeDescriptorSets not supported");
72 #else
73 	DE_UNREF(context);
74 	DE_UNREF(params);
75 #endif // CTS_USES_VULKANSC
76 }
77 
resetDescriptorPoolTest(Context & context,const ResetDescriptorPoolTestParams params)78 tcu::TestStatus resetDescriptorPoolTest (Context& context, const ResetDescriptorPoolTestParams params)
79 {
80 #ifndef CTS_USES_VULKANSC
81 	const deUint32				numDescriptorSetsPerIter = 2048;
82 #else
83 	const deUint32				numDescriptorSetsPerIter = 100;
84 #endif // CTS_USES_VULKANSC
85 	const DeviceInterface&		vkd						 = context.getDeviceInterface();
86 	const VkDevice				device					 = context.getDevice();
87 
88 	const VkDescriptorPoolSize descriptorPoolSize =
89 	{
90 		VK_DESCRIPTOR_TYPE_SAMPLER, // type
91 		numDescriptorSetsPerIter	// descriptorCount
92 	};
93 
94 	const VkDescriptorPoolCreateInfo descriptorPoolInfo =
95 	{
96 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,																			// sType
97 		NULL,																													// pNext
98 		(params.m_freeDescriptorSets) ? (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT : 0u,	// flags
99 		numDescriptorSetsPerIter,																								// maxSets
100 		1,																														// poolSizeCount
101 		&descriptorPoolSize																										// pPoolSizes
102 	};
103 
104 	{
105 		const Unique<VkDescriptorPool> descriptorPool(
106 			createDescriptorPool(vkd, device,
107 								 &descriptorPoolInfo));
108 
109 		const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding =
110 		{
111 			0,							// binding
112 			VK_DESCRIPTOR_TYPE_SAMPLER, // descriptorType
113 			1,							// descriptorCount
114 			VK_SHADER_STAGE_ALL,		// stageFlags
115 			NULL						// pImmutableSamplers
116 		};
117 
118 		const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo =
119 		{
120 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
121 			NULL,													// pNext
122 			0,														// flags
123 			1,														// bindingCount
124 			&descriptorSetLayoutBinding								// pBindings
125 		};
126 
127 		{
128 			typedef de::SharedPtr<Unique<VkDescriptorSetLayout> > DescriptorSetLayoutPtr;
129 
130 			vector<DescriptorSetLayoutPtr> descriptorSetLayouts;
131 			descriptorSetLayouts.reserve(numDescriptorSetsPerIter);
132 
133 			for (deUint32 ndx = 0; ndx < numDescriptorSetsPerIter; ++ndx)
134 			{
135 				descriptorSetLayouts.push_back(
136 					DescriptorSetLayoutPtr(
137 						new Unique<VkDescriptorSetLayout>(
138 							createDescriptorSetLayout(vkd, device,
139 													  &descriptorSetLayoutInfo))));
140 			}
141 
142 			vector<VkDescriptorSetLayout> descriptorSetLayoutsRaw(numDescriptorSetsPerIter);
143 
144 			for (deUint32 ndx = 0; ndx < numDescriptorSetsPerIter; ++ndx)
145 			{
146 				descriptorSetLayoutsRaw[ndx] = **descriptorSetLayouts[ndx];
147 			}
148 
149 			const VkDescriptorSetAllocateInfo descriptorSetInfo =
150 			{
151 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
152 				NULL,											// pNext
153 				*descriptorPool,								// descriptorPool
154 				numDescriptorSetsPerIter,						// descriptorSetCount
155 				&descriptorSetLayoutsRaw[0]						// pSetLayouts
156 			};
157 
158 			vector<VkDescriptorSet> testSets(numDescriptorSetsPerIter);
159 
160 			for (deUint32 ndx = 0; ndx < params.m_numIterations; ++ndx)
161 			{
162 				if (ndx % 1024 == 0) context.getTestContext().touchWatchdog();
163 				// The test should crash in this loop at some point if there is a memory leak
164 				VK_CHECK(vkd.allocateDescriptorSets(device, &descriptorSetInfo, &testSets[0]));
165 				if (params.m_freeDescriptorSets)
166 					VK_CHECK(vkd.freeDescriptorSets(device, *descriptorPool, 1, &testSets[0]));
167 				VK_CHECK(vkd.resetDescriptorPool(device, *descriptorPool, 0));
168 			}
169 
170 		}
171 	}
172 
173 	// If it didn't crash, pass
174 	return tcu::TestStatus::pass("Pass");
175 }
176 
outOfPoolMemoryTest(Context & context)177 tcu::TestStatus outOfPoolMemoryTest (Context& context)
178 {
179 	const DeviceInterface&	vkd							= context.getDeviceInterface();
180 	const VkDevice			device						= context.getDevice();
181 	const bool				expectOutOfPoolMemoryError	= context.isDeviceFunctionalitySupported("VK_KHR_maintenance1");
182 	deUint32				numErrorsReturned			= 0;
183 
184 	const struct FailureCase
185 	{
186 		deUint32	poolDescriptorCount;		//!< total number of descriptors (of a given type) in the descriptor pool
187 		deUint32	poolMaxSets;				//!< max number of descriptor sets that can be allocated from the pool
188 		deUint32	bindingCount;				//!< number of bindings per descriptor set layout
189 		deUint32	bindingDescriptorCount;		//!< number of descriptors in a binding (array size) (in all bindings)
190 		deUint32	descriptorSetCount;			//!< number of descriptor sets to allocate
191 		string		description;				//!< the log message for this failure condition
192 	} failureCases[] =
193 	{
194 		//	pool			pool		binding		binding		alloc set
195 		//	descr. count	max sets	count		array size	count
196 		{	4u,				2u,			1u,			1u,			3u,		"Out of descriptor sets",											},
197 		{	3u,				4u,			1u,			1u,			4u,		"Out of descriptors (due to the number of sets)",					},
198 		{	2u,				1u,			3u,			1u,			1u,		"Out of descriptors (due to the number of bindings)",				},
199 		{	3u,				2u,			1u,			2u,			2u,		"Out of descriptors (due to descriptor array size)",				},
200 		{	5u,				1u,			2u,			3u,			1u,		"Out of descriptors (due to descriptor array size in all bindings)",},
201 	};
202 
203 	context.getTestContext().getLog()
204 		<< tcu::TestLog::Message
205 		<< "Creating a descriptor pool with insufficient resources. Descriptor set allocation is likely to fail."
206 		<< tcu::TestLog::EndMessage;
207 
208 	for (deUint32 failureCaseNdx = 0u; failureCaseNdx < DE_LENGTH_OF_ARRAY(failureCases); ++failureCaseNdx)
209 	{
210 		const FailureCase& params = failureCases[failureCaseNdx];
211 		context.getTestContext().getLog() << tcu::TestLog::Message << "Checking: " << params.description << tcu::TestLog::EndMessage;
212 
213 		for (VkDescriptorType	descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
214 								descriptorType < VK_DESCRIPTOR_TYPE_LAST;
215 								descriptorType = static_cast<VkDescriptorType>(descriptorType + 1))
216 		{
217 			context.getTestContext().getLog() << tcu::TestLog::Message << "- " << getDescriptorTypeName(descriptorType) << tcu::TestLog::EndMessage;
218 
219 			const VkDescriptorPoolSize					descriptorPoolSize =
220 			{
221 				descriptorType,												// type
222 				params.poolDescriptorCount,									// descriptorCount
223 			};
224 
225 			const VkDescriptorPoolCreateInfo			descriptorPoolCreateInfo =
226 			{
227 				VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,				// VkStructureType                sType;
228 				DE_NULL,													// const void*                    pNext;
229 				(VkDescriptorPoolCreateFlags)0,								// VkDescriptorPoolCreateFlags    flags;
230 				params.poolMaxSets,											// uint32_t                       maxSets;
231 				1u,															// uint32_t                       poolSizeCount;
232 				&descriptorPoolSize,										// const VkDescriptorPoolSize*    pPoolSizes;
233 			};
234 
235 			const Unique<VkDescriptorPool>				descriptorPool(createDescriptorPool(vkd, device, &descriptorPoolCreateInfo));
236 
237 			VkShaderStageFlags stageFlags = (descriptorType != VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) ? VK_SHADER_STAGE_ALL : VK_SHADER_STAGE_FRAGMENT_BIT;
238 			const VkDescriptorSetLayoutBinding			descriptorSetLayoutBinding =
239 			{
240 				0u,															// uint32_t              binding;
241 				descriptorType,												// VkDescriptorType      descriptorType;
242 				params.bindingDescriptorCount,								// uint32_t              descriptorCount;
243 				stageFlags,													// VkShaderStageFlags    stageFlags;
244 				DE_NULL,													// const VkSampler*      pImmutableSamplers;
245 			};
246 
247 			vector<VkDescriptorSetLayoutBinding>	descriptorSetLayoutBindings (params.bindingCount, descriptorSetLayoutBinding);
248 
249 			for (deUint32 binding = 0; binding < deUint32(descriptorSetLayoutBindings.size()); ++binding)
250 			{
251 				descriptorSetLayoutBindings[binding].binding = binding;
252 			}
253 
254 			const VkDescriptorSetLayoutCreateInfo		descriptorSetLayoutInfo =
255 			{
256 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType                        sType;
257 				DE_NULL,													// const void*                            pNext;
258 				(VkDescriptorSetLayoutCreateFlags)0,						// VkDescriptorSetLayoutCreateFlags       flags;
259 				static_cast<deUint32>(descriptorSetLayoutBindings.size()),	// uint32_t                               bindingCount;
260 				&descriptorSetLayoutBindings[0],							// const VkDescriptorSetLayoutBinding*    pBindings;
261 			};
262 
263 			const Unique<VkDescriptorSetLayout>			descriptorSetLayout	(createDescriptorSetLayout(vkd, device, &descriptorSetLayoutInfo));
264 			const vector<VkDescriptorSetLayout>			rawSetLayouts		(params.descriptorSetCount, *descriptorSetLayout);
265 			vector<VkDescriptorSet>						rawDescriptorSets	(params.descriptorSetCount, DE_NULL);
266 
267 			const VkDescriptorSetAllocateInfo			descriptorSetAllocateInfo =
268 			{
269 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,				// VkStructureType                 sType;
270 				DE_NULL,													// const void*                     pNext;
271 				*descriptorPool,											// VkDescriptorPool                descriptorPool;
272 				static_cast<deUint32>(rawSetLayouts.size()),				// uint32_t                        descriptorSetCount;
273 				&rawSetLayouts[0],											// const VkDescriptorSetLayout*    pSetLayouts;
274 			};
275 
276 			const VkResult result = vkd.allocateDescriptorSets(device, &descriptorSetAllocateInfo, &rawDescriptorSets[0]);
277 
278 			if (result != VK_SUCCESS)
279 			{
280 				++numErrorsReturned;
281 
282 				if (expectOutOfPoolMemoryError && result != VK_ERROR_OUT_OF_POOL_MEMORY)
283 					return tcu::TestStatus::fail("Expected VK_ERROR_OUT_OF_POOL_MEMORY but got " + string(getResultName(result)) + " instead");
284 			}
285 			else
286 				context.getTestContext().getLog() << tcu::TestLog::Message << "  Allocation was successful anyway" << tcu::TestLog::EndMessage;
287 		}
288 	}
289 
290 	if (numErrorsReturned == 0u)
291 		return tcu::TestStatus::pass("Not validated");
292 	else
293 		return tcu::TestStatus::pass("Pass");
294 }
295 
zeroPoolSizeCount(Context & context)296 tcu::TestStatus zeroPoolSizeCount(Context& context)
297 {
298 	const DeviceInterface&	vkd = context.getDeviceInterface();
299 	const VkDevice			device = context.getDevice();
300 
301 	const VkDescriptorPoolCreateInfo			descriptorPoolCreateInfo =
302 	{
303 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,				// VkStructureType                sType;
304 		DE_NULL,													// const void*                    pNext;
305 		VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,			// VkDescriptorPoolCreateFlags    flags;
306 		1u,															// uint32_t                       maxSets;
307 		0u,															// uint32_t                       poolSizeCount;
308 		DE_NULL,													// const VkDescriptorPoolSize*    pPoolSizes;
309 	};
310 
311 	// Test a pool can be created for empty descriptor sets.
312 	const Unique<VkDescriptorPool>				descriptorPool(createDescriptorPool(vkd, device, &descriptorPoolCreateInfo));
313 
314 	const VkDescriptorSetLayoutCreateInfo		descriptorSetLayoutInfo =
315 	{
316 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType                        sType;
317 		DE_NULL,													// const void*                            pNext;
318 		(VkDescriptorSetLayoutCreateFlags)0,						// VkDescriptorSetLayoutCreateFlags       flags;
319 		0u,															// uint32_t                               bindingCount;
320 		DE_NULL,													// const VkDescriptorSetLayoutBinding*    pBindings;
321 	};
322 
323 	const Unique<VkDescriptorSetLayout>			descriptorSetLayout(createDescriptorSetLayout(vkd, device, &descriptorSetLayoutInfo));
324 
325 	const VkDescriptorSetAllocateInfo			descriptorSetAllocateInfo =
326 	{
327 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,				// VkStructureType                 sType;
328 		DE_NULL,													// const void*                     pNext;
329 		*descriptorPool,											// VkDescriptorPool                descriptorPool;
330 		1u,															// uint32_t                        descriptorSetCount;
331 		&descriptorSetLayout.get(),									// const VkDescriptorSetLayout*    pSetLayouts;
332 	};
333 
334 	// Create an empty descriptor set from the pool.
335 	VkDescriptorSet descriptorSet;
336 	VkResult result = vkd.allocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet);
337 	if (result != VK_SUCCESS)
338 		return tcu::TestStatus::fail("Expected vkAllocateDescriptorSets to return VK_SUCCESS but got " + string(getResultName(result)) + " instead");
339 
340 	// Free the empty descriptor set back to the pool.
341 	result = vkd.freeDescriptorSets(device, *descriptorPool, 1, &descriptorSet);
342 	if (result != VK_SUCCESS)
343 		return tcu::TestStatus::fail("Expected vkFreeDescriptorSets to return VK_SUCCESS but got " + string(getResultName(result)) + " instead");
344 
345 	return tcu::TestStatus::pass("Pass");
346 }
347 
348 } // anonymous
349 
createDescriptorPoolTests(tcu::TestContext & testCtx)350 tcu::TestCaseGroup* createDescriptorPoolTests (tcu::TestContext& testCtx)
351 {
352 	const deUint32 numIterationsHigh = 4096;
353 
354 	de::MovePtr<tcu::TestCaseGroup> descriptorPoolTests(
355 		new tcu::TestCaseGroup(testCtx, "descriptor_pool", "Descriptor Pool Tests"));
356 
357 	addFunctionCase(descriptorPoolTests.get(),
358 					"repeated_reset_short",
359 					"Test 2 cycles of vkAllocateDescriptorSets and vkResetDescriptorPool (should pass)",
360 					checkSupportFreeDescriptorSets,
361 					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(2U));
362 	addFunctionCase(descriptorPoolTests.get(),
363 					"repeated_reset_long",
364 					"Test many cycles of vkAllocateDescriptorSets and vkResetDescriptorPool",
365 					checkSupportFreeDescriptorSets,
366 					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(numIterationsHigh));
367 	addFunctionCase(descriptorPoolTests.get(),
368 					"repeated_free_reset_short",
369 					"Test 2 cycles of vkAllocateDescriptorSets, vkFreeDescriptorSets and vkResetDescriptorPool (should pass)",
370 					checkSupportFreeDescriptorSets,
371 					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(2U, true));
372 	addFunctionCase(descriptorPoolTests.get(),
373 					"repeated_free_reset_long",
374 					"Test many cycles of vkAllocateDescriptorSets, vkFreeDescriptorSets and vkResetDescriptorPool",
375 					checkSupportFreeDescriptorSets,
376 					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(numIterationsHigh, true));
377 	addFunctionCase(descriptorPoolTests.get(),
378 					"out_of_pool_memory",
379 					"Test that when we run out of descriptors a correct error code is returned",
380 					outOfPoolMemoryTest);
381 	addFunctionCase(descriptorPoolTests.get(),
382 					"zero_pool_size_count",
383 					"Test a descriptor pool object can be created with zero pools without error or crash",
384 					zeroPoolSizeCount);
385 
386 	return descriptorPoolTests.release();
387 }
388 
389 } // api
390 } // vkt
391