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
33namespace vkt
34{
35namespace api
36{
37namespace
38{
39
40using namespace vk;
41
42inline void release (Context& context, VkBuffer buffer, const VkAllocationCallbacks* pAllocator)
43{
44	context.getDeviceInterface().destroyBuffer(context.getDevice(), buffer, pAllocator);
45}
46
47inline void release (Context& context, VkBufferView bufferView, const VkAllocationCallbacks* pAllocator)
48{
49	context.getDeviceInterface().destroyBufferView(context.getDevice(), bufferView, pAllocator);
50}
51
52#ifndef CTS_USES_VULKANSC
53inline void release (Context& context, VkCommandPool commandPool, const VkAllocationCallbacks* pAllocator)
54{
55	context.getDeviceInterface().destroyCommandPool(context.getDevice(), commandPool, pAllocator);
56}
57
58inline void release (Context& context, VkDescriptorPool descriptorPool, const VkAllocationCallbacks* pAllocator)
59{
60	context.getDeviceInterface().destroyDescriptorPool(context.getDevice(), descriptorPool, pAllocator);
61}
62#endif // CTS_USES_VULKANSC
63
64inline void release (Context& context, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks* pAllocator)
65{
66	context.getDeviceInterface().destroyDescriptorSetLayout(context.getDevice(), descriptorSetLayout, pAllocator);
67}
68
69inline void release (Context& context, VkDevice device, const VkAllocationCallbacks* pAllocator)
70{
71	context.getDeviceInterface().destroyDevice(device, pAllocator);
72}
73
74inline void release (Context& context, VkEvent event, const VkAllocationCallbacks* pAllocator)
75{
76	context.getDeviceInterface().destroyEvent(context.getDevice(), event, pAllocator);
77}
78
79inline void release (Context& context, VkFence fence, const VkAllocationCallbacks* pAllocator)
80{
81	context.getDeviceInterface().destroyFence(context.getDevice(), fence, pAllocator);
82}
83
84inline void release (Context& context, VkFramebuffer framebuffer, const VkAllocationCallbacks* pAllocator)
85{
86	context.getDeviceInterface().destroyFramebuffer(context.getDevice(), framebuffer, pAllocator);
87}
88
89inline void release (Context& context, VkImage image, const VkAllocationCallbacks* pAllocator)
90{
91	context.getDeviceInterface().destroyImage(context.getDevice(), image, pAllocator);
92}
93
94inline void release (Context& context, VkImageView imageView, const VkAllocationCallbacks* pAllocator)
95{
96	context.getDeviceInterface().destroyImageView(context.getDevice(), imageView, pAllocator);
97}
98
99inline void release (Context& context, VkInstance instance, const VkAllocationCallbacks* pAllocator)
100{
101	context.getInstanceInterface().destroyInstance(instance, pAllocator);
102}
103
104inline void release (Context& context, VkPipeline pipeline, const VkAllocationCallbacks* pAllocator)
105{
106	context.getDeviceInterface().destroyPipeline(context.getDevice(), pipeline, pAllocator);
107}
108
109inline void release (Context& context, VkPipelineCache pipelineCache, const VkAllocationCallbacks* pAllocator)
110{
111	context.getDeviceInterface().destroyPipelineCache(context.getDevice(), pipelineCache, pAllocator);
112}
113
114inline void release (Context& context, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks* pAllocator)
115{
116	context.getDeviceInterface().destroyPipelineLayout(context.getDevice(), pipelineLayout, pAllocator);
117}
118
119#ifndef CTS_USES_VULKANSC
120inline void release (Context& context, VkQueryPool queryPool, const VkAllocationCallbacks* pAllocator)
121{
122	context.getDeviceInterface().destroyQueryPool(context.getDevice(), queryPool, pAllocator);
123}
124#endif // CTS_USES_VULKANSC
125
126inline void release (Context& context, VkRenderPass renderPass, const VkAllocationCallbacks* pAllocator)
127{
128	context.getDeviceInterface().destroyRenderPass(context.getDevice(), renderPass, pAllocator);
129}
130
131inline void release (Context& context, VkSampler sampler, const VkAllocationCallbacks* pAllocator)
132{
133	context.getDeviceInterface().destroySampler(context.getDevice(), sampler, pAllocator);
134}
135
136inline void release (Context& context, VkSemaphore semaphore, const VkAllocationCallbacks* pAllocator)
137{
138	context.getDeviceInterface().destroySemaphore(context.getDevice(), semaphore, pAllocator);
139}
140
141inline void release (Context& context, VkShaderModule shaderModule, const VkAllocationCallbacks* pAllocator)
142{
143#ifndef CTS_USES_VULKANSC
144	context.getDeviceInterface().destroyShaderModule(context.getDevice(), shaderModule, pAllocator);
145#else
146	DE_UNREF(context);
147	DE_UNREF(shaderModule);
148	DE_UNREF(pAllocator);
149#endif // CTS_USES_VULKANSC
150}
151
152inline void release (Context& context, VkDevice device, VkCommandPool cmdPool, deUint32 numCmdBuffers, const VkCommandBuffer* pCmdBuffers)
153{
154	DE_ASSERT(device		!= DE_NULL);
155	DE_ASSERT(cmdPool		!= DE_NULL);
156	DE_ASSERT(numCmdBuffers	>  0u);
157	context.getDeviceInterface().freeCommandBuffers(device, cmdPool, numCmdBuffers, pCmdBuffers);
158}
159
160inline void release (Context& context, VkDevice device, VkDescriptorPool descriptorPool, deUint32 numDescriptorSets, const VkDescriptorSet* pDescriptorSets)
161{
162	DE_ASSERT(device			!= DE_NULL);
163	DE_ASSERT(descriptorPool	!= DE_NULL);
164	DE_ASSERT(numDescriptorSets	>  0u);
165	context.getDeviceInterface().freeDescriptorSets(device, descriptorPool, numDescriptorSets, pDescriptorSets);
166}
167
168#ifndef CTS_USES_VULKANSC
169inline void release (Context& context, VkDeviceMemory memory, const VkAllocationCallbacks* pAllocator)
170{
171	context.getDeviceInterface().freeMemory(context.getDevice(), memory, pAllocator);
172}
173#endif // CTS_USES_VULKANSC
174
175tcu::TestStatus reportStatus (const bool success)
176{
177	if (success)
178		return tcu::TestStatus::pass("OK: no observable change");
179	else
180		return tcu::TestStatus::fail("Implementation allocated/freed the memory");
181}
182
183template<typename Object>
184tcu::TestStatus test (Context& context)
185{
186	const Object					nullHandle			= DE_NULL;
187	const VkAllocationCallbacks*	pNullAllocator		= DE_NULL;
188
189#ifndef CTS_USES_VULKANSC
190	AllocationCallbackRecorder		recordingAllocator	(getSystemAllocator(), 1u);
191#endif // CTS_USES_VULKANSC
192
193	// Implementation should silently ignore a delete/free of a NULL handle.
194
195	release(context, nullHandle, pNullAllocator);
196#ifndef CTS_USES_VULKANSC
197	// In Vulkan SC VkAllocationCallbacks must be NULL
198	release(context, nullHandle, recordingAllocator.getCallbacks());
199	return reportStatus(recordingAllocator.getNumRecords() == 0);
200#else
201	return reportStatus(true);
202#endif // CTS_USES_VULKANSC
203}
204
205template<>
206tcu::TestStatus test<VkCommandBuffer> (Context& context)
207{
208	const DeviceInterface&			vk					= context.getDeviceInterface();
209	const VkDevice					device				= context.getDevice();
210	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
211
212	const VkCommandPoolCreateInfo	cmdPoolCreateInfo =
213	{
214		VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,		// VkStructureType             sType;
215		DE_NULL,										// const void*                 pNext;
216		VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,			// VkCommandPoolCreateFlags    flags;
217		queueFamilyIndex,								// uint32_t                    queueFamilyIndex;
218	};
219
220	const VkCommandBuffer			pNullHandles[]		= { DE_NULL, DE_NULL, DE_NULL };
221	const deUint32					numHandles			= static_cast<deUint32>(DE_LENGTH_OF_ARRAY(pNullHandles));
222
223	// Default allocator
224	{
225		const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, &cmdPoolCreateInfo));
226
227		release(context, device, *cmdPool, numHandles, pNullHandles);
228	}
229
230	// Custom allocator
231#ifndef CTS_USES_VULKANSC
232	{
233		AllocationCallbackRecorder		recordingAllocator	(getSystemAllocator(), 1u);
234		const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, &cmdPoolCreateInfo, recordingAllocator.getCallbacks()));
235		const std::size_t				numInitialRecords	= recordingAllocator.getNumRecords();
236
237		release(context, device, *cmdPool, numHandles, pNullHandles);
238
239		return reportStatus(numInitialRecords == recordingAllocator.getNumRecords());
240	}
241#else
242	return reportStatus(true);
243#endif // CTS_USES_VULKANSC
244}
245
246void checkSupportFreeDescriptorSets (Context& context)
247{
248#ifdef CTS_USES_VULKANSC
249	if(context.getDeviceVulkanSC10Properties().recycleDescriptorSetMemory == VK_FALSE )
250		TCU_THROW(NotSupportedError, "vkFreeDescriptorSets not supported");
251#else
252	DE_UNREF(context);
253#endif // CTS_USES_VULKANSC
254}
255
256template<>
257tcu::TestStatus test<VkDescriptorSet> (Context& context)
258{
259	const DeviceInterface&				vk					= context.getDeviceInterface();
260	const VkDevice						device				= context.getDevice();
261
262	const VkDescriptorPoolSize			pPoolSizes[] =
263	{
264		// type, descriptorCount
265		{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,	2u },	// arbitrary values
266		{ VK_DESCRIPTOR_TYPE_SAMPLER,			1u },
267		{ VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,		3u },
268	};
269	const VkDescriptorPoolCreateInfo	descriptorPoolCreateInfo =
270	{
271		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,				// VkStructureType                sType;
272		DE_NULL,													// const void*                    pNext;
273		VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,			// VkDescriptorPoolCreateFlags    flags;
274		2u,															// uint32_t                       maxSets;
275		static_cast<deUint32>(DE_LENGTH_OF_ARRAY(pPoolSizes)),		// uint32_t                       poolSizeCount;
276		pPoolSizes,													// const VkDescriptorPoolSize*    pPoolSizes;
277	};
278
279	const VkDescriptorSet				pNullHandles[]	= { DE_NULL, DE_NULL, DE_NULL };
280	const deUint32						numHandles		= static_cast<deUint32>(DE_LENGTH_OF_ARRAY(pNullHandles));
281
282	// Default allocator
283	{
284		const Unique<VkDescriptorPool>	descriptorPool		(createDescriptorPool(vk, device, &descriptorPoolCreateInfo));
285
286		release(context, device, *descriptorPool, numHandles, pNullHandles);
287	}
288
289	// Custom allocator
290#ifndef CTS_USES_VULKANSC
291	{
292		AllocationCallbackRecorder		recordingAllocator	(getSystemAllocator(), 1u);
293		const Unique<VkDescriptorPool>	descriptorPool		(createDescriptorPool(vk, device, &descriptorPoolCreateInfo, recordingAllocator.getCallbacks()));
294		const std::size_t				numInitialRecords	= recordingAllocator.getNumRecords();
295
296		release(context, device, *descriptorPool, numHandles, pNullHandles);
297
298		return reportStatus(numInitialRecords == recordingAllocator.getNumRecords());
299	}
300#else
301	return reportStatus(true);
302#endif // CTS_USES_VULKANSC
303}
304
305void checkEventSupport (Context& context)
306{
307#ifndef CTS_USES_VULKANSC
308	if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") && !context.getPortabilitySubsetFeatures().events)
309		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Events are not supported by this implementation");
310#else
311	DE_UNREF(context);
312#endif // CTS_USES_VULKANSC
313}
314
315void addTestsToGroup (tcu::TestCaseGroup* group)
316{
317	addFunctionCase(group,	"destroy_buffer", test<VkBuffer>);
318	addFunctionCase(group,	"destroy_buffer_view", test<VkBufferView>);
319#ifndef CTS_USES_VULKANSC
320	// Removed from Vulkan SC test set: vkDestroyCommandPool and vkDestroyDescriptorPool command do not exist in Vulkan SC
321	addFunctionCase(group,	"destroy_command_pool", test<VkCommandPool>);
322	addFunctionCase(group,	"destroy_descriptor_pool", test<VkDescriptorPool>);
323#endif // CTS_USES_VULKANSC
324	addFunctionCase(group,	"destroy_descriptor_set_layout", test<VkDescriptorSetLayout>);
325	addFunctionCase(group,	"destroy_device", test<VkDevice>);
326	addFunctionCase(group,	"destroy_event", checkEventSupport, test<VkEvent>);
327	addFunctionCase(group,	"destroy_fence", test<VkFence>);
328	addFunctionCase(group,	"destroy_framebuffer", test<VkFramebuffer>);
329	addFunctionCase(group,	"destroy_image", test<VkImage>);
330	addFunctionCase(group,	"destroy_image_view", test<VkImageView>);
331	addFunctionCase(group,	"destroy_instance", test<VkInstance>);
332	addFunctionCase(group,	"destroy_pipeline", test<VkPipeline>);
333	addFunctionCase(group,	"destroy_pipeline_cache", test<VkPipelineCache>);
334	addFunctionCase(group,	"destroy_pipeline_layout", test<VkPipelineLayout>);
335#ifndef CTS_USES_VULKANSC
336	// Removed from Vulkan SC test set: vkDestroyQueryPool command does not exist in Vulkan SC
337	addFunctionCase(group,	"destroy_query_pool", test<VkQueryPool>);
338#endif // CTS_USES_VULKANSC
339	addFunctionCase(group,	"destroy_render_pass", test<VkRenderPass>);
340	addFunctionCase(group,	"destroy_sampler", test<VkSampler>);
341	addFunctionCase(group,	"destroy_semaphore", test<VkSemaphore>);
342	addFunctionCase(group,	"destroy_shader_module", test<VkShaderModule>);
343	addFunctionCase(group,	"free_command_buffers", test<VkCommandBuffer>);
344	addFunctionCase(group,	"free_descriptor_sets", checkSupportFreeDescriptorSets, test<VkDescriptorSet>);
345#ifndef CTS_USES_VULKANSC
346	// Removed from Vulkan SC test set: vkFreeMemory command does not exist in Vulkan SC
347	addFunctionCase(group,	"free_memory", test<VkDeviceMemory>);
348#endif // CTS_USES_VULKANSC
349}
350
351} // anonymous
352
353tcu::TestCaseGroup* createNullHandleTests (tcu::TestContext& testCtx)
354{
355	// Destroying/freeing a VK_NULL_HANDLE should be silently ignored
356	return createTestGroup(testCtx, "null_handle", addTestsToGroup);
357}
358
359} // api
360} // vkt
361