xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/api/vktApiNullHandleTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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