我将 vulkan 与 odin 编程语言结合使用。我的程序在尝试调用过程 vulkan.CreateDevice() 后崩溃(仅供参考,过程只是 odin 中的函数)。 我创建设备的代码如下所示:
bonbug.actionStart("Creating Device");
vulkan.load_proc_addresses(get_proc_address);
queuePriority : f32 = 1.0;
dQCreateInfo : []vulkan.DeviceQueueCreateInfo = {{
sType = .DEVICE_QUEUE_CREATE_INFO,
queueFamilyIndex = deviceIndex,
queueCount = 1,
pQueuePriorities = &queuePriority,
}};
deviceFeatures : vulkan.PhysicalDeviceFeatures;
dCreateInfo : vulkan.DeviceCreateInfo = {
sType = .DEVICE_CREATE_INFO,
pQueueCreateInfos = raw_data(dQCreateInfo),
queueCreateInfoCount = cast(u32)len(dQCreateInfo),
pEnabledFeatures = &deviceFeatures,
enabledExtensionCount = 0,
enabledLayerCount = layerCount,
ppEnabledLayerNames = cast([^]cstring)raw_data(requestedLayers),
};
fmt.printf("test");
vulkan.CreateDevice(devices[deviceIndex], &dCreateInfo, nil, &device);
bonbug.actionEnd();
Bonbug 只是一个调试包。我的程序叫做 bonfire,所以这就是我想出的名字。 Vulkan 不显示任何错误消息。我知道程序在运行 vulkan.CreateDevice() 时崩溃,因为 printf("test") 通过了。 结果输出是这样的:
BONBUGGER: Creating Device... test
请注意,该行末尾没有“DONE”(这就是 bonbug.actionEnd() 所做的),这验证了程序已崩溃。 此行为之前在另一个 vulkan 过程中也发生过。我用这段代码修复了:
context.user_ptr = &instance;
get_proc_address :: proc(p: rawptr, name: cstring)
{
(cast(^rawptr)p)^ = glfw.GetInstanceProcAddress((^vulkan.Instance)(context.user_ptr)^, name);
}
vulkan.load_proc_addresses(get_proc_address);
这对于该程序有效;但是我尝试运行“vulkan.load_proc_addresses(get_proc_address);”在 CreateDevice() 过程之前再次执行此操作,但它不起作用。 请帮忙,因为我还没有找到 odin 的任何 vulkan 文档,但我对项目的了解太深,无法将其转换为 c++。
不确定您是否仍在寻找这个问题的答案,但我一直在研究这个问题,并认为我会与其他人分享我的发现。
导入时的 Vulkan 库在某种意义上是“不完整的”。我们需要使用 Vulkan 的所有方法/函数都存在,但作为模板而不是真正的函数。为了使用这些函数,我们必须首先告诉库在哪里可以找到这些函数。
我们可以使用重载函数来做到这一点:
vulkan.load_proc_addresses()
。该函数重载了以下 5 个函数:
load_proc_addresses_global(vk_get_instance_proc_addr: rawptr)
load_proc_addresses_instance(instance: Instance)
load_proc_addresses_device(device: Device)
load_proc_addresses_device_vtable(device: Device, vtable: ^Device_VTable)
load_proc_addresses_custom(set_proc_address: SetProcAddressType)
load_proc_addresses_global(vk_get_instance_proc_addr: rawptr)
:
此函数采用指向函数的指针作为参数,用于访问创建 Vulkan 实例所需的最基本的 Vulkan 函数。
load_proc_addresses_instance(instance: Instance)
:
通过将
vulkan.Instance
传递给此函数,我们可以访问创建物理和逻辑设备所需的下一级 Vulkan 功能。
load_proc_addresses_device(device: Device)
将 vulkan.Device 传递给该函数后,我们就完成了所有函数定义,可以使用完整的 Vulkan 功能。
用这个我们可以组合一个基本的 Vulkan 初始化方法:
import "vendor:glfw"
import vk "vendor:vulkan"
initVulkan :: proc() {
// load_proc_addresses_global :: proc(vk_get_instance_proc_addr: rawptr)
vk.load_proc_addresses((rawptr)(glfw.GetInstanceProcAddress));
instance : vk.Instance = createVkInstance();
// load_proc_addresses_instance :: proc(instance: Instance)
vk.load_proc_addresses(instance)
physicalDevice : vk.PhysicalDevice = pickPhysicalDevice()
device : vk.Device = createLogicalDevice(physicalDevice)
// load_proc_addresses_device :: proc(device: Device)
vk.load_proc_addresses(device)
}
就是这样。这样(假设您正确创建了实例和设备),Vulkan 库就可以正常运行了。
但是我听到你问最后两个函数是什么:
load_proc_addresses_device_vtable(device: Device, vtable: ^Device_VTable)
load_proc_addresses_custom(set_proc_address: SetProcAddressType)
我们不需要它们。据我所知,仅当您计划同时使用多个设备时才使用
load_proc_addresses_device_vtable
。这是因为每个设备都有自己的关联功能位置,要求程序员为每个设备存储正确的功能位置。
另一方面,load_proc_addresses_custom
接受一个函数指针并使用它映射所有 Vulkans 函数。我想不出您希望自己这样做的任何合理理由,所以不要接近这个,除非您真的知道自己在做什么。