P/Invoke vkGetPhysicalDeviceFeatures 访问冲突
P/Invoke vkGetPhysicalDeviceFeatures Access Violation
我正在为 C# 开发 Vulkan 包装器(我相信很多人都是这样),但我在使用 vkGetPhysicalDeviceFeatures
时遇到了一些问题,它也没有 return 数据,或抛出访问冲突
未管理的一面 - 签名:
spec 的签名是这样的:
void vkGetPhysicalDeviceFeatures(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceFeatures* pFeatures);
VkPhysicalDevice
是一个 handle
对象,定义为:
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
VK_DEFINE_HANDLE(VkPhysicalDevice)
这只是一个指针,其他使用 IntPtr
或 SafeHandle
包装器的导入也适用于这种形状的对象。
托管端 - 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。克拉夫琴科
上面的导入没有问题。我的问题实际上是 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);
注意:这在函数文档的 description/valid 用法部分中有概述,我只是在第一次通读时没有正确解释它。
一旦我最终从 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# 开发 Vulkan 包装器(我相信很多人都是这样),但我在使用 vkGetPhysicalDeviceFeatures
时遇到了一些问题,它也没有 return 数据,或抛出访问冲突
未管理的一面 - 签名:
spec 的签名是这样的:
void vkGetPhysicalDeviceFeatures(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceFeatures* pFeatures);
VkPhysicalDevice
是一个 handle
对象,定义为:
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
VK_DEFINE_HANDLE(VkPhysicalDevice)
这只是一个指针,其他使用 IntPtr
或 SafeHandle
包装器的导入也适用于这种形状的对象。
托管端 - 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。克拉夫琴科
上面的导入没有问题。我的问题实际上是 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);
注意:这在函数文档的 description/valid 用法部分中有概述,我只是在第一次通读时没有正确解释它。
一旦我最终从 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 对象的位置是有效内存。