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