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