P / Invoke vkGetPhysicalDeviceFeatures访问冲突

时间:2016-02-24 05:51:14

标签: c# pinvoke vulkan

我正在研究一个用于C#的Vulkan包装器(就像我确定很多人一样)而且我遇到了vkGetPhysicalDeviceFeatures有点问题,它要么不返回数据,要么抛出Access违反

Unanaged Side - 签名:

spec的签名是:

void vkGetPhysicalDeviceFeatures(
    VkPhysicalDevice                            physicalDevice,
    VkPhysicalDeviceFeatures*                   pFeatures);

VkPhysicalDevice是一个handle对象,定义为:

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

这只是一个指针和其他使用IntPtrSafeHandle包装的导入,用于此形状的对象。

托管方 - DLL导入:

预期的DLL导入(但失败):

[DllImport("vulkan-1.dll", EntryPoint = "vkGetPhysicalDeviceFeatures")]
internal static extern void GetPhysicalDeviceFeatures(PhysicalDeviceHandle physicalDevice, ref IntPtr features);

这与其他工作进口类似。注意:PhysicalDeviceHandle派生自SafeHandle应该编组到IntPtr,我有其他导入这种模式的工作。上面的内容在调用时会引发访问冲突。

平台:

  • Windows 10(x64)
  • Nvidia Driver:356.43-vkonly(最新)

更新

@V。 Kravchenko是correct

上面的导入没有任何问题。我的问题实际上是vkEnumeratePhysicalDevices来电。

首先我输入错误,正确导入如下:

[DllImport("vulkan-1.dll", EntryPoint = "vkEnumeratePhysicalDevices ")]
internal static extern Result EnumeratePhysicalDevices (InstanceHandle instance, ref physicalDeviceCount, IntPtr[] physicalDevices);

第二关,我实际上错误地使用了这个功能。您需要拨打vkEnumeratePhysicalDevices两次。第一个调用获取设备数,第二个调用填充设备数组。:

IntPtr[] devices = new IntPtr[]();
uint deviceCount = 0;
// populates deviceCount with the number of devices
Vk.EnumeratePhysicalDevices(instanceHandle, ref deviceCount, null);
// populates the devices array with the handle to each device, will only populate up to deviceCount devices
Vk.EnumeratePhysicalDevices(instanceHandle, ref deviceCount, devices);

注意:这在功能文档的描述/有效使用部分中有概述,我在第一次阅读时没有正确解释。

一旦我从EnumeratePhysicalDevices获得了正确的句柄值,那么我对GetPhysicalDeviceFeatures的最终调用就会按预期工作。 GetPhysicalDeviceFeatures的最终导入如下:

[DllImport("vulkan-1.dll", EntryPoint = "vkGetPhysicalDeviceFeatures")]
internal static extern void GetPhysicalDeviceFeatures(PhysicalDeviceHandle physicalDevice, ref VkPhysicalDeviceFeatures features);

注意:名称中Handle的任何变量都是SafeHandle的子类。

1 个答案:

答案 0 :(得分:1)

您必须IntPtr,它实际上指向有效对象,但不仅仅是IntPtr。访问冲突意味着dll中的代码正在尝试访问内存,而IntPtr指向并且不能,因为您的IntPtr未指向有效对象。

总的来说,您应该使用您期望的变体,但将指针传递给有效对象。 工作变体正在工作,因为ref IntPtr实际上是指向IntPtr的指针,而ref IntPtr所指向的IntPtr对象的位置是有效的内存。