From 04c0be3becb91ab5113e4b27a16743d97972ba25 Mon Sep 17 00:00:00 2001 From: Jeremy Powell Date: Wed, 30 Apr 2025 12:12:17 +1200 Subject: [PATCH 1/2] Add GRContext Metal backend test --- .../Tests/iOS/iOSExtensionsTests.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/SkiaSharp.Tests.Devices/Tests/iOS/iOSExtensionsTests.cs b/tests/SkiaSharp.Tests.Devices/Tests/iOS/iOSExtensionsTests.cs index a0e8c55f29..51398d4bed 100644 --- a/tests/SkiaSharp.Tests.Devices/Tests/iOS/iOSExtensionsTests.cs +++ b/tests/SkiaSharp.Tests.Devices/Tests/iOS/iOSExtensionsTests.cs @@ -1,5 +1,7 @@ -using CoreGraphics; +using System; +using CoreGraphics; using Foundation; +using Metal; using Xunit; namespace SkiaSharp.Views.iOS.Tests @@ -99,5 +101,21 @@ public void CGRectToSKRect(int x, int y, int w, int h) Assert.Equal(expected, actual); } + + [SkippableFact] + public void GRContextDisposeDoesNotCrash() + { + var device = MTLDevice.SystemDefault!; + Skip.If(device == null, "Metal is not supported on this device."); + + using var commandQueue = device.CreateCommandQueue(); + using var backendContext = new GRMtlBackendContext() + { + Device = device, + Queue = commandQueue, + }; + + using var context = GRContext.CreateMetal(backendContext); + } } } From 8a1443c9a45aad5db7cb022ea10afb518bd56417 Mon Sep 17 00:00:00 2001 From: Jeremy Powell Date: Wed, 30 Apr 2025 15:48:46 +1200 Subject: [PATCH 2/2] Retain command buffer in Metal GRMtlBackendContext AbandonContext appears to destroy the command buffer, causing the finalizer to crash from a double free. Fixes: #3178 --- binding/SkiaSharp/GRContext.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/binding/SkiaSharp/GRContext.cs b/binding/SkiaSharp/GRContext.cs index 918348f32d..273639ee15 100644 --- a/binding/SkiaSharp/GRContext.cs +++ b/binding/SkiaSharp/GRContext.cs @@ -91,6 +91,11 @@ public static GRContext CreateMetal (GRMtlBackendContext backendContext, GRConte var device = backendContext.DeviceHandle; var queue = backendContext.QueueHandle; +#if __IOS__ || __MACOS__ || __TVOS__ + using Foundation.NSObject queueObject = Foundation.NSObject.FromObject(backendContext.Queue); + queueObject.DangerousRetain (); +#endif + if (options == null) { return GetObject (SkiaApi.gr_direct_context_make_metal ((void*)device, (void*)queue)); } else {