mono / VulkanSharp

Open source .NET binding for the Vulkan API
MIT License
538 stars 61 forks source link

Consider a pattern for extending external surface creation #53

Open tim-stasse opened 7 years ago

tim-stasse commented 7 years ago

I'm using GLFW (with c# bindings), to create a surface, using the glfwCreateWindowSurface method. However since the SurfaceKhr constructor is internal, I am unable to implement the same pattern used to create the surface in the CreateWin32SurfaceKHR extension method, from a separate project.

My solution was to create a simple factory in helpers.cs, which allows a UInt64/ulong to be passed in and returns a new SurfaceKhr. I'm not sure if this is the best pattern to use in this circumstance, so any other alternative suggestion would suffice.

The other issue is, that the ResultException constructor is internal, I simply made this public, however again, any other alternative will suffice.

The code I intend to write is:

namespace Glfw3
{
    using System;
    using System.Runtime.InteropServices;
    using System.Security;
    using Vulkan;

    public static partial class Glfw
    {
        private struct VkAllocationCallbacks
        {
            private IntPtr UserData;
            private IntPtr PfnAllocation;
            private IntPtr PfnReallocation;
            private IntPtr PfnFree;
            private IntPtr PfnInternalAllocation;
            private IntPtr PfnInternalFree;
        }

        public static SurfaceKhr CreateWindowSurface(Instance instance, Window window, AllocationCallbacks allocationCallbacks = null)
        {
            Result result;
            ulong pSurface;

            unsafe
            {
                var ptrpSurface = &pSurface;
                var pAlloactor = allocationCallbacks != null ? (VkAllocationCallbacks*)((IMarshalling)allocationCallbacks).Handle : null;

                result = glfwCreateWindowSurface(((IMarshalling)instance).Handle, window, pAlloactor, ptrpSurface);

                if (result != Result.Success)
                {
                    throw new ResultException(result);
                }

                return SurfaceKhrFactory.CreateSurface(pSurface);
            }
        }

        [DllImport(kLibrary, CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
        private static extern unsafe Result glfwCreateWindowSurface(IntPtr instance, [MarshalAs(UnmanagedType.Struct)] Window window, VkAllocationCallbacks* pAllocator, ulong* surface);
    }
}

The modifications that I made to helpers.cs, (in order for the above code to work) are:

public class ResultException : Exception
{
    internal Result result;

    public Result Result
    {
        get { return result; }
    }

    public ResultException(Result res)
    {
        result = res;
    }
}

...

public static class SurfaceKhrFactory
{
    public static SurfaceKhr CreateSurface(ulong pSurface)
    {
        return new SurfaceKhr
        {
            m = pSurface
        };
    }
}