blob: 99d5b7d479fbb54362a1d1793961e74110b94a2f [file] [log] [blame]
/*-------------------------------------------------------------------------
* 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