# Resource management

Let's see how resources get freed automatically, and when they aren't. First let's set the preference "LOG_DESTRUCTION" to "true" to see what's going on:

using Vulkan

Vulkan.set_preferences!("LOG_DESTRUCTION" => "true")

Now let's create a bunch of handles and see what happens when the GC runs:

function do_something()
instance = Instance([], [])
physical_devices = unwrap(enumerate_physical_devices(instance))
physical_device = first(physical_devices)
device = Device(physical_device, [DeviceQueueCreateInfo(0, [1.0])], [], [])

command_pool = CommandPool(device, 0)
buffers = unwrap(
allocate_command_buffers(
device,
CommandBufferAllocateInfo(command_pool, COMMAND_BUFFER_LEVEL_PRIMARY, 10),
),
)
# they won't be automatically freed individually
free_command_buffers(device, command_pool, buffers)
nothing
end

do_something()

# to force some finalizers to run
GC.gc()

Not all handles were destroyed upon finalization. In particular, the physical device and the buffers were not destroyed. That's because a physical device is not owned by the application, so you can't destroy it, and buffers must be freed in batches with free_command_buffers (as done above). See more information in Automatic finalization.

Note

Not all finalizers have run. In some cases (e.g. when a finalizer must be run to release resources), it may be preferable to run them directly. You can do this by calling finalize (exported from Base):

instance = Instance([], [])
finalize(instance)