1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 Google Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Descriptor pool tests
22 *//*--------------------------------------------------------------------*/
24 #include "vktApiDescriptorPoolTests.hpp"
25 #include "vktTestCaseUtil.hpp"
29 #include "vkRefUtil.hpp"
30 #include "vkPlatform.hpp"
31 #include "vkDeviceUtil.hpp"
32 #include "vkQueryUtil.hpp"
34 #include "tcuCommandLine.hpp"
35 #include "tcuTestLog.hpp"
36 #include "tcuPlatform.hpp"
38 #include "deUniquePtr.hpp"
39 #include "deSharedPtr.hpp"
41 #include "deSTLUtil.hpp"
43 #define VK_DESCRIPTOR_TYPE_LAST (VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT + 1)
56 struct ResetDescriptorPoolTestParams
58 ResetDescriptorPoolTestParams (deUint32 numIterations, bool freeDescriptorSets = false)
59 : m_numIterations (numIterations)
60 , m_freeDescriptorSets (freeDescriptorSets)
63 deUint32 m_numIterations;
64 bool m_freeDescriptorSets;
67 tcu::TestStatus resetDescriptorPoolTest (Context& context, const ResetDescriptorPoolTestParams params)
69 const deUint32 numDescriptorSetsPerIter = 2048;
70 const DeviceInterface& vkd = context.getDeviceInterface();
71 const VkDevice device = context.getDevice();
73 const VkDescriptorPoolSize descriptorPoolSize =
75 VK_DESCRIPTOR_TYPE_SAMPLER, // type
76 numDescriptorSetsPerIter // descriptorCount
79 const VkDescriptorPoolCreateInfo descriptorPoolInfo =
81 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // sType
83 (params.m_freeDescriptorSets) ? (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT : 0u, // flags
84 numDescriptorSetsPerIter, // maxSets
86 &descriptorPoolSize // pPoolSizes
90 const Unique<VkDescriptorPool> descriptorPool(
91 createDescriptorPool(vkd, device,
92 &descriptorPoolInfo));
94 const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding =
97 VK_DESCRIPTOR_TYPE_SAMPLER, // descriptorType
99 VK_SHADER_STAGE_ALL, // stageFlags
100 NULL // pImmutableSamplers
103 const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo =
105 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // sType
109 &descriptorSetLayoutBinding // pBindings
113 typedef de::SharedPtr<Unique<VkDescriptorSetLayout> > DescriptorSetLayoutPtr;
115 vector<DescriptorSetLayoutPtr> descriptorSetLayouts;
116 descriptorSetLayouts.reserve(numDescriptorSetsPerIter);
118 for (deUint32 ndx = 0; ndx < numDescriptorSetsPerIter; ++ndx)
120 descriptorSetLayouts.push_back(
121 DescriptorSetLayoutPtr(
122 new Unique<VkDescriptorSetLayout>(
123 createDescriptorSetLayout(vkd, device,
124 &descriptorSetLayoutInfo))));
127 vector<VkDescriptorSetLayout> descriptorSetLayoutsRaw(numDescriptorSetsPerIter);
129 for (deUint32 ndx = 0; ndx < numDescriptorSetsPerIter; ++ndx)
131 descriptorSetLayoutsRaw[ndx] = **descriptorSetLayouts[ndx];
134 const VkDescriptorSetAllocateInfo descriptorSetInfo =
136 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // sType
138 *descriptorPool, // descriptorPool
139 numDescriptorSetsPerIter, // descriptorSetCount
140 &descriptorSetLayoutsRaw[0] // pSetLayouts
143 vector<VkDescriptorSet> testSets(numDescriptorSetsPerIter);
145 for (deUint32 ndx = 0; ndx < params.m_numIterations; ++ndx)
147 // The test should crash in this loop at some point if there is a memory leak
148 VK_CHECK(vkd.allocateDescriptorSets(device, &descriptorSetInfo, &testSets[0]));
149 if (params.m_freeDescriptorSets)
150 VK_CHECK(vkd.freeDescriptorSets(device, *descriptorPool, 1, &testSets[0]));
151 VK_CHECK(vkd.resetDescriptorPool(device, *descriptorPool, 0));
157 // If it didn't crash, pass
158 return tcu::TestStatus::pass("Pass");
161 tcu::TestStatus outOfPoolMemoryTest (Context& context)
163 const DeviceInterface& vkd = context.getDeviceInterface();
164 const VkDevice device = context.getDevice();
165 const bool expectOutOfPoolMemoryError = isDeviceExtensionSupported(context.getUsedApiVersion(), context.getDeviceExtensions(), "VK_KHR_maintenance1");
166 deUint32 numErrorsReturned = 0;
168 const struct FailureCase
170 deUint32 poolDescriptorCount; //!< total number of descriptors (of a given type) in the descriptor pool
171 deUint32 poolMaxSets; //!< max number of descriptor sets that can be allocated from the pool
172 deUint32 bindingCount; //!< number of bindings per descriptor set layout
173 deUint32 bindingDescriptorCount; //!< number of descriptors in a binding (array size) (in all bindings)
174 deUint32 descriptorSetCount; //!< number of descriptor sets to allocate
175 string description; //!< the log message for this failure condition
178 // pool pool binding binding alloc set
179 // descr. count max sets count array size count
180 { 4u, 2u, 1u, 1u, 3u, "Out of descriptor sets", },
181 { 3u, 4u, 1u, 1u, 4u, "Out of descriptors (due to the number of sets)", },
182 { 2u, 1u, 3u, 1u, 1u, "Out of descriptors (due to the number of bindings)", },
183 { 3u, 2u, 1u, 2u, 2u, "Out of descriptors (due to descriptor array size)", },
184 { 5u, 1u, 2u, 3u, 1u, "Out of descriptors (due to descriptor array size in all bindings)",},
187 context.getTestContext().getLog()
188 << tcu::TestLog::Message
189 << "Creating a descriptor pool with insufficient resources. Descriptor set allocation is likely to fail."
190 << tcu::TestLog::EndMessage;
192 for (deUint32 failureCaseNdx = 0u; failureCaseNdx < DE_LENGTH_OF_ARRAY(failureCases); ++failureCaseNdx)
194 const FailureCase& params = failureCases[failureCaseNdx];
195 context.getTestContext().getLog() << tcu::TestLog::Message << "Checking: " << params.description << tcu::TestLog::EndMessage;
197 for (VkDescriptorType descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
198 descriptorType < VK_DESCRIPTOR_TYPE_LAST;
199 descriptorType = static_cast<VkDescriptorType>(descriptorType + 1))
201 context.getTestContext().getLog() << tcu::TestLog::Message << "- " << getDescriptorTypeName(descriptorType) << tcu::TestLog::EndMessage;
203 const VkDescriptorPoolSize descriptorPoolSize =
205 descriptorType, // type
206 params.poolDescriptorCount, // descriptorCount
209 const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo =
211 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType;
212 DE_NULL, // const void* pNext;
213 (VkDescriptorPoolCreateFlags)0, // VkDescriptorPoolCreateFlags flags;
214 params.poolMaxSets, // uint32_t maxSets;
215 1u, // uint32_t poolSizeCount;
216 &descriptorPoolSize, // const VkDescriptorPoolSize* pPoolSizes;
219 const Unique<VkDescriptorPool> descriptorPool(createDescriptorPool(vkd, device, &descriptorPoolCreateInfo));
221 const VkDescriptorSetLayoutBinding descriptorSetLayoutBinding =
223 0u, // uint32_t binding;
224 descriptorType, // VkDescriptorType descriptorType;
225 params.bindingDescriptorCount, // uint32_t descriptorCount;
226 VK_SHADER_STAGE_ALL, // VkShaderStageFlags stageFlags;
227 DE_NULL, // const VkSampler* pImmutableSamplers;
230 vector<VkDescriptorSetLayoutBinding> descriptorSetLayoutBindings (params.bindingCount, descriptorSetLayoutBinding);
232 for (deUint32 binding = 0; binding < deUint32(descriptorSetLayoutBindings.size()); ++binding)
234 descriptorSetLayoutBindings[binding].binding = binding;
237 const VkDescriptorSetLayoutCreateInfo descriptorSetLayoutInfo =
239 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType;
240 DE_NULL, // const void* pNext;
241 (VkDescriptorSetLayoutCreateFlags)0, // VkDescriptorSetLayoutCreateFlags flags;
242 static_cast<deUint32>(descriptorSetLayoutBindings.size()), // uint32_t bindingCount;
243 &descriptorSetLayoutBindings[0], // const VkDescriptorSetLayoutBinding* pBindings;
246 const Unique<VkDescriptorSetLayout> descriptorSetLayout (createDescriptorSetLayout(vkd, device, &descriptorSetLayoutInfo));
247 const vector<VkDescriptorSetLayout> rawSetLayouts (params.descriptorSetCount, *descriptorSetLayout);
248 vector<VkDescriptorSet> rawDescriptorSets (params.descriptorSetCount, DE_NULL);
250 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
252 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType;
253 DE_NULL, // const void* pNext;
254 *descriptorPool, // VkDescriptorPool descriptorPool;
255 static_cast<deUint32>(rawSetLayouts.size()), // uint32_t descriptorSetCount;
256 &rawSetLayouts[0], // const VkDescriptorSetLayout* pSetLayouts;
259 const VkResult result = vkd.allocateDescriptorSets(device, &descriptorSetAllocateInfo, &rawDescriptorSets[0]);
261 if (result != VK_SUCCESS)
265 if (expectOutOfPoolMemoryError && result != VK_ERROR_OUT_OF_POOL_MEMORY)
266 return tcu::TestStatus::fail("Expected VK_ERROR_OUT_OF_POOL_MEMORY but got " + string(getResultName(result)) + " instead");
269 context.getTestContext().getLog() << tcu::TestLog::Message << " Allocation was successful anyway" << tcu::TestLog::EndMessage;
273 if (numErrorsReturned == 0u)
274 return tcu::TestStatus::pass("Not validated");
276 return tcu::TestStatus::pass("Pass");
281 tcu::TestCaseGroup* createDescriptorPoolTests (tcu::TestContext& testCtx)
283 const deUint32 numIterationsHigh = 4096;
285 de::MovePtr<tcu::TestCaseGroup> descriptorPoolTests(
286 new tcu::TestCaseGroup(testCtx, "descriptor_pool", "Descriptor Pool Tests"));
288 addFunctionCase(descriptorPoolTests.get(),
289 "repeated_reset_short",
290 "Test 2 cycles of vkAllocateDescriptorSets and vkResetDescriptorPool (should pass)",
291 resetDescriptorPoolTest, ResetDescriptorPoolTestParams(2U));
292 addFunctionCase(descriptorPoolTests.get(),
293 "repeated_reset_long",
294 "Test many cycles of vkAllocateDescriptorSets and vkResetDescriptorPool",
295 resetDescriptorPoolTest, ResetDescriptorPoolTestParams(numIterationsHigh));
296 addFunctionCase(descriptorPoolTests.get(),
297 "repeated_free_reset_short",
298 "Test 2 cycles of vkAllocateDescriptorSets, vkFreeDescriptorSets and vkResetDescriptorPool (should pass)",
299 resetDescriptorPoolTest, ResetDescriptorPoolTestParams(2U, true));
300 addFunctionCase(descriptorPoolTests.get(),
301 "repeated_free_reset_long",
302 "Test many cycles of vkAllocateDescriptorSets, vkFreeDescriptorSets and vkResetDescriptorPool",
303 resetDescriptorPoolTest, ResetDescriptorPoolTestParams(numIterationsHigh, true));
304 addFunctionCase(descriptorPoolTests.get(),
305 "out_of_pool_memory",
306 "Test that when we run out of descriptors a correct error code is returned",
307 outOfPoolMemoryTest);
309 return descriptorPoolTests.release();