[Metal][Generator] Fix the SetBuffers methods in protocols. Fixes #9649 (#9651)

Add fixes for Metal for XAM_CORE_4. Fixing the methods takes us to a dangerous path, so we do not do it unless we have issues about the methods.

Fixes https://github.com/xamarin/xamarin-macios/issues/9649
This commit is contained in:
Manuel de la Pena 2020-10-01 14:27:55 -04:00 коммит произвёл GitHub
Родитель 8a92716c89
Коммит 2c78255dbe
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 218 добавлений и 1 удалений

Просмотреть файл

@ -1,11 +1,40 @@
using System;
using System.Runtime.InteropServices;
using Foundation;
using ObjCRuntime;
namespace Metal {
public static partial class MTLArgumentEncoder_Extensions {
#if XAMCORE_4_0
public static void SetBuffers (this IMTLArgumentEncoder encoder, IMTLBuffer[] buffers, nuint[] offsets, NSRange range)
{
if (buffers == null)
throw new ArgumentNullException (nameof (buffers));
if (offsets == null)
throw new ArgumentNullException (nameof (offsets));
var bufferPtrArray = buffers.Length <= 1024 ? stackalloc IntPtr[buffers.Length] : new IntPtr [buffers.Length];
// get all intptr from the array to pass to the lower level call
for (var i = 0; i < buffers.Length; i++) {
bufferPtrArray [i] = buffers [i].Handle;
}
unsafe {
fixed (void* buffersPtr = bufferPtrArray)
fixed (void* offsetsPtr = offsets) { // can use fixed
encoder.SetBuffers ((IntPtr) buffersPtr, (IntPtr) offsetsPtr, range);
}
}
GC.KeepAlive (buffers)
}
#else
public unsafe static void SetBuffers (this IMTLArgumentEncoder This, IMTLBuffer [] buffers, nint [] offsets, Foundation.NSRange range)
{
fixed (void* handle = offsets)
This.SetBuffers (buffers, (IntPtr)handle, range);
}
#endif
}
}

Просмотреть файл

@ -0,0 +1,36 @@
using System;
using System.Runtime.InteropServices;
using Foundation;
using ObjCRuntime;
namespace Metal {
#if XAMCORE_4_0
// add some extension methods to make the API of the protocol nicer
public static class IMTLComputeCommandEncoderExtensions {
public static void SetBuffers (this IMTLComputeCommandEncoder table, IMTLBuffer[] buffers, nuint[] offsets, NSRange range)
{
if (buffers == null)
throw new ArgumentNullException (nameof (buffers));
if (offsets == null)
throw new ArgumentNullException (nameof (offsets));
var bufferPtrArray = buffers.Length <= 1024 ? stackalloc IntPtr[buffers.Length] : new IntPtr [buffers.Length];
// get all intptr from the array to pass to the lower level call
for (var i = 0; i < buffers.Length; i++) {
bufferPtrArray [i] = buffers [i].Handle;
}
unsafe {
fixed (void* buffersPtr = bufferPtrArray)
fixed (void* offsetsPtr = offsets) { // can use fixed
table.SetBuffers ((IntPtr) buffersPtr, (IntPtr) offsetsPtr, range);
}
}
GC.KeepAlive (buffers)
}
}
#endif
}

Просмотреть файл

@ -1078,6 +1078,7 @@ METAL_SOURCES = \
Metal/MTLArgumentEncoder.cs \
Metal/MTLBlitPassSampleBufferAttachmentDescriptorArray.cs \
Metal/MTLCompat.cs \
Metal/MTLComputeCommandEncoder.cs \
Metal/MTLComputePassSampleBufferAttachmentDescriptorArray.cs \
Metal/MTLDevice.cs \
Metal/MTLIntersectionFunctionTable.cs \

Просмотреть файл

@ -495,9 +495,16 @@ namespace Metal {
[Export ("dispatchThreadgroupsWithIndirectBuffer:indirectBufferOffset:threadsPerThreadgroup:")]
void DispatchThreadgroups (IMTLBuffer indirectBuffer, nuint indirectBufferOffset, MTLSize threadsPerThreadgroup);
#if XAMCORE_4_0
[Abstract]
[Export ("setBuffers:offsets:withRange:")]
void SetBuffers (IntPtr buffers, IntPtr offsets, NSRange range);
#else
[Abstract]
[Export ("setBuffers:offsets:withRange:")]
void SetBuffers (IMTLBuffer [] buffers, IntPtr offsets, NSRange range);
#endif
[Abstract]
[Export ("setSamplerStates:lodMinClamps:lodMaxClamps:withRange:")]
@ -3911,9 +3918,15 @@ namespace Metal {
[Export ("setBuffer:offset:atIndex:")]
void SetBuffer ([NullAllowed] IMTLBuffer buffer, nuint offset, nuint index);
#if XAMCORE_4_0
[Abstract]
[Export ("setBuffers:offsets:withRange:")]
void SetBuffers (IntPtr buffers, IntPtr offsets, NSRange range);
#else
[Abstract]
[Export ("setBuffers:offsets:withRange:")]
void SetBuffers (IMTLBuffer[] buffers, IntPtr offsets, NSRange range);
#endif
[Abstract]
[Export ("setTexture:atIndex:")]

Просмотреть файл

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

Просмотреть файл

@ -0,0 +1,69 @@
#if !__WATCHOS__
using System;
using Foundation;
using Metal;
using NUnit.Framework;
namespace MonoTouchFixtures.Metal {
[TestFixture]
public class MTLArgumentEncoderTest {
IMTLDevice device;
IMTLLibrary library;
IMTLFunction function;
IMTLArgumentEncoder encoder;
[SetUp]
public void SetUp ()
{
device = MTLDevice.SystemDefault;
// some older hardware won't have a default
if (device == null)
Assert.Inconclusive ("Metal is not supported");
library = device.CreateDefaultLibrary ();
if (library == null) // this happens on a simulator
Assert.Inconclusive ("Could not get the functions library for the device.");
if (library.FunctionNames.Length == 0)
Assert.Inconclusive ("Could not get functions for the pipeline.");
function = library.CreateFunction (library.FunctionNames [0]);
encoder = function.CreateArgumentEncoder (0);
}
[TearDown]
public void TearDown ()
{
library?.Dispose ();
library = null;
function?.Dispose ();
function = null;
encoder?.Dispose ();
encoder = null;
}
#if XAMCORE_4_0
[Test]
public void SetBuffers ()
{
Assert.Throws<ArgumentNullException> (() => {
encoder.SetBuffers (null, new nuint [0], new NSRange ());
}, "Null buffers should throw.");
Assert.Throws<ArgumentNullException> (() => {
encoder.SetBuffers (new IMTLBuffer [0], null, new NSRange ());
}, "Null offsets should throw.");
// assert we do not crash or throw, we are testing the extension method
Assert.DoesNotThrow (() => {
encoder.SetBuffers (new IMTLBuffer [0], new nuint [0], new NSRange ());
}, "Should not throw");
}
#endif
}
}
#endif

Просмотреть файл

@ -0,0 +1,69 @@
#if !__WATCHOS__
using System;
using Foundation;
using Metal;
using NUnit.Framework;
namespace MonoTouchFixtures.Metal {
[TestFixture]
public class MTLComputeCommandEncoderTest {
IMTLDevice device;
IMTLCommandQueue commandQ;
IMTLCommandBuffer commandBuffer;
IMTLComputeCommandEncoder encoder;
[SetUp]
public void SetUp ()
{
device = MTLDevice.SystemDefault;
// some older hardware won't have a default
if (device == null)
Assert.Inconclusive ("Metal is not supported");
commandQ = device.CreateCommandQueue ();
if (commandQ == null) // this happens on a simulator
Assert.Inconclusive ("Could not get the functions library for the device.");
commandBuffer = commandQ.CommandBuffer ();
if (commandBuffer == null) // happens on sim
Assert.Inconclusive ("Could not get the command buffer for the device.");
encoder = commandBuffer.ComputeCommandEncoder;
}
[TearDown]
public void TearDown ()
{
commandQ?.Dispose ();
commandQ = null;
commandBuffer?.Dispose ();
commandBuffer = null;
encoder?.Dispose ();
encoder = null;
}
#if XAMCORE_4_0
[Test]
public void SetBuffers ()
{
Assert.Throws<ArgumentNullException> (() => {
encoder.SetBuffers (null, new nuint [0], new NSRange ());
}, "Null buffers should throw.");
Assert.Throws<ArgumentNullException> (() => {
encoder.SetBuffers (new IMTLBuffer [0], null, new NSRange ());
}, "Null offsets should throw.");
// assert we do not crash or throw, we are testing the extension method
Assert.DoesNotThrow (() => {
encoder.SetBuffers (new IMTLBuffer [0], new nuint [0], new NSRange ());
}, "Should not throw");
}
#endif
}
}
#endif