[metal] Add option for strong resource reference in command buffers
diff --git a/experimental/metal/direct_command_buffer.m b/experimental/metal/direct_command_buffer.m
index 1ab3583..bfb6081 100644
--- a/experimental/metal/direct_command_buffer.m
+++ b/experimental/metal/direct_command_buffer.m
@@ -135,6 +135,7 @@
 iree_status_t iree_hal_metal_direct_command_buffer_create(
     iree_hal_device_t* device, iree_hal_command_buffer_mode_t mode,
     iree_hal_command_category_t command_categories, iree_host_size_t binding_capacity,
+    iree_hal_metal_command_buffer_resource_reference_mode_t resource_reference_mode,
     id<MTLCommandQueue> queue, iree_allocator_t host_allocator, iree_arena_block_pool_t* block_pool,
     iree_hal_metal_builtin_executable_t* builtin_executable,
     iree_hal_command_buffer_t** out_command_buffer) {
@@ -163,8 +164,13 @@
     @autoreleasepool {  // Use @autoreleasepool to trigger the autorelease within encoder creation.
       // We track resource lifetime by ourselves in IREE; so just do unretained references to
       // resources in Metal command buffer, which avoids overhead and gives better performance.
+      MTLCommandBufferDescriptor* descriptor = [MTLCommandBufferDescriptor new];  // +1
+      descriptor.retainedReferences =
+          resource_reference_mode == IREE_HAL_METAL_COMMAND_BUFFER_RESOURCE_REFERENCE_MODE_RETAINED;
+      descriptor.errorOptions = MTLCommandBufferErrorOptionNone;
       command_buffer->command_buffer =
-          [[queue commandBufferWithUnretainedReferences] retain];  // +1
+          [[queue commandBufferWithDescriptor:descriptor] retain];  // +1
+      [descriptor release];                                         // -1
     }
     const iree_hal_metal_device_params_t* params = iree_hal_metal_device_params(device);
     command_buffer->dispatch_type =