通过 c# 中的 pInvoke 调用 vkEnumeratePhysicalDevices 时出现 AccessViolationException [英] AccessViolationException when calling vkEnumeratePhysicalDevices via pInvoke from c#
问题描述
我有一个敏锐的想法,用 C# 为 Vulkan 编写一个包装器.不幸的是,Vulkan API 的第二次调用已经无法解释地失败了.下面的代码取自 Sascha Willems 的 Vulkan 示例并转换为 c# 代码:
I have the keen idea to write a wrapper for Vulkan in c#. Unfortunately the second call of the Vulkan API already fails unexplainably. The code below is taken from Sascha Willems' Vulkan examples and converted into c# code:
Vk.ApplicationInfo applicationInfo = new Vk.ApplicationInfo();
applicationInfo.sType = Vk.StructureType.STRUCTURE_TYPE_APPLICATION_INFO;
applicationInfo.pApplicationName = "Example";
applicationInfo.pEngineName = "Example";
applicationInfo.apiVersion = (uint)Math.Pow(2, 22) + 2;
string[] enabledExtensions = new string[] { "VK_KHR_surface", "VK_KHR_win32_surface" };
Vk.InstanceCreateInfo instanceCreateInfo = new Vk.InstanceCreateInfo();
instanceCreateInfo.sType = Vk.StructureType.STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pNext = null;
instanceCreateInfo.pApplicationInfo = applicationInfo;
instanceCreateInfo.enabledExtensionCount = (uint)enabledExtensions.Count();
instanceCreateInfo.ppEnabledExtensionNames = enabledExtensions;
Vk.Instance theInstance = new Vk.Instance();
Vk.Result vr = Vk.vkCreateInstance(instanceCreateInfo, IntPtr.Zero, theInstance);
// vr = SUCCESS
uint gpuCount = 0;
vr = Vk.vkEnumeratePhysicalDevices(theInstance, ref gpuCount, IntPtr.Zero);
//Fails with System.AccessViolationException
与
public static class Vk
{
public enum Result
{
SUCCESS = 0,
...
};
public enum StructureType
{
...
}
static Vk()
{
List<string> path = new List<string>() { @"C:\VulkanSDK\1.0.3.1\Source\lib32\" };
AddEnvironmentPaths(path);
}
static void AddEnvironmentPaths(IEnumerable<string> paths)
{
var path = new[] { Environment.GetEnvironmentVariable("PATH") ?? string.Empty };
string newPath = string.Join(Path.PathSeparator.ToString(), path.Concat(paths));
Environment.SetEnvironmentVariable("PATH", newPath);
}
[DllImport("vulkan-1.dll")]
public static extern Result vkCreateInstance(InstanceCreateInfo instanceCreateInfo, IntPtr pAllocator, Instance instance);
[StructLayout(LayoutKind.Sequential)]
public class InstanceCreateInfo
{
public StructureType sType;
public object pNext;
public uint flags;
public ApplicationInfo pApplicationInfo;
public uint enabledLayerCount;
public string[] ppEnabledLayerNames;
public uint enabledExtensionCount;
public string[] ppEnabledExtensionNames;
}
[StructLayout(LayoutKind.Sequential)]
public class ApplicationInfo
{
public StructureType sType;
public object pNext;
public string pApplicationName;
public uint applicationVersion;
public string pEngineName;
public uint engineVersion;
public uint apiVersion;
}
[StructLayout(LayoutKind.Sequential)]
public class Instance
{
}
[DllImport("vulkan-1.dll")]
public static extern Result vkEnumeratePhysicalDevices(Instance instance, ref uint pPhysicalDeviceCount, PhysicalDevice pPhysicalDevices);
[DllImport("vulkan-1.dll")]
public static extern Result vkEnumeratePhysicalDevices(Instance instance, ref uint pPhysicalDeviceCount, IntPtr pPhysicalDevices);
public class PhysicalDevice
{
}
}
我怀疑 Vk.Instance 不应该只是一个空类.VkInstance 在官方 vulkan.h 中定义为 typedef struct VkInstance_T* VkInstance
.不幸的是,我对这条线的理解非常有限.我已经尝试用 IntPtr
和 object
交换类型 Vk.Instance
但没有成功.
My Suspicion is that Vk.Instance should be something else than just an empty class. VkInstance is in the official vulkan.h defined as typedef struct VkInstance_T* VkInstance
. My understanding of this line is unfortunately very limited. I already tried exchanging the type Vk.Instance
with IntPtr
and object
but without success.
论文是vulkan.h
#define VK_DEFINE_HANDLE(object) typedef struct object##_T* object;
VK_DEFINE_HANDLE(VkInstance)
VK_DEFINE_HANDLE(VkPhysicalDevice)
VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(
const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkInstance* pInstance);
VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(
VkInstance instance,
uint32_t* pPhysicalDeviceCount,
VkPhysicalDevice* pPhysicalDevices);
推荐答案
Zatai 回答了我的问题.必须是
Zastai answered my question. It had to be
[DllImport("vulkan-1.dll")]
public static extern Result vkCreateInstance(InstanceCreateInfo instanceCreateInfo, IntPtr pAllocator, out IntPtr instance);
因为它确实是指向指针的指针.
because it were indeed pointers to pointers.
IntPtr instance;
Vk.Result vr = Vk.vkCreateInstance(instanceCreateInfo, IntPtr.Zero, out instance);
uint gpuCount = 0;
vr = Vk.vkEnumeratePhysicalDevices(instance, ref gpuCount, IntPtr.Zero);
非常感谢!
这篇关于通过 c# 中的 pInvoke 调用 vkEnumeratePhysicalDevices 时出现 AccessViolationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!