AMF_FAIL: LoadFunctionsTable() failed: It may be wrong Vulkan driver version
I'm trying to use AMFVideoEncoderVCE_AVC with an existing vulkan device but it doesn't initialize.
[vkCreateInstance] createInfo=000000000885C3B0, allocator=0000000000000000, instance=0000000086D00290
[vkCreateDevice] physicalDevice=000000000593D690, createInfo=000000000886F390, allocator=0000000000000000, device=0000000086D00CA0
AMFDeviceVulkanImpl: 2019-12-13 14:27:56.542 CC3C [AMFDeviceVulkanImpl] Error: ..\..\..\..\..\runtime\src\core\DeviceVulkanImpl.cpp(417):AMF_ERROR 1 : AMF_FAIL: LoadFunctionsTable() failed: It may be wrong Vulkan driver version
AMFContextImpl: 2019-12-13 14:27:56.543 CC3C [AMFContextImpl] Error: ..\..\..\..\..\runtime\src\core\ContextImpl.cpp(797):AMF_ERROR 1 : AMF_FAIL: pDeviceVulkan->Init(pVulkanDevice)
calling code is
g_AMFFactory.Init();
g_AMFFactory.GetTrace()->SetGlobalLevel(AMF_TRACE_TRACE);
g_AMFFactory.GetFactory()->CreateContext(&AmfContext);
amf::AMFVulkanDevice VulkanDevice { };
VulkanDevice.cbSizeof = sizeof(VulkanDevice);
VulkanDevice.hDevice = s_VulkanDevice;
VulkanDevice.hInstance = s_VulkanInstance;
VulkanDevice.hPhysicalDevice = s_VulkanPhysicalDevice;
AMF_RESULT Ret = amf::AMFContext1Ptr(AmfContext)->InitVulkan(&VulkanDevice);
What I know:
- s_VulkanPhysicalDevice, ...Device & ...Instance are all valid and working
-
amf::AMFContext1Ptr(AmfContext)->InitVulkan(nullptr);also works fine (well as a separate instance) -
vulkan-1.dllis loaded
Now, what's the issue here?
I do know it fails around public\common\VulkanImportTable.cpp in AMD's amfrt64.dll library, when it tries to load your privatevkCreateVideoDecoderAMD etc import functions.
How do I make it happy? There must be an issue when I create the Vulkan device, a missing extension, a flag, something. At the beginning of your import scan you look for the generic vkCreateSwapchainKHR, vkDestroySwapchainKHR etc imports, they all seem to work (as for those you print a better error message with a line number). Only your private functions are silently failing. And all are failing the same I guess, so the VulkanImportTable.cpp cannot find vkGetPhysicalDeviceVideoDecodeCodecsAMD (the very first of your private ones).
Can someone at AMD hint me what the issue is? Otherwise it's gonna be a long road for me to hack thru your code.
Well, furthermore I tracked it to amfrt64.dll calling vkGetDeviceProcAddr in vulkan-1.dll to get vkBindVideoEncoderMemoryAMD and the call return nullptr. That's why it fails.
The physical device is an AMD Radeon R590, that's confirmed but for unknown reasons those extra functions aren't registered in the VkDevice.
-
amf::AMFContext1Ptr(AmfContext)->InitVulkan(nullptr);works -
amf::AMFContext1Ptr(AmfContext)->InitVulkan(&VulkanDevice);doesn't works
VkCreateDevice, VkCreateInstance look identical to me, same layers, same extensions. Same flags, same features. How is AMD registering these private function by what secret undocumented method?
It looks like you didn't call GetVulkanDeviceExtensions, which returns private extensions needed for encoder and decoder. You would have to adds the extensions when you create devices. Check DeviceVulkan.cpp. Note that Vulkan debug layers will not work.
Any update?
Thanks for the reply.
As far as I can tell, GetVulkanDeviceExtensions returns 5 strings that I have to add as extensions to the call to VkCreateDevice. I'm already doing it.
VkDeviceCreateInfo CreateInfo = *pCreateInfo;
...
LPCSTR Extensions[32] { };
CreateInfo.ppEnabledExtensionNames = Extensions;
...
Extensions[CreateInfo.enabledExtensionCount++] = "VK_AMD_video_decode_queue";
Extensions[CreateInfo.enabledExtensionCount++] = "VK_AMD_yuv_image";
Extensions[CreateInfo.enabledExtensionCount++] = "VK_AMD_video_encode_queue";
Extensions[CreateInfo.enabledExtensionCount++] = "VK_AMD_video_encode_h264";
Extensions[CreateInfo.enabledExtensionCount++] = "VK_AMD_video_encode_h265";
The sample code works and I see no difference to the VkCreateDevice call as far as I can see looking at the Vulkan API Call Trace. Do I have to do anything else? Maybe a flag? And I'm not using any layer.
Is it possible that your app linked with Vulkan rather then using LoadLibrary? It didn't work earlier but now we fixed this. If so you have to update to the latest driver released recently.
vulkan-1.dll 1.1.126
amdvlk64.dll 26.20.15002.61
amfrt64.dll 1.04.16.0
Both are actually rather new. And those are the libraries that are loaded (in process). I look for a driver update. Maybe a beta driver.
New Radeon Software driver was released Dec 10th. It is not a hot fix but entirely new. It has the change I mentioned.
There as a fresh release on the 18th, I installed that.
But I'm not sure if that is better now, it's at least different:
2019-12-19 14:52:39.033 19700 [AMFDeviceVulkanImpl] Error: ..\..\..\..\..\runtime\src\core\DeviceVulkanImpl.cpp(722):Assertion failed:vkCreateDevice() failed, Error=-7
2019-12-19 14:52:39.033 19700 [AMFDeviceVulkanImpl] Error: ..\..\..\..\..\runtime\src\core\DeviceVulkanImpl.cpp(412):AMF_ERROR 1 : AMF_FAIL: CreateDeviceAndFindQueues() failed
2019-12-19 14:52:39.033 19700 [AMFContextImpl] Error: ..\..\..\..\..\runtime\src\core\ContextImpl.cpp(797):AMF_ERROR 1 : AMF_FAIL: pDeviceVulkan->Init(pVulkanDevice)
I assume the -7 is a VkResult which means VK_ERROR_EXTENSION_NOT_PRESENT but this time it's reported by the Vulkan API. I'm not sure what to make of it.
On the other hand, why is AMF calling vkCreateDevice when I provide one.
I will able to check tomorrow but one thing I noticed: you created AMFVulkanDevice on stack so it will be destroyed at the end of the function. But AMF uses the pointer to this structure as a handle so you need to keep the structure alive.
Well, AMF should make a copy of the structure, otherwise the caller can change the values at any time and mix and match handle values. That's especially critical if the values are checked for validity at the beginning and later blindly used. It's a common security flaw.
In any case, the function is a thread handler and never returns. So the structure on stack is valid all the time.
Btw, AMF works beautifully with DX11 as backup solution. I have no issue with that, I just want to avoid the GPU/CPU/GPU memory transfer as currently I grab the Vulkan surface before presentation, and then return it in a ID3D11Texture2D back to the GPU. It has quite some impact for 4K 60 fps resolutions.
A background thread asynchronously uses AVC lossless encoding of the game rendering for analysis and diagnostic reasons. Overall it's working beautifully, I just want to remove the DX11 and Vulkan/DX11 bottleneck. And platform dependency.
I assume there is no public documentation of the AMD Vulkan Extension for HW Encoding. Functions vkGetPhysicalDeviceVideoDecodeCodecsAMD et al.
And thank you for the help.
This is done for consistency. Check how you can wrap a Vulkan texture into AMF surface. The AMFVulkanSurface needs to be filled in but the structure has members for synchronization : fences, semaphores and Boolean variables, all of them can be changed during execution. Copying the structure would make all this unusable. So for consistency all externally filled structures need to be stored. This is kind of symmetrical, AMF returns internal structures if they created inside and uses external structures created outside. The encoder and decoder extensions are private, can be changed at any time. Note that Khronos is working on public extensions. Does AMF sample work with the new driver? Another thought: do you enable Vulkan debug layers?
- the samples work find with the latest driver
- debug layers are not enabled (as you mentioned it doesn't work)
I will run another Vulkan API monitor to see if anyone is adding layers or removing extensions
- Hmmm. I checked the code for your latest log. It really came from vkCreateDevice call. This code branch is executed only if someone calls InitVulkan(nullptr).
- You've mentioned a separate instance of AMF context or Vulkan device. Could you please elaborate more?
- What is full list of instance extensions?
- What is full list of device extensions?
Is this still an issue?
Yes and No.
The issue still exists if anything else in the process is using D3D11. It does not matter what framework or library or UI. As long as there is an open D3D11 handle within the process. If not, then Vulkan works.
I worked around this by using a separate process for just Vulkan.
Could you please reproduce the issue by modifying one of AMF samples?
Hi there. I'm having the same issue too. Both VulkanInit(NULL) and VulkanInit(device) with a valid device ptr fail with AMF_FAIL. There is d3d11 stuff running in one of the libraries, so probably this is the cause here too. Was this issue addressed, or do you still need a repro case? I could provide an executable that tries to VulkanInit() and fails.
Or maybe it would be easier to wait until Vulkan video extensions will be available, what do you think? I only need to decode video for vulkan presentation.
It should work and so far we cannot reproduce this. So questions:
- Did you request Vulkan extensions as it is done in samples?
- Do you use the latest driver?
- What is AMF logging into debug output?
- Are you loading Vulkan DLL before asking AMF for list of needed extension?
Closing due to inactivity.