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