source/SkiaSharp.Vulkan/SkiaSharp.Vulkan.SharpVk/GRSharpVkBackendContext.cs (108 lines of code) (raw):
using System;
using System.Runtime.InteropServices;
using SharpVk;
using PhysicalDeviceFeaturesNative = SharpVk.Interop.PhysicalDeviceFeatures;
namespace SkiaSharp
{
public delegate IntPtr GRSharpVkGetProcedureAddressDelegate(string name, Instance instance, Device device);
public unsafe class GRSharpVkBackendContext : GRVkBackendContext
{
private Instance vkInstance;
private PhysicalDevice vkPhysicalDevice;
private Device vkDevice;
private Queue vkQueue;
private PhysicalDeviceFeatures? vkPhysicalDeviceFeatures;
private GRSharpVkGetProcedureAddressDelegate getProc;
private PhysicalDeviceFeaturesNative devFeatures;
private GCHandle devFeaturesHandle;
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
if (devFeaturesHandle.IsAllocated)
{
devFeaturesHandle.Free();
devFeaturesHandle = default;
}
}
}
public new Instance VkInstance
{
get => vkInstance;
set
{
vkInstance = value;
base.VkInstance = (IntPtr)vkInstance?.RawHandle.ToUInt64();
}
}
public new PhysicalDevice VkPhysicalDevice
{
get => vkPhysicalDevice;
set
{
vkPhysicalDevice = value;
base.VkPhysicalDevice = (IntPtr)vkPhysicalDevice?.RawHandle.ToUInt64();
}
}
public new Device VkDevice
{
get => vkDevice;
set
{
vkDevice = value;
base.VkDevice = (IntPtr)vkDevice?.RawHandle.ToUInt64();
}
}
public new Queue VkQueue
{
get => vkQueue;
set
{
vkQueue = value;
base.VkQueue = (IntPtr)vkQueue?.RawHandle.ToUInt64();
}
}
public new PhysicalDeviceFeatures? VkPhysicalDeviceFeatures
{
get => vkPhysicalDeviceFeatures;
set
{
vkPhysicalDeviceFeatures = value;
if (devFeaturesHandle.IsAllocated)
devFeaturesHandle.Free();
devFeatures = default;
devFeaturesHandle = default;
base.VkPhysicalDeviceFeatures = IntPtr.Zero;
if (value is PhysicalDeviceFeatures feat)
{
devFeatures = feat.ToNative();
devFeaturesHandle = GCHandle.Alloc(devFeatures, GCHandleType.Pinned);
base.VkPhysicalDeviceFeatures = devFeaturesHandle.AddrOfPinnedObject();
}
}
}
public new GRSharpVkGetProcedureAddressDelegate GetProcedureAddress
{
get => getProc;
set
{
getProc = value;
base.GetProcedureAddress = null;
if (value is GRSharpVkGetProcedureAddressDelegate del)
{
base.GetProcedureAddress = (name, instance, device) =>
{
if (instance != IntPtr.Zero && vkInstance?.RawHandle.ToUInt64() != (ulong)instance.ToInt64())
throw new InvalidOperationException("Incorrect object for VkInstance.");
if (device != IntPtr.Zero && vkDevice?.RawHandle.ToUInt64() != (ulong)device.ToInt64())
throw new InvalidOperationException("Incorrect object for VkDevice.");
var i = instance != IntPtr.Zero ? vkInstance : null;
var d = device != IntPtr.Zero ? vkDevice : null;
return del?.Invoke(name, i, d) ?? IntPtr.Zero;
};
}
}
}
}
}