| /*------------------------------------------------------------------------- |
| * 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<typename Object> |
| 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<VkCommandBuffer> (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<deUint32>(DE_LENGTH_OF_ARRAY(pNullHandles)); |
| |
| // Default allocator |
| { |
| const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, &cmdPoolCreateInfo)); |
| |
| release(context, device, *cmdPool, numHandles, pNullHandles); |
| } |
| |
| // Custom allocator |
| { |
| AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u); |
| const Unique<VkCommandPool> 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<VkDescriptorSet> (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<deUint32>(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<deUint32>(DE_LENGTH_OF_ARRAY(pNullHandles)); |
| |
| // Default allocator |
| { |
| const Unique<VkDescriptorPool> descriptorPool (createDescriptorPool(vk, device, &descriptorPoolCreateInfo)); |
| |
| release(context, device, *descriptorPool, numHandles, pNullHandles); |
| } |
| |
| // Custom allocator |
| { |
| AllocationCallbackRecorder recordingAllocator (getSystemAllocator(), 1u); |
| const Unique<VkDescriptorPool> 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 checkEventSupport (Context& context) |
| { |
| if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events) |
| TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation"); |
| } |
| |
| void addTestsToGroup (tcu::TestCaseGroup* group) |
| { |
| addFunctionCase(group, "destroy_buffer", "", test<VkBuffer>); |
| addFunctionCase(group, "destroy_buffer_view", "", test<VkBufferView>); |
| addFunctionCase(group, "destroy_command_pool", "", test<VkCommandPool>); |
| addFunctionCase(group, "destroy_descriptor_pool", "", test<VkDescriptorPool>); |
| addFunctionCase(group, "destroy_descriptor_set_layout", "", test<VkDescriptorSetLayout>); |
| addFunctionCase(group, "destroy_device", "", test<VkDevice>); |
| addFunctionCase(group, "destroy_event", "", checkEventSupport, test<VkEvent>); |
| addFunctionCase(group, "destroy_fence", "", test<VkFence>); |
| addFunctionCase(group, "destroy_framebuffer", "", test<VkFramebuffer>); |
| addFunctionCase(group, "destroy_image", "", test<VkImage>); |
| addFunctionCase(group, "destroy_image_view", "", test<VkImageView>); |
| addFunctionCase(group, "destroy_instance", "", test<VkInstance>); |
| addFunctionCase(group, "destroy_pipeline", "", test<VkPipeline>); |
| addFunctionCase(group, "destroy_pipeline_cache", "", test<VkPipelineCache>); |
| addFunctionCase(group, "destroy_pipeline_layout", "", test<VkPipelineLayout>); |
| addFunctionCase(group, "destroy_query_pool", "", test<VkQueryPool>); |
| addFunctionCase(group, "destroy_render_pass", "", test<VkRenderPass>); |
| addFunctionCase(group, "destroy_sampler", "", test<VkSampler>); |
| addFunctionCase(group, "destroy_semaphore", "", test<VkSemaphore>); |
| addFunctionCase(group, "destroy_shader_module", "", test<VkShaderModule>); |
| addFunctionCase(group, "free_command_buffers", "", test<VkCommandBuffer>); |
| addFunctionCase(group, "free_descriptor_sets", "", test<VkDescriptorSet>); |
| addFunctionCase(group, "free_memory", "", test<VkDeviceMemory>); |
| } |
| |
| } // 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 |