Skip to content

rudybear/unity-vulkan-interop

Repository files navigation

Unity External Vulkan Device Interop

This project provides a complete, working solution for integrating an external Vulkan device with Unity's native rendering plugin. It supports two approaches:

  1. Device Interception - Provide your own VkDevice to Unity (similar to OpenXR)
  2. Resource Sharing - Share resources between your device and Unity's device

Features

  • ✅ Fully compilable and working code
  • ✅ Device interception using IUnityGraphicsVulkanV2
  • ✅ Create your own Vulkan device before Unity initializes
  • ✅ Provide external VkInstance, VkPhysicalDevice, VkDevice to Unity
  • ✅ C# wrapper for easy Unity integration
  • ✅ Cross-platform support (Windows, macOS, Linux, Android)
  • ✅ Example usage scripts

Project Structure

unityexternalvulkan/
├── CMakeLists.txt                          # Build configuration
├── include/                                # Header files
│   ├── IUnityInterface.h                   # Unity plugin interface
│   ├── IUnityGraphics.h                    # Unity graphics interface
│   ├── IUnityGraphicsVulkan.h              # Unity Vulkan interface (V2)
│   ├── VulkanDeviceManager.h               # Your external device manager
│   └── UnityVulkanPlugin.h                 # Plugin API
├── src/                                    # Implementation files
│   ├── VulkanDeviceManager.cpp             # External device creation
│   └── UnityVulkanPlugin.cpp               # Plugin implementation
└── UnityProject/Assets/Scripts/            # Unity C# scripts
    ├── VulkanInterop.cs                    # C# wrapper
    └── VulkanInteropExample.cs             # Example usage

Building the Plugin

Prerequisites

  • CMake 3.15 or higher
  • Vulkan SDK installed
  • C++17 compatible compiler
  • macOS: Xcode command line tools
  • Linux: GCC/Clang
  • Windows: Visual Studio 2019+

macOS Build

# Install Vulkan SDK
# Download from https://vulkan.lunarg.com/sdk/home

# Build the plugin
mkdir build
cd build
cmake ..
make

# The plugin will be output to: UnityProject/Assets/Plugins/libUnityVulkanInterop.bundle

Linux Build

# Install Vulkan SDK
sudo apt-get install vulkan-sdk

# Build the plugin
mkdir build
cd build
cmake ..
make

# The plugin will be output to: UnityProject/Assets/Plugins/libUnityVulkanInterop.so

Windows Build

# Install Vulkan SDK from https://vulkan.lunarg.com/sdk/home

# Build the plugin
mkdir build
cd build
cmake ..
cmake --build . --config Release

# The plugin will be output to: UnityProject/Assets/Plugins/UnityVulkanInterop.dll

Unity Setup

1. Import the Plugin

  1. Copy the built plugin to your Unity project:

    • macOS: libUnityVulkanInterop.bundleAssets/Plugins/
    • Linux: libUnityVulkanInterop.soAssets/Plugins/
    • Windows: UnityVulkanInterop.dllAssets/Plugins/
  2. Copy the C# scripts:

    • VulkanInterop.csAssets/Scripts/
    • VulkanInteropExample.csAssets/Scripts/

2. Configure Unity for Vulkan

  1. Go to Edit → Project Settings → Player
  2. Under Other Settings, set:
    • Graphics APIs: Remove all except Vulkan
    • Color Space: Linear (recommended)
  3. Click Apply

3. Use the Plugin

Option A: Automatic Initialization (Recommended)

Add VulkanInteropExample.cs to a GameObject in your first scene. The script uses [RuntimeInitializeOnLoadMethod] to initialize before Unity creates its graphics device.

// This happens automatically via the RuntimeInitializeOnLoadMethod attribute
// No manual setup required!

Option B: Manual Initialization

If you need more control, call the initialization manually:

using UnityEngine;

public class CustomVulkanSetup
{
    [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)]
    static void Initialize()
    {
        // Enable device interception
        VulkanInterop.EnableDeviceInterception(true);

        // Initialize your external Vulkan device
        bool success = VulkanInterop.InitializeExternalDevice();

        if (success)
        {
            // Get device handles
            IntPtr instance, device, physicalDevice;
            VulkanInterop.GetDeviceInfo(out instance, out device, out physicalDevice);

            Debug.Log($"External VkDevice: 0x{device.ToInt64():X}");
            // Unity will now use your external device!
        }
    }
}

How It Works

Device Interception Flow

1. Unity loads plugin → UnityPluginLoad() called
2. Plugin registers device event callback
3. Your code calls InitializeExternalVulkanDevice()
   → Creates VkInstance, VkPhysicalDevice, VkDevice
4. Unity initializes graphics
   → Plugin's OnVulkanInitializationCallback() is called
   → Plugin provides external device to Unity
5. Unity uses your external device for all rendering!

Key Components

VulkanDeviceManager

Creates and manages your external Vulkan device:

VulkanDeviceManager deviceMgr;
deviceMgr.InitializeExternalDevice();
// Now you have: VkInstance, VkPhysicalDevice, VkDevice, VkQueue

Device Interception Callback

The plugin intercepts Unity's initialization:

void OnVulkanInitializationCallback(const UnityVulkanPluginEventConfig* config)
{
    // Provide your external device to Unity
    initData->instanceOverride = myVkInstance;
    initData->deviceOverride = myVkDevice;
    initData->physicalDeviceOverride = myVkPhysicalDevice;
    // Unity will now use YOUR device!
}

Integrating Your Own Vulkan Library

To use your own existing Vulkan device:

1. Modify VulkanDeviceManager

Replace the device creation in VulkanDeviceManager.cpp:

bool VulkanDeviceManager::InitializeExternalDevice()
{
    // Instead of creating a new device:
    // m_instance = YourLibrary::GetVkInstance();
    // m_device = YourLibrary::GetVkDevice();
    // m_physicalDevice = YourLibrary::GetVkPhysicalDevice();
    // m_graphicsQueue = YourLibrary::GetVkQueue();
    // m_queueFamilyIndex = YourLibrary::GetQueueFamilyIndex();

    m_initialized = true;
    return true;
}

2. Link Your Library

Update CMakeLists.txt:

# Add your library
find_library(YOUR_VULKAN_LIB YourVulkanLib PATHS /path/to/lib)

target_link_libraries(UnityVulkanInterop PRIVATE
    ${Vulkan_LIBRARIES}
    ${YOUR_VULKAN_LIB}
)

3. Rebuild

cd build
cmake ..
make

Testing

1. Build the Plugin

mkdir build && cd build
cmake ..
make

2. Run in Unity

  1. Open Unity project
  2. Ensure Vulkan is the graphics API
  3. Add VulkanInteropExample.cs to a GameObject
  4. Click Play

3. Check Console Output

You should see:

[VulkanInteropExample] BeforeSplashScreen - Setting up Vulkan device interception
[VulkanDeviceManager] Initializing external Vulkan device...
[VulkanDeviceManager] External Vulkan device initialized successfully
[UnityVulkanPlugin] Vulkan initialization intercept callback triggered!
[UnityVulkanPlugin] Providing external Vulkan device to Unity
[UnityVulkanPlugin] External device successfully provided to Unity

Advanced: Resource Sharing

If you need to share resources between your device and Unity's device:

// Enable external memory extensions in VulkanDeviceManager.cpp
m_deviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
m_deviceExtensions.push_back(VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);

#ifdef _WIN32
m_deviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
#else
m_deviceExtensions.push_back(VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
#endif

Then create shared images/buffers with external memory:

VkExternalMemoryImageCreateInfo externalInfo = {};
externalInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
externalInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;

VkImageCreateInfo imageInfo = {};
imageInfo.pNext = &externalInfo;
// ... other image parameters

Troubleshooting

Plugin Not Loading

  • Check the plugin is in Assets/Plugins/
  • Verify Vulkan SDK is installed
  • Check Unity console for error messages

Device Interception Not Working

  • Ensure initialization happens BEFORE Unity graphics init
  • Use RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSplashScreen)
  • Check that Vulkan is the selected graphics API

Build Errors

macOS:

# If Vulkan SDK not found
export VULKAN_SDK=/path/to/vulkansdk

Linux:

# Install missing dependencies
sudo apt-get install libvulkan-dev vulkan-tools

Windows:

# Set Vulkan SDK path
set VULKAN_SDK=C:\VulkanSDK\1.x.xxx.x

References

License

This is example code for educational purposes. Use it as a starting point for your own projects.

Support

For issues or questions:

  1. Check the Unity console logs
  2. Verify plugin is loaded: Look for [UnityVulkanPlugin] Plugin loaded
  3. Check device interception: Look for Providing external Vulkan device to Unity

About

Unity native plugin for integrating external Vulkan devices - Device interception using IUnityGraphicsVulkanV2

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors