-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Background and motivation
Ability to access floats in the WASM linear memory from in WebGPU contexts, without requiring data copies.
Performance of rendering and also neural networks (AI) depends on no-copy interop.
In those scenarios buffers of float[] are in many cases preferred over double[] buffers because of memory bandwidth and size of RAM on the GPU.
We already have the same API for copy-by-value JS interop of double[] and no-copy interop of , Span<double>, ArraySegment<double>
API Proposal
namespace System.Runtime.InteropServices.JavaScript;
[Versioning.SupportedOSPlatformAttribute("browser")]
[CLSCompliant(false)]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public struct JSMarshalerArgument
{
....
+ public void ToManaged(out float[]? value) { throw null; }
public void ToManaged(out double[]? value) { throw null; }
+ public void ToJS(float[]? value) { throw null; }
public void ToJS(double[]? value) { throw null; }
+ public void ToManaged(out Span<float> value) { throw null; }
public void ToManaged(out Span<double> value) { throw null; }
+ public void ToJS(Span<float> value) { throw null; }
public void ToJS(Span<double> value) { throw null; }
+ public void ToManaged(out ArraySegment<float> value) { throw null; }
public void ToManaged(out ArraySegment<double> value) { throw null; }
+ public void ToJS(ArraySegment<float> value) { throw null; }
public void ToJS(ArraySegment<double> value) { throw null; }
}API Usage
This is API for code generated by Roslyn analyzer when users use [JSImport] or [JSExport].
It's not human facing API, but it needs to be public API because Roslyn generated code is consuming only visible APIs.
The generated code looks similar to this, just with float data type.
Lines 210 to 227 in cf05e72
| global::System.DateTime a10 = default; | |
| global::System.DateTimeOffset a11 = default; | |
| global::System.Threading.Tasks.Task<global::System.DateTime> a12 = default; | |
| global::System.Threading.Tasks.Task<global::System.DateTimeOffset> a13 = default; | |
| global::System.Threading.Tasks.Task<long> a14 = default; | |
| global::System.Threading.Tasks.Task<long> a15 = default; | |
| ref global::System.Runtime.InteropServices.JavaScript.JSMarshalerArgument ____arg_exception_native = ref *____arg_exception_native__param; | |
| try | |
| { | |
| // UnmarshalCapture - Capture the native data into marshaller instances in case conversion to managed data throws an exception. | |
| __a11_native.ToManaged(out a11); | |
| __a10_native.ToManaged(out a10); | |
| __a9_native.ToManaged(out a9); | |
| __a7_native.ToManaged(out a7); | |
| __a6_native.ToManaged(out a6); | |
| __a3_native.ToManagedBig(out a3); | |
| __a2_native.ToManaged(out a2); | |
| __a1_native.ToManaged(out a1); |
User facing API
This doesn't change because this is all user code.
[JSImport("echo1", "JavaScriptTestHelper")]
static partial float[]? Echo1(float[]? value);
[JSExport]
internal static ArraySegment<float> Echo2(ArraySegment<float> value)
{
return value;
}
[JSImport("echo3", "JavaScriptTestHelper")]
static partial Span<float> Echo3(Span<float> value);
[JSExport]
static Span<float> EchoSpanSingle(Span<float> value)
{
return value;
}There is draft implementation #123642
Alternative Designs
No response
Risks
No known risks.