• 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::__anon8597da820111::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 
resetDescriptorPoolTest(Context & context,const ResetDescriptorPoolTestParams params)67 tcu::TestStatus resetDescriptorPoolTest (Context& context, const ResetDescriptorPoolTestParams params)
68 {
69 	const deUint32				numDescriptorSetsPerIter = 2048;
70 	const DeviceInterface&		vkd						 = context.getDeviceInterface();
71 	const VkDevice				device					 = context.getDevice();
72 
73 	const VkDescriptorPoolSize descriptorPoolSize =
74 	{
75 		VK_DESCRIPTOR_TYPE_SAMPLER, // type
76 		numDescriptorSetsPerIter	// descriptorCount
77 	};
78 
79 	const VkDescriptorPoolCreateInfo descriptorPoolInfo =
80 	{
81 		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,																			// sType
82 		NULL,																													// pNext
83 		(params.m_freeDescriptorSets) ? (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT : 0u,	// flags
84 		numDescriptorSetsPerIter,																								// maxSets
85 		1,																														// poolSizeCount
86 		&descriptorPoolSize																										// pPoolSizes
87 	};
88 
89 	{
90 		const Unique<VkDescriptorPool> descriptorPool(
91 			createDescriptorPool(vkd, device,
92 								 &descriptorPoolInfo));
93 
94 		const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding =
95 		{
96 			0,							// binding
97 			VK_DESCRIPTOR_TYPE_SAMPLER, // descriptorType
98 			1,							// descriptorCount
99 			VK_SHADER_STAGE_ALL,		// stageFlags
100 			NULL						// pImmutableSamplers
101 		};
102 
103 		const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo =
104 		{
105 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// sType
106 			NULL,													// pNext
107 			0,														// flags
108 			1,														// bindingCount
109 			&descriptorSetLayoutBinding								// pBindings
110 		};
111 
112 		{
113 			typedef de::SharedPtr<Unique<VkDescriptorSetLayout> > DescriptorSetLayoutPtr;
114 
115 			vector<DescriptorSetLayoutPtr> descriptorSetLayouts;
116 			descriptorSetLayouts.reserve(numDescriptorSetsPerIter);
117 
118 			for (deUint32 ndx = 0; ndx < numDescriptorSetsPerIter; ++ndx)
119 			{
120 				descriptorSetLayouts.push_back(
121 					DescriptorSetLayoutPtr(
122 						new Unique<VkDescriptorSetLayout>(
123 							createDescriptorSetLayout(vkd, device,
124 													  &descriptorSetLayoutInfo))));
125 			}
126 
127 			vector<VkDescriptorSetLayout> descriptorSetLayoutsRaw(numDescriptorSetsPerIter);
128 
129 			for (deUint32 ndx = 0; ndx < numDescriptorSetsPerIter; ++ndx)
130 			{
131 				descriptorSetLayoutsRaw[ndx] = **descriptorSetLayouts[ndx];
132 			}
133 
134 			const VkDescriptorSetAllocateInfo descriptorSetInfo =
135 			{
136 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
137 				NULL,											// pNext
138 				*descriptorPool,								// descriptorPool
139 				numDescriptorSetsPerIter,						// descriptorSetCount
140 				&descriptorSetLayoutsRaw[0]						// pSetLayouts
141 			};
142 
143 			vector<VkDescriptorSet> testSets(numDescriptorSetsPerIter);
144 
145 			for (deUint32 ndx = 0; ndx < params.m_numIterations; ++ndx)
146 			{
147 				if (ndx % 1024 == 0) context.getTestContext().touchWatchdog();
148 				// The test should crash in this loop at some point if there is a memory leak
149 				VK_CHECK(vkd.allocateDescriptorSets(device, &descriptorSetInfo, &testSets[0]));
150 				if (params.m_freeDescriptorSets)
151 					VK_CHECK(vkd.freeDescriptorSets(device, *descriptorPool, 1, &testSets[0]));
152 				VK_CHECK(vkd.resetDescriptorPool(device, *descriptorPool, 0));
153 			}
154 
155 		}
156 	}
157 
158 	// If it didn't crash, pass
159 	return tcu::TestStatus::pass("Pass");
160 }
161 
outOfPoolMemoryTest(Context & context)162 tcu::TestStatus outOfPoolMemoryTest (Context& context)
163 {
164 	const DeviceInterface&	vkd							= context.getDeviceInterface();
165 	const VkDevice			device						= context.getDevice();
166 	const bool				expectOutOfPoolMemoryError	= context.isDeviceFunctionalitySupported("VK_KHR_maintenance1");
167 	deUint32				numErrorsReturned			= 0;
168 
169 	const struct FailureCase
170 	{
171 		deUint32	poolDescriptorCount;		//!< total number of descriptors (of a given type) in the descriptor pool
172 		deUint32	poolMaxSets;				//!< max number of descriptor sets that can be allocated from the pool
173 		deUint32	bindingCount;				//!< number of bindings per descriptor set layout
174 		deUint32	bindingDescriptorCount;		//!< number of descriptors in a binding (array size) (in all bindings)
175 		deUint32	descriptorSetCount;			//!< number of descriptor sets to allocate
176 		string		description;				//!< the log message for this failure condition
177 	} failureCases[] =
178 	{
179 		//	pool			pool		binding		binding		alloc set
180 		//	descr. count	max sets	count		array size	count
181 		{	4u,				2u,			1u,			1u,			3u,		"Out of descriptor sets",											},
182 		{	3u,				4u,			1u,			1u,			4u,		"Out of descriptors (due to the number of sets)",					},
183 		{	2u,				1u,			3u,			1u,			1u,		"Out of descriptors (due to the number of bindings)",				},
184 		{	3u,				2u,			1u,			2u,			2u,		"Out of descriptors (due to descriptor array size)",				},
185 		{	5u,				1u,			2u,			3u,			1u,		"Out of descriptors (due to descriptor array size in all bindings)",},
186 	};
187 
188 	context.getTestContext().getLog()
189 		<< tcu::TestLog::Message
190 		<< "Creating a descriptor pool with insufficient resources. Descriptor set allocation is likely to fail."
191 		<< tcu::TestLog::EndMessage;
192 
193 	for (deUint32 failureCaseNdx = 0u; failureCaseNdx < DE_LENGTH_OF_ARRAY(failureCases); ++failureCaseNdx)
194 	{
195 		const FailureCase& params = failureCases[failureCaseNdx];
196 		context.getTestContext().getLog() << tcu::TestLog::Message << "Checking: " << params.description << tcu::TestLog::EndMessage;
197 
198 		for (VkDescriptorType	descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
199 								descriptorType < VK_DESCRIPTOR_TYPE_LAST;
200 								descriptorType = static_cast<VkDescriptorType>(descriptorType + 1))
201 		{
202 			context.getTestContext().getLog() << tcu::TestLog::Message << "- " << getDescriptorTypeName(descriptorType) << tcu::TestLog::EndMessage;
203 
204 			const VkDescriptorPoolSize					descriptorPoolSize =
205 			{
206 				descriptorType,												// type
207 				params.poolDescriptorCount,									// descriptorCount
208 			};
209 
210 			const VkDescriptorPoolCreateInfo			descriptorPoolCreateInfo =
211 			{
212 				VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,				// VkStructureType                sType;
213 				DE_NULL,													// const void*                    pNext;
214 				(VkDescriptorPoolCreateFlags)0,								// VkDescriptorPoolCreateFlags    flags;
215 				params.poolMaxSets,											// uint32_t                       maxSets;
216 				1u,															// uint32_t                       poolSizeCount;
217 				&descriptorPoolSize,										// const VkDescriptorPoolSize*    pPoolSizes;
218 			};
219 
220 			const Unique<VkDescriptorPool>				descriptorPool(createDescriptorPool(vkd, device, &descriptorPoolCreateInfo));
221 
222 			VkShaderStageFlags stageFlags = (descriptorType != VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) ? VK_SHADER_STAGE_ALL : VK_SHADER_STAGE_FRAGMENT_BIT;
223 			const VkDescriptorSetLayoutBinding			descriptorSetLayoutBinding =
224 			{
225 				0u,															// uint32_t              binding;
226 				descriptorType,												// VkDescriptorType      descriptorType;
227 				params.bindingDescriptorCount,								// uint32_t              descriptorCount;
228 				stageFlags,													// VkShaderStageFlags    stageFlags;
229 				DE_NULL,													// const VkSampler*      pImmutableSamplers;
230 			};
231 
232 			vector<VkDescriptorSetLayoutBinding>	descriptorSetLayoutBindings (params.bindingCount, descriptorSetLayoutBinding);
233 
234 			for (deUint32 binding = 0; binding < deUint32(descriptorSetLayoutBindings.size()); ++binding)
235 			{
236 				descriptorSetLayoutBindings[binding].binding = binding;
237 			}
238 
239 			const VkDescriptorSetLayoutCreateInfo		descriptorSetLayoutInfo =
240 			{
241 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType                        sType;
242 				DE_NULL,													// const void*                            pNext;
243 				(VkDescriptorSetLayoutCreateFlags)0,						// VkDescriptorSetLayoutCreateFlags       flags;
244 				static_cast<deUint32>(descriptorSetLayoutBindings.size()),	// uint32_t                               bindingCount;
245 				&descriptorSetLayoutBindings[0],							// const VkDescriptorSetLayoutBinding*    pBindings;
246 			};
247 
248 			const Unique<VkDescriptorSetLayout>			descriptorSetLayout	(createDescriptorSetLayout(vkd, device, &descriptorSetLayoutInfo));
249 			const vector<VkDescriptorSetLayout>			rawSetLayouts		(params.descriptorSetCount, *descriptorSetLayout);
250 			vector<VkDescriptorSet>						rawDescriptorSets	(params.descriptorSetCount, DE_NULL);
251 
252 			const VkDescriptorSetAllocateInfo			descriptorSetAllocateInfo =
253 			{
254 				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,				// VkStructureType                 sType;
255 				DE_NULL,													// const void*                     pNext;
256 				*descriptorPool,											// VkDescriptorPool                descriptorPool;
257 				static_cast<deUint32>(rawSetLayouts.size()),				// uint32_t                        descriptorSetCount;
258 				&rawSetLayouts[0],											// const VkDescriptorSetLayout*    pSetLayouts;
259 			};
260 
261 			const VkResult result = vkd.allocateDescriptorSets(device, &descriptorSetAllocateInfo, &rawDescriptorSets[0]);
262 
263 			if (result != VK_SUCCESS)
264 			{
265 				++numErrorsReturned;
266 
267 				if (expectOutOfPoolMemoryError && result != VK_ERROR_OUT_OF_POOL_MEMORY)
268 					return tcu::TestStatus::fail("Expected VK_ERROR_OUT_OF_POOL_MEMORY but got " + string(getResultName(result)) + " instead");
269 			}
270 			else
271 				context.getTestContext().getLog() << tcu::TestLog::Message << "  Allocation was successful anyway" << tcu::TestLog::EndMessage;
272 		}
273 	}
274 
275 	if (numErrorsReturned == 0u)
276 		return tcu::TestStatus::pass("Not validated");
277 	else
278 		return tcu::TestStatus::pass("Pass");
279 }
280 
281 } // anonymous
282 
createDescriptorPoolTests(tcu::TestContext & testCtx)283 tcu::TestCaseGroup* createDescriptorPoolTests (tcu::TestContext& testCtx)
284 {
285 	const deUint32 numIterationsHigh = 4096;
286 
287 	de::MovePtr<tcu::TestCaseGroup> descriptorPoolTests(
288 		new tcu::TestCaseGroup(testCtx, "descriptor_pool", "Descriptor Pool Tests"));
289 
290 	addFunctionCase(descriptorPoolTests.get(),
291 					"repeated_reset_short",
292 					"Test 2 cycles of vkAllocateDescriptorSets and vkResetDescriptorPool (should pass)",
293 					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(2U));
294 	addFunctionCase(descriptorPoolTests.get(),
295 					"repeated_reset_long",
296 					"Test many cycles of vkAllocateDescriptorSets and vkResetDescriptorPool",
297 					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(numIterationsHigh));
298 	addFunctionCase(descriptorPoolTests.get(),
299 					"repeated_free_reset_short",
300 					"Test 2 cycles of vkAllocateDescriptorSets, vkFreeDescriptorSets and vkResetDescriptorPool (should pass)",
301 					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(2U, true));
302 	addFunctionCase(descriptorPoolTests.get(),
303 					"repeated_free_reset_long",
304 					"Test many cycles of vkAllocateDescriptorSets, vkFreeDescriptorSets and vkResetDescriptorPool",
305 					resetDescriptorPoolTest, ResetDescriptorPoolTestParams(numIterationsHigh, true));
306 	addFunctionCase(descriptorPoolTests.get(),
307 					"out_of_pool_memory",
308 					"Test that when we run out of descriptors a correct error code is returned",
309 					outOfPoolMemoryTest);
310 
311 	return descriptorPoolTests.release();
312 }
313 
314 } // api
315 } // vkt
316