jgbit / vuda

VUDA is a header-only library based on Vulkan that provides a CUDA Runtime API interface for writing GPU-accelerated applications.
MIT License
862 stars 35 forks source link

VUDA and ErrorIncompatibleDriver #27

Open jxc100 opened 1 year ago

jxc100 commented 1 year ago

I'm new to Vuda, Vulkan and MoltenVK. I have the recent MoltenVK and the Vulkan SDK installed (and validation examples run - vkcube, vkvia and vulkaninfo) but I'm stuck with the simple VUDA example (https://github.com/jgbit/vuda) which compiles but returns an error at the line "cudaGetDeviceCount(&deviceCount);":

libc++abi: terminating with uncaught exception of type vk::IncompatibleDriverError: vk::createInstanceUnique: ErrorIncompatibleDriver

As best I understand it, this is a result of Vulkan requiring conformity - from Sascha Willems (https://stackoverflow.com/questions/72789012/why-does-vkcreateinstance-return-vk-error-incompatible-driver-on-macos-despite):

SDK 1.3.216 introduced a change in how devices are enumerated on MacOSX, and your code must make use of the portability subset extension to discover your devices (again).

There are some examples (not always in agreement) in various places about setting VkInstanceCreateInfo with the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR flag, and VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME but apparently a device also needs to be enabled.

How is this handled for CUDA code that I want to run with VUDA? In particular, how do I get past the "ErrorIncompatibleDriver" issue with the sample code? I have tried creating a VkInstance, and I can explicitly call vkEnumeratePhysicalDevices() and get back a count of 1 device (I'm using an M1 MacBook Pro) but the cudaGetDeviceCount() still returns "ErrorIncompatibleDriver".

Thanks for any pointers on this - James Conway

quadpixels commented 1 year ago

Try changing vuda::detail::Instance::get to the following:

static vk::UniqueInstance& get(void)
{
    // the initialization of the function local static variable is thread-safe.
    #ifdef __APPLE__
    vk::InstanceCreateInfo createInfo(
        vk::InstanceCreateFlags(VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR),
        &getInstanceCreateInfo());
    createInfo.enabledExtensionCount = 2;
    const char* exts[] = {
        VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,  // Mandatory for MacOS
        VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,  // Mandatory for MacOS
    };
    createInfo.ppEnabledExtensionNames = exts;
    static vk::UniqueInstance instance = vk::createInstanceUnique(createInfo);
    #else
    static vk::UniqueInstance instance = vk::createInstanceUnique(vk::InstanceCreateInfo(vk::InstanceCreateFlags(), &getInstanceCreateInfo()));
    #endif
    return instance;
}

I was able to run the "add" sample with the above changes. The above changes (the inclusion of the VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME and VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME extensions`) came from the Vulkan Tutorial.

jgbit commented 9 months ago

Try out the latest commit and let me know if it solves the issue. Thank you.

jxc100 commented 9 months ago

To quadpixles - sorry, I may have missed this when posted. However, I believe I had already tried something like that, but I will keep it in mind to move forward.

To jgbit - thanks for your response. I couldn't move forward last March so I dropped it, but I have run into another problem. Fortunately I left some usable notes behind, and I have recreated the Vulkan/MoltenVK set up on my M1 MBpro (OS 14.2.1) as follows:

So, at this point, I think the current Vulkan/MoltenVK setup is working. Next is Vuda:

../../inc/state/node_device.hpp:26:32: error: use of undeclared identifier 'VirtAlloc' m_ptrVirtual = VirtAlloc(size, m_allocatedSize); ^ ../../inc/state/node_device.hpp:45:17: error: use of undeclared identifier 'VirtFree' VirtFree(m_ptrVirtual, m_allocatedSize); ^

I see that ../../inc/state/node_device.hpp has a comment:

        This is 'unfortunately' requires an OS depedendent implementation, i.e. VirtualAlloc / mmap.

However, I don't know what this means - the undeclared function is "VirtAlloc" not "VirtualAlloc", and I am not familiar with the "mmap" function.

In file included from device_query.cpp:11: In file included from ../../inc/vuda_runtime.hpp:3: In file included from ../../inc/vuda.hpp:46: ../../inc/state/instance.hpp:99:7: error: use of undeclared identifier 'VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME' , VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME ^ ../../inc/state/instance.hpp:97:63: error: default initialization of an object of const type 'const std::array<const char , vk_extensionsNum>' without a user-provided default constructor static constexpr std::array<const char, vk_extensionsNum> vk_instanceextensions = {

I'm a bit out of depth here. Am I missing something simple?

Thanks again for your help.