-1

I'm trying to create a Vulkan wrapper in C#, but I have some problems when I call a function. I rewrote the vulkan.h header as follows :

public static class Vk {
    [StructLayout(LayoutKind.Sequential)] public class Instance { }

    public enum Result {
        ...
    }
    public enum StructureType {
        ...
    }

    [StructLayout(LayoutKind.Sequential)] public class ApplicationInfo {
        public StructureType sType;
        public IntPtr pNext;
        public string pApplicationName;
        public uint applicationVersion;
        public string pEngineName;
        public uint engineVersion;
        public uint apiVersion;
    }

    [StructLayout(LayoutKind.Sequential)] public class InstanceCreateInfo {
        public StructureType sType;
        public IntPtr pNext;
        public uint flags_VkInstanceCreateFlags;
        public ApplicationInfo pApplicationInfo;
        public uint enabledLayerCount;
        public string[] ppEnabledLayerNames;
        public uint enabledExtensionCount;
        public string[] ppEnabledExtensionNames;
    }

    [DllImport("vulkan-1.dll", EntryPoint = "vkCreateInstance")]
    public extern static Result CreateInstance(
        InstanceCreateInfo pCreateInfo,
        IntPtr AllocationCallbacks_pAllocator,
        out IntPtr pInstance_Instance);
}

The original declaration in C of this function is

VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
    const VkInstanceCreateInfo*                 pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkInstance*                                 pInstance);

Now when I call my function, I'm doing like this :

Vk.InstanceCreateInfo instance_create_info = new Vk.InstanceCreateInfo();
...

IntPtr hinstance;
Vk.Result result = Vk.CreateInstance(instance_create_info, IntPtr.Zero, out hinstance);   <-- error AccessViolationException

I don't understand where is my problem, because it seems to be a valid solution : StackOverflow : AccessViolationException when calling vkEnumeratePhysicalDevices via pInvoke from c#.

I tried by initializing my IntPtr hinstance with

Marshal.AllocHGlobal(Marshal.SizeOf<Vk.Instance>());  

I also tried to "convert" my instance_create_info to another IntPtr with Marshal.StructureToPtr(...); and I tried to pass instance_create_info and instance by the ref keyword. Obviously, nothing worked.

Any idea ?


EDIT :

The native function is used as follows :

//Definition
typedef struct VkApplicationInfo {
    VkStructureType    sType;
    const void*        pNext;
    const char*        pApplicationName;
    uint32_t           applicationVersion;
    const char*        pEngineName;
    uint32_t           engineVersion;
    uint32_t           apiVersion;
} VkApplicationInfo;`
typedef struct VkInstanceCreateInfo {
    VkStructureType             sType;
    const void*                 pNext;
    VkInstanceCreateFlags       flags;
    const VkApplicationInfo*    pApplicationInfo;
    uint32_t                    enabledLayerCount;
    const char* const*          ppEnabledLayerNames;
    uint32_t                    enabledExtensionCount;
    const char* const*          ppEnabledExtensionNames;
} VkInstanceCreateInfo;

#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
VK_DEFINE_HANDLE(VkInstance)

//Code
VkApplicationInfo application_info{};
    application_info.sType                  = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    application_info.apiVersion             = VK_API_VERSION;
    application_info.applicationVersion     = VK_MAKE_VERSION( 1, 0, 0 );
    application_info.pApplicationName       = "";
    application_info.engineVersion          = VK_MAKE_VERSION( 1, 0, 0 );
    application_info.pEngineName            = "";

VkInstanceCreateInfo instance_create_info{};
    instance_create_info.sType                      = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    instance_create_info.pApplicationInfo           = &application_info;
    instance_create_info.enabledLayerCount          = 0
    instance_create_info.ppEnabledLayerNames        = nullptr
    instance_create_info.enabledExtensionCount      = 0
    instance_create_info.ppEnabledExtensionNames    = nullptr

VkInstance _instance = nullptr;
assert( !vkCreateInstance( &instance_create_info, nullptr, &_instance ) );
Community
  • 1
  • 1
Clematrics
  • 15
  • 8
  • There's not enough info here to answer. We'd need both sides of the interface in full and a spec of the semantics. Or some example C calling code. – David Heffernan Apr 16 '16 at 15:17
  • @DavidHeffernan I added a sample code. Tell me if you need something else. – Clematrics Apr 16 '16 at 15:44
  • I don't know how the the C# FFI works, but `out IntPtr pInstance_Instance` looks wrong. The out argument of `vkCreateInstance` takes a double-pointer to an opaque struct; an integer may not be large enough for the pointer. – Colonel Thirty Two Apr 17 '16 at 15:51

2 Answers2

1

it seems that you are trying to do something similar this guy made a wrapper for the c#. Can be useful for you. Go to Source/SharpVulkan/Generated/Functions.

    public static unsafe Instance CreateInstance(ref InstanceCreateInfo createInfo, AllocationCallbacks* allocator = null)
    {
        Instance instance;
        fixed (InstanceCreateInfo* __createInfo__ = &createInfo)
        {
            vkCreateInstance(__createInfo__, allocator, &instance).CheckError();
        }
        return instance;
    }

    [DllImport("vulkan-1.dll", CallingConvention = CallingConvention.StdCall)]
    internal static extern unsafe Result vkCreateInstance(InstanceCreateInfo* createInfo, AllocationCallbacks* allocator, Instance* instance);

    internal static unsafe void EnumerateInstanceExtensionProperties(byte* layerName, ref uint propertyCount, ExtensionProperties* properties)
    {
        fixed (uint* __propertyCount__ = &propertyCount)
        {
            vkEnumerateInstanceExtensionProperties(layerName, __propertyCount__, properties).CheckError();
        }
    }

Hope it is helpfull :)

Nikolai Arsenov
  • 464
  • 2
  • 10
-1

remove out keyword for third argument or declare it as corresponding struct.

mehrdad safa
  • 1,081
  • 9
  • 10