# 低级原生插件接口

> Implement low-level rendering in your native plug-ins.

Unity 中的[原生插件](/engine/6000.0/manual/scripting/compilation-and-code-reload/plug-ins/native.md)可以在发生某些事件时接收回调。此功能可用于实现插件中的低级渲染，以便低级渲染能够与 Unity 的多线程渲染一起使用。

## 接口注册表##additional-resources

要处理主要的 Unity 事件，插件必须导出 `UnityPluginLoad` 和 `UnityPluginUnload` 函数。IUnityInterfaces 使插件能够访问这些函数，您可以在插件 API 中的 `IUnityInterface.h` 中找到这些函数：

```
#include "IUnityInterface.h"
#include "IUnityGraphics.h"
// Unity plugin load event
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
    UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
    IUnityGraphics* graphics = unityInterfaces->Get<IUnityGraphics>();
}
```

## 访问图形设备

使用 `IUnityGraphics` 接口（可在 `IUnityGraphics.h` 中找到）可让插件访问通用图形设备功能。此脚本演示了如何使用 `IUnityGraphics` 接口注册回调：

```
#include "IUnityInterface.h"
#include "IUnityGraphics.h"
    
static IUnityInterfaces* s_UnityInterfaces = NULL;
static IUnityGraphics* s_Graphics = NULL;
static UnityGfxRenderer s_RendererType = kUnityGfxRendererNull;
    
// Unity plugin load event
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
    UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
    s_UnityInterfaces = unityInterfaces;
    s_Graphics = unityInterfaces->Get<IUnityGraphics>();
        
    s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent);
        
    // Run OnGraphicsDeviceEvent(initialize) manually on plugin load
    // to not miss the event in case the graphics device is already initialized
    OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize);
}
    
// Unity plugin unload event
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
    UnityPluginUnload()
{
    s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent);
}
    
static void UNITY_INTERFACE_API
    OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType)
{
    switch (eventType)
    {
        case kUnityGfxDeviceEventInitialize:
        {
            s_RendererType = s_Graphics->GetRenderer();
            //TODO: user initialization code on graphics device initialization. 
            For example, D3D11 resource creation.
            break;
        }
        case kUnityGfxDeviceEventShutdown:
        {
            s_RendererType = kUnityGfxRendererNull;
            //TODO: user graphics API code to call on graphics device shutdown.
            break;
        }
        case kUnityGfxDeviceEventBeforeReset:
        {
            //TODO: user graphics API code to call before graphics device reset.
            break;
        }
        case kUnityGfxDeviceEventAfterReset:
        {
            //TODO: user graphics API code to call after graphics device reset.
            break;
        }
    };
}
```

## 渲染线程上的插件回调

如果平台和可用 CPU 数量允许，可以使用多线程在 Unity 中进行渲染。

**注意**：当使用多线程渲染时，执行渲染 API 命令的线程完全独立于运行 MonoBehaviour 脚本的线程。主线程和渲染线程之间的通信意味着插件可能无法立即开始渲染，具体取决于主线程向渲染线程推送的工作量。

要从插件渲染，请从托管插件脚本调用 [GL.IssuePluginEvent](/engine/6000.0/script-reference/unity-engine/gl/issue-plugin-event.md)。这会导致 Unity 的渲染管线从渲染线程调用原生函数，如下代码示例所示。例如，如果从摄像机的 OnPostRender 函数调用 GL.IssuePluginEvent，则在该摄像机已完成渲染后，函数将立即调用插件回调。

原生插件代码：

```
// Plugin function to handle a specific rendering event
static void UNITY_INTERFACE_API OnRenderEvent(int eventID)
{
    // User rendering code
}
    
// Freely defined function to pass a callback to plugin-specific scripts
extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
    GetRenderEventFunc()
{
    return OnRenderEvent;
}
```

托管插件代码：

```
#if UNITY_IPHONE && !UNITY_EDITOR
[DllImport ("__Internal")]
#else
[DllImport("RenderingPlugin")]
#endif
private static extern IntPtr GetRenderEventFunc();
    
// Queue a specific callback to be called on the render thread
GL.IssuePluginEvent(GetRenderEventFunc(), 1);
```

[原生渲染插件示例的 IUnityGraphics.h](https://github.com/Unity-Technologies/NativeRenderingPlugin/tree/master/PluginSource/source/Unity) 中提供了 `UnityRenderingEvent` 回调的签名。

## 使用 OpenGL 图形 API 的插件

有两种 OpenGL 对象：

* **OpenGL 上下文共享的对象**，例如纹理、缓冲区、渲染缓冲区、采样器、查询、着色器和程序对象。
* **Per-OpenGL 上下文对象**，例如顶点数组、帧缓冲区、程序管线、变换反馈和同步对象。

Unity 使用多个 OpenGL 上下文。在初始化和关闭编辑器和播放器时，Unity 依赖于主上下文，但我们使用专用上下文进行渲染。即，在 `kUnityGfxDeviceEventInitialize` 和 `kUnityGfxDeviceEventShutdown` 事件期间无法创建每个上下文的对象。

## 其他资源

* [低级原生插件渲染扩展](/engine/6000.0/manual/scripting/compilation-and-code-reload/plug-ins/native-plugin-interface/low-level-native-plugin-rendering-extensions.md)
* [低级原生插件着色器编译器访问](/engine/6000.0/manual/scripting/compilation-and-code-reload/plug-ins/native-plugin-interface/low-level-native-plugin-shader-compiler-access.md)
* [低级原生插件内存管理器 API](/engine/6000.0/manual/scripting/compilation-and-code-reload/plug-ins/native-plugin-interface/low-level-native-plugin-memory-manager-api.md)
* [低级原生插件内存管理器 API 参考](/engine/6000.0/manual/scripting/compilation-and-code-reload/plug-ins/native-plugin-interface/low-level-native-plugin-memory-manager-api/reference.md)
