1 /*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2016 The Khronos Group 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 Null handle tests 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktApiNullHandleTests.hpp" 25 #include "vktTestCaseUtil.hpp" 26 #include "vktTestGroupUtil.hpp" 27 28 #include "vkDefs.hpp" 29 #include "vkRef.hpp" 30 #include "vkRefUtil.hpp" 31 #include "vkAllocationCallbackUtil.hpp" 32 33 namespace vkt 34 { 35 namespace api 36 { 37 namespace 38 { 39 40 using namespace vk; 41 42 inline void release (Context& context, VkBuffer buffer, const VkAllocationCallbacks* pAllocator) 43 { 44 context.getDeviceInterface().destroyBuffer(context.getDevice(), buffer, pAllocator); 45 } 46 47 inline void release (Context& context, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator) 48 { 49 context.getDeviceInterface().destroyBufferView(context.getDevice(), bufferView, pAllocator); 50 } 51 52 inline void release (Context& context, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator) 53 { 54 context.getDeviceInterface().destroyCommandPool(context.getDevice(), commandPool, pAllocator); 55 } 56 57 inline void release (Context& context, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator) 58 { 59 context.getDeviceInterface().destroyDescriptorPool(context.getDevice(), descriptorPool, pAllocator); 60 } 61 62 inline void release (Context& context, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator) 63 { 64 context.getDeviceInterface().destroyDescriptorSetLayout(context.getDevice(), descriptorSetLayout, pAllocator); 65 } 66 67 inline void release (Context& context, VkDevice device, const VkAllocationCallbacks* pAllocator) 68 { 69 context.getDeviceInterface().destroyDevice(device, pAllocator); 70 } 71 72 inline void release (Context& context, VkEvent event, const VkAllocationCallbacks* pAllocator) 73 { 74 context.getDeviceInterface().destroyEvent(context.getDevice(), event, pAllocator); 75 } 76 77 inline void release (Context& context, VkFence fence, const VkAllocationCallbacks* pAllocator) 78 { 79 context.getDeviceInterface().destroyFence(context.getDevice(), fence, pAllocator); 80 } 81 82 inline void release (Context& context, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator) 83 { 84 context.getDeviceInterface().destroyFramebuffer(context.getDevice(), framebuffer, pAllocator); 85 } 86 87 inline void release (Context& context, VkImage image, const VkAllocationCallbacks* pAllocator) 88 { 89 context.getDeviceInterface().destroyImage(context.getDevice(), image, pAllocator); 90 } 91 92 inline void release (Context& context, VkImageView imageView, const VkAllocationCallbacks* pAllocator) 93 { 94 context.getDeviceInterface().destroyImageView(context.getDevice(), imageView, pAllocator); 95 } 96 97 inline void release (Context& context, VkInstance instance, const VkAllocationCallbacks* pAllocator) 98 { 99 context.getInstanceInterface().destroyInstance(instance, pAllocator); 100 } 101 102 inline void release (Context& context, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator) 103 { 104 context.getDeviceInterface().destroyPipeline(context.getDevice(), pipeline, pAllocator); 105 } 106 107 inline void release (Context& context, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator) 108 { 109 context.getDeviceInterface().destroyPipelineCache(context.getDevice(), pipelineCache, pAllocator); 110 } 111 112 inline void release (Context& context, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator) 113 { 114 context.getDeviceInterface().destroyPipelineLayout(context.getDevice(), pipelineLayout, pAllocator); 115 } 116 117 inline void release (Context& context, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator) 118 { 119 context.getDeviceInterface().destroyQueryPool(context.getDevice(), queryPool, pAllocator); 120 } 121 122 inline void release (Context& context, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator) 123 { 124 context.getDeviceInterface().destroyRenderPass(context.getDevice(), renderPass, pAllocator); 125 } 126 127 inline void release (Context& context, VkSampler sampler, const VkAllocationCallbacks* pAllocator) 128 { 129 context.getDeviceInterface().destroySampler(context.getDevice(), sampler, pAllocator); 130 } 131 132 inline void release (Context& context, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator) 133 { 134 context.getDeviceInterface().destroySemaphore(context.getDevice(), semaphore, pAllocator); 135 } 136 137 inline void release (Context& context, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator) 138 { 139 context.getDeviceInterface().destroyShaderModule(context.getDevice(), shaderModule, pAllocator); 140 } 141 142 inline void release (Context& context, VkDevice device, VkCommandPool cmdPool, deUint32 numCmdBuffers, const VkCommandBuffer* pCmdBuffers) 143 { 144 DE_ASSERT(device != DE_NULL); 145 DE_ASSERT(cmdPool != DE_NULL); 146 DE_ASSERT(numCmdBuffers > 0u); 147 context.getDeviceInterface().freeCommandBuffers(device, cmdPool, numCmdBuffers, pCmdBuffers); 148 } 149 150 inline void release (Context& context, VkDevice device, VkDescriptorPool descriptorPool, deUint32 numDescriptorSets, const VkDescriptorSet* pDescriptorSets) 151 { 152 DE_ASSERT(device != DE_NULL); 153 DE_ASSERT(descriptorPool != DE_NULL); 154 DE_ASSERT(numDescriptorSets > 0u); 155 context.getDeviceInterface().freeDescriptorSets(device, descriptorPool, numDescriptorSets, pDescriptorSets); 156 } 157 158 inline void release (Context& context, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator) 159 { 160 context.getDeviceInterface().freeMemory(context.getDevice(), memory, pAllocator); 161 } 162 163 tcu::TestStatus reportStatus (const bool success) 164 { 165 if (success) 166 return tcu::TestStatus::pass("OK: no observable change"); 167 else 168 return tcu::TestStatus::fail("Implementation allocated/freed the memory"); 169 } 170 171 template<typename Object> 172 tcu::TestStatus test (Context& context) 173 { 174 const Object nullHandle = DE_NULL; 175 const VkAllocationCallbacks* pNullAllocator = DE_NULL; 176 AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u); 177 178 // Implementation should silently ignore a delete/free of a NULL handle. 179 180 release(context, nullHandle, pNullAllocator); 181 release(context, nullHandle, recordingAllocator.getCallbacks()); 182 183 return reportStatus(recordingAllocator.getNumRecords() == 0); 184 } 185 186 template<> 187 tcu::TestStatus test<VkCommandBuffer> (Context& context) 188 { 189 const DeviceInterface& vk = context.getDeviceInterface(); 190 const VkDevice device = context.getDevice(); 191 const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); 192 193 const VkCommandPoolCreateInfo cmdPoolCreateInfo = 194 { 195 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; 196 DE_NULL, // const void* pNext; 197 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags; 198 queueFamilyIndex, // uint32_t queueFamilyIndex; 199 }; 200 201 const VkCommandBuffer pNullHandles[] = { DE_NULL, DE_NULL, DE_NULL }; 202 const deUint32 numHandles = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(pNullHandles)); 203 204 // Default allocator 205 { 206 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, &cmdPoolCreateInfo)); 207 208 release(context, device, *cmdPool, numHandles, pNullHandles); 209 } 210 211 // Custom allocator 212 { 213 AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u); 214 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, &cmdPoolCreateInfo, recordingAllocator.getCallbacks())); 215 const std::size_t numInitialRecords = recordingAllocator.getNumRecords(); 216 217 release(context, device, *cmdPool, numHandles, pNullHandles); 218 219 return reportStatus(numInitialRecords == recordingAllocator.getNumRecords()); 220 } 221 } 222 223 template<> 224 tcu::TestStatus test<VkDescriptorSet> (Context& context) 225 { 226 const DeviceInterface& vk = context.getDeviceInterface(); 227 const VkDevice device = context.getDevice(); 228 229 const VkDescriptorPoolSize pPoolSizes[] = 230 { 231 // type, descriptorCount 232 { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u }, // arbitrary values 233 { VK_DESCRIPTOR_TYPE_SAMPLER, 1u }, 234 { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 3u }, 235 }; 236 const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = 237 { 238 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType; 239 DE_NULL, // const void* pNext; 240 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags flags; 241 2u, // uint32_t maxSets; 242 static_cast<deUint32>(DE_LENGTH_OF_ARRAY(pPoolSizes)), // uint32_t poolSizeCount; 243 pPoolSizes, // const VkDescriptorPoolSize* pPoolSizes; 244 }; 245 246 const VkDescriptorSet pNullHandles[] = { DE_NULL, DE_NULL, DE_NULL }; 247 const deUint32 numHandles = static_cast<deUint32>(DE_LENGTH_OF_ARRAY(pNullHandles)); 248 249 // Default allocator 250 { 251 const Unique<VkDescriptorPool> descriptorPool (createDescriptorPool(vk, device, &descriptorPoolCreateInfo)); 252 253 release(context, device, *descriptorPool, numHandles, pNullHandles); 254 } 255 256 // Custom allocator 257 { 258 AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u); 259 const Unique<VkDescriptorPool> descriptorPool (createDescriptorPool(vk, device, &descriptorPoolCreateInfo, recordingAllocator.getCallbacks())); 260 const std::size_t numInitialRecords = recordingAllocator.getNumRecords(); 261 262 release(context, device, *descriptorPool, numHandles, pNullHandles); 263 264 return reportStatus(numInitialRecords == recordingAllocator.getNumRecords()); 265 } 266 } 267 268 void addTestsToGroup (tcu::TestCaseGroup* group) 269 { 270 addFunctionCase(group, "destroy_buffer", "", test<VkBuffer>); 271 addFunctionCase(group, "destroy_buffer_view", "", test<VkBufferView>); 272 addFunctionCase(group, "destroy_command_pool", "", test<VkCommandPool>); 273 addFunctionCase(group, "destroy_descriptor_pool", "", test<VkDescriptorPool>); 274 addFunctionCase(group, "destroy_descriptor_set_layout", "", test<VkDescriptorSetLayout>); 275 addFunctionCase(group, "destroy_device", "", test<VkDevice>); 276 addFunctionCase(group, "destroy_event", "", test<VkEvent>); 277 addFunctionCase(group, "destroy_fence", "", test<VkFence>); 278 addFunctionCase(group, "destroy_framebuffer", "", test<VkFramebuffer>); 279 addFunctionCase(group, "destroy_image", "", test<VkImage>); 280 addFunctionCase(group, "destroy_image_view", "", test<VkImageView>); 281 addFunctionCase(group, "destroy_instance", "", test<VkInstance>); 282 addFunctionCase(group, "destroy_pipeline", "", test<VkPipeline>); 283 addFunctionCase(group, "destroy_pipeline_cache", "", test<VkPipelineCache>); 284 addFunctionCase(group, "destroy_pipeline_layout", "", test<VkPipelineLayout>); 285 addFunctionCase(group, "destroy_query_pool", "", test<VkQueryPool>); 286 addFunctionCase(group, "destroy_render_pass", "", test<VkRenderPass>); 287 addFunctionCase(group, "destroy_sampler", "", test<VkSampler>); 288 addFunctionCase(group, "destroy_semaphore", "", test<VkSemaphore>); 289 addFunctionCase(group, "destroy_shader_module", "", test<VkShaderModule>); 290 addFunctionCase(group, "free_command_buffers", "", test<VkCommandBuffer>); 291 addFunctionCase(group, "free_descriptor_sets", "", test<VkDescriptorSet>); 292 addFunctionCase(group, "free_memory", "", test<VkDeviceMemory>); 293 } 294 295 } // anonymous 296 297 tcu::TestCaseGroup* createNullHandleTests (tcu::TestContext& testCtx) 298 { 299 return createTestGroup(testCtx, "null_handle", "Destroying/freeing a VK_NULL_HANDLE should be silently ignored", addTestsToGroup); 300 } 301 302 } // api 303 } // vkt 304