/*------------------------------------------------------------------------- * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2016 The Khronos Group Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Null handle tests *//*--------------------------------------------------------------------*/ #include "vktApiNullHandleTests.hpp" #include "vktTestCaseUtil.hpp" #include "vktTestGroupUtil.hpp" #include "vkDefs.hpp" #include "vkRef.hpp" #include "vkRefUtil.hpp" #include "vkAllocationCallbackUtil.hpp" namespace vkt { namespace api { namespace { using namespace vk; inline void release (Context& context, VkBuffer buffer, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyBuffer(context.getDevice(), buffer, pAllocator); } inline void release (Context& context, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyBufferView(context.getDevice(), bufferView, pAllocator); } inline void release (Context& context, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyCommandPool(context.getDevice(), commandPool, pAllocator); } inline void release (Context& context, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyDescriptorPool(context.getDevice(), descriptorPool, pAllocator); } inline void release (Context& context, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyDescriptorSetLayout(context.getDevice(), descriptorSetLayout, pAllocator); } inline void release (Context& context, VkDevice device, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyDevice(device, pAllocator); } inline void release (Context& context, VkEvent event, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyEvent(context.getDevice(), event, pAllocator); } inline void release (Context& context, VkFence fence, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyFence(context.getDevice(), fence, pAllocator); } inline void release (Context& context, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyFramebuffer(context.getDevice(), framebuffer, pAllocator); } inline void release (Context& context, VkImage image, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyImage(context.getDevice(), image, pAllocator); } inline void release (Context& context, VkImageView imageView, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyImageView(context.getDevice(), imageView, pAllocator); } inline void release (Context& context, VkInstance instance, const VkAllocationCallbacks* pAllocator) { context.getInstanceInterface().destroyInstance(instance, pAllocator); } inline void release (Context& context, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyPipeline(context.getDevice(), pipeline, pAllocator); } inline void release (Context& context, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyPipelineCache(context.getDevice(), pipelineCache, pAllocator); } inline void release (Context& context, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyPipelineLayout(context.getDevice(), pipelineLayout, pAllocator); } inline void release (Context& context, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyQueryPool(context.getDevice(), queryPool, pAllocator); } inline void release (Context& context, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyRenderPass(context.getDevice(), renderPass, pAllocator); } inline void release (Context& context, VkSampler sampler, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroySampler(context.getDevice(), sampler, pAllocator); } inline void release (Context& context, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroySemaphore(context.getDevice(), semaphore, pAllocator); } inline void release (Context& context, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().destroyShaderModule(context.getDevice(), shaderModule, pAllocator); } inline void release (Context& context, VkDevice device, VkCommandPool cmdPool, deUint32 numCmdBuffers, const VkCommandBuffer* pCmdBuffers) { DE_ASSERT(device != DE_NULL); DE_ASSERT(cmdPool != DE_NULL); DE_ASSERT(numCmdBuffers > 0u); context.getDeviceInterface().freeCommandBuffers(device, cmdPool, numCmdBuffers, pCmdBuffers); } inline void release (Context& context, VkDevice device, VkDescriptorPool descriptorPool, deUint32 numDescriptorSets, const VkDescriptorSet* pDescriptorSets) { DE_ASSERT(device != DE_NULL); DE_ASSERT(descriptorPool != DE_NULL); DE_ASSERT(numDescriptorSets > 0u); context.getDeviceInterface().freeDescriptorSets(device, descriptorPool, numDescriptorSets, pDescriptorSets); } inline void release (Context& context, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator) { context.getDeviceInterface().freeMemory(context.getDevice(), memory, pAllocator); } tcu::TestStatus reportStatus (const bool success) { if (success) return tcu::TestStatus::pass("OK: no observable change"); else return tcu::TestStatus::fail("Implementation allocated/freed the memory"); } template tcu::TestStatus test (Context& context) { const Object nullHandle = DE_NULL; const VkAllocationCallbacks* pNullAllocator = DE_NULL; AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u); // Implementation should silently ignore a delete/free of a NULL handle. release(context, nullHandle, pNullAllocator); release(context, nullHandle, recordingAllocator.getCallbacks()); return reportStatus(recordingAllocator.getNumRecords() == 0); } template<> tcu::TestStatus test (Context& context) { const DeviceInterface& vk = context.getDeviceInterface(); const VkDevice device = context.getDevice(); const deUint32 queueFamilyIndex = context.getUniversalQueueFamilyIndex(); const VkCommandPoolCreateInfo cmdPoolCreateInfo = { VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, // VkCommandPoolCreateFlags flags; queueFamilyIndex, // uint32_t queueFamilyIndex; }; const VkCommandBuffer pNullHandles[] = { DE_NULL, DE_NULL, DE_NULL }; const deUint32 numHandles = static_cast(DE_LENGTH_OF_ARRAY(pNullHandles)); // Default allocator { const Unique cmdPool (createCommandPool(vk, device, &cmdPoolCreateInfo)); release(context, device, *cmdPool, numHandles, pNullHandles); } // Custom allocator { AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u); const Unique cmdPool (createCommandPool(vk, device, &cmdPoolCreateInfo, recordingAllocator.getCallbacks())); const std::size_t numInitialRecords = recordingAllocator.getNumRecords(); release(context, device, *cmdPool, numHandles, pNullHandles); return reportStatus(numInitialRecords == recordingAllocator.getNumRecords()); } } template<> tcu::TestStatus test (Context& context) { const DeviceInterface& vk = context.getDeviceInterface(); const VkDevice device = context.getDevice(); const VkDescriptorPoolSize pPoolSizes[] = { // type, descriptorCount { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u }, // arbitrary values { VK_DESCRIPTOR_TYPE_SAMPLER, 1u }, { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 3u }, }; const VkDescriptorPoolCreateInfo descriptorPoolCreateInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags flags; 2u, // uint32_t maxSets; static_cast(DE_LENGTH_OF_ARRAY(pPoolSizes)), // uint32_t poolSizeCount; pPoolSizes, // const VkDescriptorPoolSize* pPoolSizes; }; const VkDescriptorSet pNullHandles[] = { DE_NULL, DE_NULL, DE_NULL }; const deUint32 numHandles = static_cast(DE_LENGTH_OF_ARRAY(pNullHandles)); // Default allocator { const Unique descriptorPool (createDescriptorPool(vk, device, &descriptorPoolCreateInfo)); release(context, device, *descriptorPool, numHandles, pNullHandles); } // Custom allocator { AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u); const Unique descriptorPool (createDescriptorPool(vk, device, &descriptorPoolCreateInfo, recordingAllocator.getCallbacks())); const std::size_t numInitialRecords = recordingAllocator.getNumRecords(); release(context, device, *descriptorPool, numHandles, pNullHandles); return reportStatus(numInitialRecords == recordingAllocator.getNumRecords()); } } void addTestsToGroup (tcu::TestCaseGroup* group) { addFunctionCase(group, "destroy_buffer", "", test); addFunctionCase(group, "destroy_buffer_view", "", test); addFunctionCase(group, "destroy_command_pool", "", test); addFunctionCase(group, "destroy_descriptor_pool", "", test); addFunctionCase(group, "destroy_descriptor_set_layout", "", test); addFunctionCase(group, "destroy_device", "", test); addFunctionCase(group, "destroy_event", "", test); addFunctionCase(group, "destroy_fence", "", test); addFunctionCase(group, "destroy_framebuffer", "", test); addFunctionCase(group, "destroy_image", "", test); addFunctionCase(group, "destroy_image_view", "", test); addFunctionCase(group, "destroy_instance", "", test); addFunctionCase(group, "destroy_pipeline", "", test); addFunctionCase(group, "destroy_pipeline_cache", "", test); addFunctionCase(group, "destroy_pipeline_layout", "", test); addFunctionCase(group, "destroy_query_pool", "", test); addFunctionCase(group, "destroy_render_pass", "", test); addFunctionCase(group, "destroy_sampler", "", test); addFunctionCase(group, "destroy_semaphore", "", test); addFunctionCase(group, "destroy_shader_module", "", test); addFunctionCase(group, "free_command_buffers", "", test); addFunctionCase(group, "free_descriptor_sets", "", test); addFunctionCase(group, "free_memory", "", test); } } // anonymous tcu::TestCaseGroup* createNullHandleTests (tcu::TestContext& testCtx) { return createTestGroup(testCtx, "null_handle", "Destroying/freeing a VK_NULL_HANDLE should be silently ignored", addTestsToGroup); } } // api } // vkt