Skip to content

Commit

Permalink
Modify the delegate calling pattern in C# code by converting a functi…
Browse files Browse the repository at this point in the history
…on pointer to a direct delegate call.
  • Loading branch information
jcant0n committed Oct 11, 2024
1 parent d19e3da commit 20fc4d3
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 38 deletions.
18 changes: 9 additions & 9 deletions WebGPUGen/Evergine.Bindings.WebGPU/Generated/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public static unsafe partial class WebGPUNative
public static extern WGPUInstance wgpuCreateInstance(WGPUInstanceDescriptor* descriptor);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuGetProcAddress")]
public static extern WGPUProc wgpuGetProcAddress(WGPUDevice device, char* procName);
public static extern delegate* unmanaged<void> wgpuGetProcAddress(WGPUDevice device, char* procName);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuAdapterEnumerateFeatures")]
public static extern ulong wgpuAdapterEnumerateFeatures(WGPUAdapter adapter, WGPUFeatureName* features);
Expand All @@ -26,7 +26,7 @@ public static unsafe partial class WebGPUNative
public static extern WGPUBool wgpuAdapterHasFeature(WGPUAdapter adapter, WGPUFeatureName feature);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuAdapterRequestDevice")]
public static extern void wgpuAdapterRequestDevice(WGPUAdapter adapter, WGPUDeviceDescriptor* descriptor, WGPUAdapterRequestDeviceCallback callback, void* userdata);
public static extern void wgpuAdapterRequestDevice(WGPUAdapter adapter, WGPUDeviceDescriptor* descriptor, delegate* unmanaged<WGPURequestDeviceStatus, WGPUDevice, char*, void*, void> callback, void* userdata);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuAdapterReference")]
public static extern void wgpuAdapterReference(WGPUAdapter adapter);
Expand Down Expand Up @@ -74,7 +74,7 @@ public static unsafe partial class WebGPUNative
public static extern WGPUBufferUsage wgpuBufferGetUsage(WGPUBuffer buffer);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuBufferMapAsync")]
public static extern void wgpuBufferMapAsync(WGPUBuffer buffer, WGPUMapMode mode, ulong offset, ulong size, WGPUBufferMapAsyncCallback callback, void* userdata);
public static extern void wgpuBufferMapAsync(WGPUBuffer buffer, WGPUMapMode mode, ulong offset, ulong size, delegate* unmanaged<WGPUBufferMapAsyncStatus, void*, void> callback, void* userdata);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuBufferSetLabel")]
public static extern void wgpuBufferSetLabel(WGPUBuffer buffer, char* label);
Expand Down Expand Up @@ -206,7 +206,7 @@ public static unsafe partial class WebGPUNative
public static extern WGPUComputePipeline wgpuDeviceCreateComputePipeline(WGPUDevice device, WGPUComputePipelineDescriptor* descriptor);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuDeviceCreateComputePipelineAsync")]
public static extern void wgpuDeviceCreateComputePipelineAsync(WGPUDevice device, WGPUComputePipelineDescriptor* descriptor, WGPUDeviceCreateComputePipelineAsyncCallback callback, void* userdata);
public static extern void wgpuDeviceCreateComputePipelineAsync(WGPUDevice device, WGPUComputePipelineDescriptor* descriptor, delegate* unmanaged<WGPUCreatePipelineAsyncStatus, WGPUComputePipeline, char*, void*, void> callback, void* userdata);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuDeviceCreatePipelineLayout")]
public static extern WGPUPipelineLayout wgpuDeviceCreatePipelineLayout(WGPUDevice device, WGPUPipelineLayoutDescriptor* descriptor);
Expand All @@ -221,7 +221,7 @@ public static unsafe partial class WebGPUNative
public static extern WGPURenderPipeline wgpuDeviceCreateRenderPipeline(WGPUDevice device, WGPURenderPipelineDescriptor* descriptor);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuDeviceCreateRenderPipelineAsync")]
public static extern void wgpuDeviceCreateRenderPipelineAsync(WGPUDevice device, WGPURenderPipelineDescriptor* descriptor, WGPUDeviceCreateRenderPipelineAsyncCallback callback, void* userdata);
public static extern void wgpuDeviceCreateRenderPipelineAsync(WGPUDevice device, WGPURenderPipelineDescriptor* descriptor, delegate* unmanaged<WGPUCreatePipelineAsyncStatus, WGPURenderPipeline, char*, void*, void> callback, void* userdata);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuDeviceCreateSampler")]
public static extern WGPUSampler wgpuDeviceCreateSampler(WGPUDevice device, WGPUSamplerDescriptor* descriptor);
Expand Down Expand Up @@ -266,7 +266,7 @@ public static unsafe partial class WebGPUNative
public static extern void wgpuInstanceProcessEvents(WGPUInstance instance);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuInstanceRequestAdapter")]
public static extern void wgpuInstanceRequestAdapter(WGPUInstance instance, WGPURequestAdapterOptions* options, WGPUInstanceRequestAdapterCallback callback, void* userdata);
public static extern void wgpuInstanceRequestAdapter(WGPUInstance instance, WGPURequestAdapterOptions* options, delegate* unmanaged<WGPURequestAdapterStatus, WGPUAdapter, char*, void*, void> callback, void* userdata);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuInstanceReference")]
public static extern void wgpuInstanceReference(WGPUInstance instance);
Expand Down Expand Up @@ -302,7 +302,7 @@ public static unsafe partial class WebGPUNative
public static extern void wgpuQuerySetRelease(WGPUQuerySet querySet);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuQueueOnSubmittedWorkDone")]
public static extern void wgpuQueueOnSubmittedWorkDone(WGPUQueue queue, WGPUQueueOnSubmittedWorkDoneCallback callback, void* userdata);
public static extern void wgpuQueueOnSubmittedWorkDone(WGPUQueue queue, delegate* unmanaged<WGPUQueueWorkDoneStatus, void*, void> callback, void* userdata);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuQueueSetLabel")]
public static extern void wgpuQueueSetLabel(WGPUQueue queue, char* label);
Expand Down Expand Up @@ -458,7 +458,7 @@ public static unsafe partial class WebGPUNative
public static extern void wgpuSamplerRelease(WGPUSampler sampler);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuShaderModuleGetCompilationInfo")]
public static extern void wgpuShaderModuleGetCompilationInfo(WGPUShaderModule shaderModule, WGPUShaderModuleGetCompilationInfoCallback callback, void* userdata);
public static extern void wgpuShaderModuleGetCompilationInfo(WGPUShaderModule shaderModule, delegate* unmanaged<WGPUCompilationInfoRequestStatus, WGPUCompilationInfo*, void*, void> callback, void* userdata);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuShaderModuleSetLabel")]
public static extern void wgpuShaderModuleSetLabel(WGPUShaderModule shaderModule, char* label);
Expand Down Expand Up @@ -557,7 +557,7 @@ public static unsafe partial class WebGPUNative
public static extern WGPUBool wgpuDevicePoll(WGPUDevice device, WGPUBool wait, WGPUWrappedSubmissionIndex* wrappedSubmissionIndex);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuSetLogCallback")]
public static extern void wgpuSetLogCallback(WGPULogCallback callback, void* userdata);
public static extern void wgpuSetLogCallback(delegate* unmanaged<WGPULogLevel, char*, void*, void> callback, void* userdata);

[DllImport("wgpu_native", CallingConvention = CallingConvention.Cdecl, EntryPoint = "wgpuSetLogLevel")]
public static extern void wgpuSetLogLevel(WGPULogLevel level);
Expand Down
16 changes: 8 additions & 8 deletions WebGPUGen/Evergine.Bindings.WebGPU/Generated/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ namespace Evergine.Bindings.WebGPU
{
public static partial class WebGPUNative
{
public const float WGPU_ARRAY_LAYER_COUNT_UNDEFINED = 0xffffffffUL;
public const float WGPU_COPY_STRIDE_UNDEFINED = 0xffffffffUL;
public const float WGPU_DEPTH_SLICE_UNDEFINED = 0xffffffffUL;
public const float WGPU_LIMIT_U32_UNDEFINED = 0xffffffffUL;
public const float WGPU_LIMIT_U64_UNDEFINED = 0xffffffffffffffffUL;
public const float WGPU_MIP_LEVEL_COUNT_UNDEFINED = 0xffffffffUL;
public const float WGPU_QUERY_SET_INDEX_UNDEFINED = 0xffffffffUL;
public const ulong WGPU_ARRAY_LAYER_COUNT_UNDEFINED = 0xffffffffUL;
public const ulong WGPU_COPY_STRIDE_UNDEFINED = 0xffffffffUL;
public const ulong WGPU_DEPTH_SLICE_UNDEFINED = 0xffffffffUL;
public const ulong WGPU_LIMIT_U32_UNDEFINED = 0xffffffffUL;
public const ulong WGPU_LIMIT_U64_UNDEFINED = 0xffffffffffffffffUL;
public const ulong WGPU_MIP_LEVEL_COUNT_UNDEFINED = 0xffffffffUL;
public const ulong WGPU_QUERY_SET_INDEX_UNDEFINED = 0xffffffffUL;
public static readonly nuint WGPU_WHOLE_MAP_SIZE = nuint.MaxValue;
public const float WGPU_WHOLE_SIZE = 0xffffffffffffffffUL;
public const ulong WGPU_WHOLE_SIZE = 0xffffffffffffffffUL;
}
}
2 changes: 1 addition & 1 deletion WebGPUGen/Evergine.Bindings.WebGPU/Generated/Structs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ public unsafe struct WGPUDeviceDescriptor
public WGPUFeatureName* requiredFeatures;
public WGPURequiredLimits* requiredLimits;
public WGPUQueueDescriptor defaultQueue;
public WGPUDeviceLostCallback deviceLostCallback;
public delegate* unmanaged<WGPUDeviceLostReason, char*, void*, void> deviceLostCallback;
public void* deviceLostUserdata;
public WGPUUncapturedErrorCallbackInfo uncapturedErrorCallbackInfo;
}
Expand Down
31 changes: 18 additions & 13 deletions WebGPUGen/HelloTriangle/HelloTriangle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,19 @@ private void InitWebGPU()
powerPreference = WGPUPowerPreference.HighPerformance
};

wgpuInstanceRequestAdapter(Instance, &options, OnAdapterRequestEnded, (void*)0);
WGPUAdapter adapter = WGPUAdapter.Null;
wgpuInstanceRequestAdapter(Instance, &options, &OnAdapterRequestEnded, &adapter);
WGPUAdapterInfo properties;
wgpuAdapterGetInfo(adapter, &properties);
window.Text = $"WGPU-Native Triangle ({properties.backendType})";

WGPUSupportedLimits limits;
wgpuAdapterGetLimits(adapter, &limits);
this.Adapter = adapter;

AdapterInfo = properties;
AdapterLimits = limits;


WGPUDeviceDescriptor deviceDescriptor = new WGPUDeviceDescriptor()
{
Expand All @@ -107,7 +119,7 @@ private void InitWebGPU()
};

WGPUDevice device = WGPUDevice.Null;
wgpuAdapterRequestDevice(Adapter, &deviceDescriptor, OnDeviceRequestEnded, &device);
wgpuAdapterRequestDevice(Adapter, &deviceDescriptor, &OnDeviceRequestEnded, &device);
Device = device;

Queue = wgpuDeviceGetQueue(Device);
Expand Down Expand Up @@ -140,27 +152,20 @@ private static void HandleUncapturedErrorCallback(WGPUErrorType type, char* pMes
Console.WriteLine($"Uncaptured device error: type: {type} ({Helpers.GetString(pMessage)})");
}

private void OnAdapterRequestEnded(WGPURequestAdapterStatus status, WGPUAdapter candidateAdapter, char* message, void* pUserData)
[UnmanagedCallersOnly]
private static void OnAdapterRequestEnded(WGPURequestAdapterStatus status, WGPUAdapter candidateAdapter, char* message, void* pUserData)
{
if (status == WGPURequestAdapterStatus.Success)
{
Adapter = candidateAdapter;
WGPUAdapterInfo properties;
wgpuAdapterGetInfo(candidateAdapter, &properties);
window.Text = $"WGPU-Native Triangle ({properties.backendType})";

WGPUSupportedLimits limits;
wgpuAdapterGetLimits(candidateAdapter, &limits);

AdapterInfo = properties;
AdapterLimits = limits;
*(WGPUAdapter*)pUserData = candidateAdapter;
}
else
{
Console.WriteLine($"Could not get WebGPU adapter: {Helpers.GetString(message)}");
}
}

[UnmanagedCallersOnly]
private static void OnDeviceRequestEnded(WGPURequestDeviceStatus status, WGPUDevice device, char* message, void* pUserData)
{
if (status == WGPURequestDeviceStatus.Success)
Expand Down
6 changes: 6 additions & 0 deletions WebGPUGen/WebGPUGen/CsCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ public void Generate(CppCompilation compilation, string basePath)
{
string outputPath = basePath;

Helpers.delegates = compilation.Typedefs
.Where(t => t.TypeKind == CppTypeKind.Typedef
&& t.ElementType is CppPointerType
&& ((CppPointerType)t.ElementType).ElementType.TypeKind == CppTypeKind.Function)
.ToList();

GenerateConstants(compilation, outputPath);
GenerateDelegates(compilation, outputPath);
GenerateEnums(compilation, outputPath);
Expand Down
32 changes: 25 additions & 7 deletions WebGPUGen/WebGPUGen/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net.Mime;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using CppAst;
Expand All @@ -10,6 +11,8 @@ namespace WebGPUGen
{
public static class Helpers
{
public static List<CppTypedef> delegates;

private static readonly Dictionary<string, string> s_csNameMappings = new Dictionary<string, string>()
{
{ "uint8_t", "byte" },
Expand All @@ -26,7 +29,6 @@ public static class Helpers
{ "DWORD", "uint" },

{ "WGPUSubmissionIndex", "ulong" },
{ "WGPUErrorCallback", "delegate* unmanaged<WGPUErrorType, char*, void*, void>" },
};

public static string ConvertToCSharpType(CppType type, bool isPointer = false)
Expand Down Expand Up @@ -243,14 +245,15 @@ private static string GetCsTypeName(CppType type, bool isPointer = false)

private static string GetCsCleanName(string name)
{
if (s_csNameMappings.TryGetValue(name, out string mappedName))
var typedef = delegates.Find(d => d.Name == name);
if (typedef != null)
{
return GetCsCleanName(mappedName);
return GetDelegatePointer(typedef);
}
if (name.StartsWith("PFN"))

if (s_csNameMappings.TryGetValue(name, out string mappedName))
{
return "IntPtr";
return GetCsCleanName(mappedName);
}

if (name.Contains("Flags"))
Expand All @@ -265,7 +268,7 @@ public static string GetConstantType(string value)
{
string constType = "string";
if (value.EndsWith("UL", StringComparison.OrdinalIgnoreCase))
constType = "float";
constType = "ulong";
else if (value.EndsWith("U", StringComparison.OrdinalIgnoreCase))
constType = "uint";
else if (value.EndsWith("F", StringComparison.OrdinalIgnoreCase))
Expand Down Expand Up @@ -293,5 +296,20 @@ public static string NormalizeConstantValue(string constantValue)
return constantValue.Replace("ULL", "UL");

}

private static string GetDelegatePointer(CppTypedef type)
{
CppFunctionType pointerType = ((CppPointerType)type.ElementType).ElementType as CppFunctionType;
StringBuilder result = new StringBuilder();

result.Append("delegate* unmanaged<");
for (int i = 0; i < pointerType.Parameters.Count; i++)
{
result.Append(ConvertToCSharpType(pointerType.Parameters[i].Type) + ", ");
}
result.Append(ConvertToCSharpType(pointerType.ReturnType) + ">");

return result.ToString();
}
}
}

0 comments on commit 20fc4d3

Please sign in to comment.