c# - P/调用 vkGetPhysicalDeviceFeatures 访问冲突

标签 c# pinvoke vulkan

我正在为 C# 开发 Vulkan 包装器(我相信很多人都是这样),我在使用 vkGetPhysicalDeviceFeatures 时遇到了一些问题,它要么不返回数据,或抛出访问冲突

未管理方 - 签名:

来自 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 驱动程序:356.43-vkonly(最新)

更新

@V。克拉夫琴科是 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 的子类.

最佳答案

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

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

关于c# - P/调用 vkGetPhysicalDeviceFeatures 访问冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35594281/

相关文章:

c# - 在 C# 中减少代码复制的惯用方法

C# - 使用子类实现接口(interface)

C# 精简多指针的内存读取

f# - extern 访问修饰符不起作用

vulkan - 是否允许在从同一池分配的多个线程上记录 CommandBuffers?

vulkan - 是否有可能意外覆盖 VkDeviceMemory 中的 "meta-data"?

c# - 为什么根据 ReSharper 将 double-to-int 转换分配给冗余的动态变量?

c# - 为什么我们需要 dnx 或 web 跨平台

c# - 为什么将 DllImport 返回值中的 char[] 替换为 IntPtr 或 StringBuilder 会导致我的程序不再找到正确的入口点?

c++ - 如何正确调用命令缓冲区的 vulkan.hpp 构造函数?