-
-
Notifications
You must be signed in to change notification settings - Fork 448
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:
Silk.NET/src/Vulkan/Silk.NET.Vulkan/Vk.cs
Lines 149 to 155 in f91291d
| public bool TryGetDeviceExtension<T> | |
| #endif | |
| (Instance instance, Device device, out T ext, string layer = null) where T : NativeExtension<Vk> => | |
| !((ext = IsDeviceExtensionPresent(instance, ExtensionAttribute.GetExtensionAttribute(typeof(T)).Name, layer) | |
| ? (T)Activator.CreateInstance | |
| (typeof(T), new LamdaNativeContext(x => GetDeviceProcAddr(device, x))) | |
| : null) is null); |
Silk 3 implementation:
Silk.NET/sources/Vulkan/Vulkan/Vk.cs
Lines 181 to 187 in 7a5299e
| void* ptr = Ivk.GetDeviceProcAddr(Vk.CurrentDevice, functionName); | |
| if (ptr != null) | |
| { | |
| return ptr; | |
| } | |
| ptr = Ivk.GetInstanceProcAddr(Vk.CurrentInstance, functionName); |
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:
// 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);
}));
}Metadata
Metadata
Assignees
Labels
Type
Projects
Status