Vulkan instance functions exposed by device extensions fail to be loaded
- Dominant language
- C#
- Stars
- 5.2k
- Forks
- 477
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 2
Description
# Summary
Silk 2 assumes that all Vulkan functions exposed by device extensions can be retrieved by calling `vkGetDeviceProcAddr`, but apparently device level extensions can expose instance level functions that can only be retrieved by calling `vkGetInstanceProcAddr` (such as `vkGetPhysicalDeviceCalibrateableTimeDomainsKHR`).
The way that Vulkan functions are loaded in Silk 3 means that it will work (try device first, then instance), but it will also report a Vulkan validation warning:
```
vkGetDeviceProcAddr(): pName is trying to grab vkGetPhysicalDeviceCalibrateableTimeDomainsKHR which is an instance level function
```
Unfortunately, there doesn't seem to be an easy way to get around this either other than properly categorizing the functions according to the Vulkan spec for `vkGetDeviceProcAddr`:
> The returned function pointer must only be called with a dispatchable object (the first parameter) that is device or a child of device e.g. VkDevice, VkQueue, or VkCommandBuffer.
Silk 2 implementation:
https://github.com/dotnet/Silk.NET/blob/f91291d97f911fa36b7ee437f2c11d21db223578/src/Vulkan/Silk.NET.Vulkan/Vk.cs#L149-L155
Silk 3 implementation:
https://github.com/dotnet/Silk.NET/blob/7a5299e51253102b65f25675d19ab31e3a15e868/sources/Vulkan/Vulkan/Vk.cs#L181-L187
# Steps to reproduce
On a device that has support for the `VK_KHR_calibrated_timestamps` extension, load the extension using `TryGetDeviceExtension` and call `GetPhysicalDeviceCalibrateableTimeDomain`.
You will get a `Native symbol not found (Symbol: vkGetPhysicalDeviceCalibrateableTimeDomainsKHR)` error and a Vulkan validation warning if Vulkan validation layers are turned on.
Calling `GetInstanceProcAddr`, as suggested by the warning, will result in a valid function pointer and no validation errors.
# Comments
Since I'm the one in charge of the Vulkan bindings for Silk 3, I'll fix this at some point before the full release.
I'll use a workaround in my own codebase for Silk 2.
This seems to require reading the object type graph defined in the Vulkan XML spec and modifying codegen, so not a trivial fix.
This works as a workaround:
```cs
// Workaround for https://github.com/dotnet/Silk.NET/issues/2547
if (EnabledDeviceExtensions.Contains(KhrCalibratedTimestamps.ExtensionName))
{
VkCalibratedTimestamps = new KhrCalibratedTimestamps(new LamdaNativeContext(name =>
{
if (name == "vkGetPhysicalDeviceCalibrateableTimeDomainsKHR")
{
// Instance only
return vk.GetInstanceProcAddr(Instance, name);
}
// The usual try device, then instance fallback
var pointer = vk.GetDeviceProcAddr(Device, name);
if (pointer != 0)
{
return pointer;
}
return vk.GetInstanceProcAddr(Instance, name);
}));
}
```
Contributor guide
Assessment
This issue has not been assessed yet.