dotnet / dotnet/Silk.NET

Vulkan instance functions exposed by device extensions fail to be loaded

Open
#2,547 2 comments 0 reactions 0 assignees View on GitHub
bug
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.