2

我正在为 C# 开发一个 Vulkan 包装器(就像我相信很多人一样),我遇到了一些问题,vkGetPhysicalDeviceFeatures要么不返回数据,要么抛出访问冲突

未管理的一面 - 签名:

规范的签名是这样的:

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,我有其他使用这种模式的导入。上面调用时会引发访问冲突。


平台:

  • 视窗 10 (x64)
  • Nvidia 驱动程序:(356.43-vkonly最新)

更新

@V。克拉夫琴科是正确的

上面的导入没有任何问题。我的问题实际上与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.

4

1 回答 1

1

You must IntPtr,它实际上确实指向一个有效的对象,但不仅仅是IntPtr. 访问冲突意味着 dll 中的代码正在尝试访问内存,您IntPtr指出并且不能访问内存,因为您IntPtr没有指向有效对象。

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

于 2016-02-24T06:18:17.810 回答