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 
release(Context & context,VkBuffer buffer,const VkAllocationCallbacks * pAllocator)42 inline void release (Context& context, VkBuffer buffer, const VkAllocationCallbacks* pAllocator)
43 {
44 	context.getDeviceInterface().destroyBuffer(context.getDevice(), buffer, pAllocator);
45 }
46 
release(Context & context,VkBufferView bufferView,const VkAllocationCallbacks * pAllocator)47 inline void release (Context& context, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator)
48 {
49 	context.getDeviceInterface().destroyBufferView(context.getDevice(), bufferView, pAllocator);
50 }
51 
release(Context & context,VkCommandPool commandPool,const VkAllocationCallbacks * pAllocator)52 inline void release (Context& context, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator)
53 {
54 	context.getDeviceInterface().destroyCommandPool(context.getDevice(), commandPool, pAllocator);
55 }
56 
release(Context & context,VkDescriptorPool descriptorPool,const VkAllocationCallbacks * pAllocator)57 inline void release (Context& context, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator)
58 {
59 	context.getDeviceInterface().destroyDescriptorPool(context.getDevice(), descriptorPool, pAllocator);
60 }
61 
release(Context & context,VkDescriptorSetLayout descriptorSetLayout,const VkAllocationCallbacks * pAllocator)62 inline void release (Context& context, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator)
63 {
64 	context.getDeviceInterface().destroyDescriptorSetLayout(context.getDevice(), descriptorSetLayout, pAllocator);
65 }
66 
release(Context & context,VkDevice device,const VkAllocationCallbacks * pAllocator)67 inline void release (Context& context, VkDevice device, const VkAllocationCallbacks* pAllocator)
68 {
69 	context.getDeviceInterface().destroyDevice(device, pAllocator);
70 }
71 
release(Context & context,VkEvent event,const VkAllocationCallbacks * pAllocator)72 inline void release (Context& context, VkEvent event, const VkAllocationCallbacks* pAllocator)
73 {
74 	context.getDeviceInterface().destroyEvent(context.getDevice(), event, pAllocator);
75 }
76 
release(Context & context,VkFence fence,const VkAllocationCallbacks * pAllocator)77 inline void release (Context& context, VkFence fence, const VkAllocationCallbacks* pAllocator)
78 {
79 	context.getDeviceInterface().destroyFence(context.getDevice(), fence, pAllocator);
80 }
81 
release(Context & context,VkFramebuffer framebuffer,const VkAllocationCallbacks * pAllocator)82 inline void release (Context& context, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator)
83 {
84 	context.getDeviceInterface().destroyFramebuffer(context.getDevice(), framebuffer, pAllocator);
85 }
86 
release(Context & context,VkImage image,const VkAllocationCallbacks * pAllocator)87 inline void release (Context& context, VkImage image, const VkAllocationCallbacks* pAllocator)
88 {
89 	context.getDeviceInterface().destroyImage(context.getDevice(), image, pAllocator);
90 }
91 
release(Context & context,VkImageView imageView,const VkAllocationCallbacks * pAllocator)92 inline void release (Context& context, VkImageView imageView, const VkAllocationCallbacks* pAllocator)
93 {
94 	context.getDeviceInterface().destroyImageView(context.getDevice(), imageView, pAllocator);
95 }
96 
release(Context & context,VkInstance instance,const VkAllocationCallbacks * pAllocator)97 inline void release (Context& context, VkInstance instance, const VkAllocationCallbacks* pAllocator)
98 {
99 	context.getInstanceInterface().destroyInstance(instance, pAllocator);
100 }
101 
release(Context & context,VkPipeline pipeline,const VkAllocationCallbacks * pAllocator)102 inline void release (Context& context, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator)
103 {
104 	context.getDeviceInterface().destroyPipeline(context.getDevice(), pipeline, pAllocator);
105 }
106 
release(Context & context,VkPipelineCache pipelineCache,const VkAllocationCallbacks * pAllocator)107 inline void release (Context& context, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator)
108 {
109 	context.getDeviceInterface().destroyPipelineCache(context.getDevice(), pipelineCache, pAllocator);
110 }
111 
release(Context & context,VkPipelineLayout pipelineLayout,const VkAllocationCallbacks * pAllocator)112 inline void release (Context& context, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator)
113 {
114 	context.getDeviceInterface().destroyPipelineLayout(context.getDevice(), pipelineLayout, pAllocator);
115 }
116 
release(Context & context,VkQueryPool queryPool,const VkAllocationCallbacks * pAllocator)117 inline void release (Context& context, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator)
118 {
119 	context.getDeviceInterface().destroyQueryPool(context.getDevice(), queryPool, pAllocator);
120 }
121 
release(Context & context,VkRenderPass renderPass,const VkAllocationCallbacks * pAllocator)122 inline void release (Context& context, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator)
123 {
124 	context.getDeviceInterface().destroyRenderPass(context.getDevice(), renderPass, pAllocator);
125 }
126 
release(Context & context,VkSampler sampler,const VkAllocationCallbacks * pAllocator)127 inline void release (Context& context, VkSampler sampler, const VkAllocationCallbacks* pAllocator)
128 {
129 	context.getDeviceInterface().destroySampler(context.getDevice(), sampler, pAllocator);
130 }
131 
release(Context & context,VkSemaphore semaphore,const VkAllocationCallbacks * pAllocator)132 inline void release (Context& context, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator)
133 {
134 	context.getDeviceInterface().destroySemaphore(context.getDevice(), semaphore, pAllocator);
135 }
136 
release(Context & context,VkShaderModule shaderModule,const VkAllocationCallbacks * pAllocator)137 inline void release (Context& context, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator)
138 {
139 	context.getDeviceInterface().destroyShaderModule(context.getDevice(), shaderModule, pAllocator);
140 }
141 
release(Context & context,VkDevice device,VkCommandPool cmdPool,deUint32 numCmdBuffers,const VkCommandBuffer * pCmdBuffers)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 
release(Context & context,VkDevice device,VkDescriptorPool descriptorPool,deUint32 numDescriptorSets,const VkDescriptorSet * pDescriptorSets)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 
release(Context & context,VkDeviceMemory memory,const VkAllocationCallbacks * pAllocator)158 inline void release (Context& context, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator)
159 {
160 	context.getDeviceInterface().freeMemory(context.getDevice(), memory, pAllocator);
161 }
162 
reportStatus(const bool success)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>
test(Context & context)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<>
test(Context & context)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<>
test(Context & context)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 
addTestsToGroup(tcu::TestCaseGroup * group)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 
createNullHandleTests(tcu::TestContext & testCtx)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