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 45namespace vkt 46{ 47namespace api 48{ 49 50namespace 51{ 52 53using namespace std; 54using namespace vk; 55 56struct ResetDescriptorPoolTestParams 57{ 58 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 67void 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 78tcu::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 177tcu::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 296tcu::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 350tcu::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")); 356 357 // Test 2 cycles of vkAllocateDescriptorSets and vkResetDescriptorPool (should pass) 358 addFunctionCase(descriptorPoolTests.get(), 359 "repeated_reset_short", 360 checkSupportFreeDescriptorSets, 361 resetDescriptorPoolTest, ResetDescriptorPoolTestParams(2U)); 362 // Test many cycles of vkAllocateDescriptorSets and vkResetDescriptorPool 363 addFunctionCase(descriptorPoolTests.get(), 364 "repeated_reset_long", 365 checkSupportFreeDescriptorSets, 366 resetDescriptorPoolTest, ResetDescriptorPoolTestParams(numIterationsHigh)); 367 // Test 2 cycles of vkAllocateDescriptorSets, vkFreeDescriptorSets and vkResetDescriptorPool (should pass) 368 addFunctionCase(descriptorPoolTests.get(), 369 "repeated_free_reset_short", 370 checkSupportFreeDescriptorSets, 371 resetDescriptorPoolTest, ResetDescriptorPoolTestParams(2U, true)); 372 // Test many cycles of vkAllocateDescriptorSets, vkFreeDescriptorSets and vkResetDescriptorPool 373 addFunctionCase(descriptorPoolTests.get(), 374 "repeated_free_reset_long", 375 checkSupportFreeDescriptorSets, 376 resetDescriptorPoolTest, ResetDescriptorPoolTestParams(numIterationsHigh, true)); 377 // Test that when we run out of descriptors a correct error code is returned 378 addFunctionCase(descriptorPoolTests.get(), 379 "out_of_pool_memory", 380 outOfPoolMemoryTest); 381 // Test a descriptor pool object can be created with zero pools without error or crash 382 addFunctionCase(descriptorPoolTests.get(), 383 "zero_pool_size_count", 384 zeroPoolSizeCount); 385 386 return descriptorPoolTests.release(); 387} 388 389} // api 390} // vkt 391