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