Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 92 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,32 @@ unity-native-plugin = { version = "*", features = ["d3d11"] }
# * d3d12 - IUnityGraphicsD3D12
# * vulkan - IUnityGraphicsVulkan
# * metal - IUnityGraphicsMetal
# * profiler - IUnityProfiler
# * profiler_callbacks - IUnityProfilerCallbacks
# * profiler - IUnityProfiler / IUnityProfilerCallbacks
```

* Vulkan support has been integrated into `unity-native-plugin`. No separate crate needs to be added to your dependencies.

### Platform-specific features

The graphics features are gated by both a feature flag **and** a target `cfg`:

| Feature | Effective on |
| --- | --- |
| `d3d11`, `d3d12` | Windows (`cfg(windows)`) |
| `metal` | Apple platforms (`cfg(target_vendor = "apple")`) |
| `vulkan` | Cross-platform |
| `profiler` | Cross-platform |

Enabling a feature on a non-matching platform compiles silently as a no-op — the flag is accepted but the corresponding module (`unity_native_plugin::d3d11`, `unity_native_plugin::metal`, etc.) will not be present. This is intentional so that you can write a single `Cargo.toml` such as:

```toml
[dependencies]
unity-native-plugin = { version = "*", features = ["d3d11", "d3d12", "metal", "vulkan"] }
```

without per-platform `[target.'cfg(...)'.dependencies]` blocks. The unused features
have no runtime cost.

* Use a macro in lib.rs to define your entry points. Without this definition, UnityInterfaces cannot be used.
```rust
unity_native_plugin::unity_native_plugin_entry_point! {
Expand All @@ -44,3 +64,73 @@ let intf = unity_native_plugin::interface::UnityInterfaces::get()
* [unity-native-plugin-sample](./unity-native-plugin-sample)
* [Native code (Rust) rendering plugin example for Unity](https://github.com/aosoft/unity-native-rendering-plugin-example-rs) - a port of ["C++ Rendering Plugin example for Unity"](https://github.com/Unity-Technologies/NativeRenderingPlugin)
* [Event tracing example for unity](./unity-native-plugin-sample-profiler) - similar to ["TraceEventProfiler from Unity-Technologies"](https://github.com/Unity-Technologies/TraceEventProfiler)

## Migration guide: 0.8 → 0.9

### `Cargo.toml`

* **The `unity-native-plugin-vulkan` crate has been removed.** Vulkan support is now an opt-in feature of `unity-native-plugin` itself.

```toml
# Before (0.8)
unity-native-plugin = "0.8"
unity-native-plugin-vulkan = "0.8"

# After (0.9)
unity-native-plugin = { version = "0.9", features = ["vulkan"] }
```

* **The `profiler_callbacks` feature has been merged into `profiler`.** Enabling `profiler` now exposes both `IUnityProfiler` and `IUnityProfilerCallbacks`.

```toml
# Before
features = ["profiler", "profiler_callbacks"]
# After
features = ["profiler"]
```

### Module paths

* `unity_native_plugin_vulkan::vulkan::*` → `unity_native_plugin::vulkan::*`
* `unity_native_plugin::d3d11::ComPtr` / `unity_native_plugin::d3d12::ComPtr` → `unity_native_plugin::windows::ComPtr`

### Methods are now provided through `*Interface` traits

The inherent `impl` blocks on `UnityGraphicsD3D11`, `UnityGraphicsD3D12*`, `UnityGraphicsMetal*` and `UnityGraphicsVulkan*` have been replaced with traits that mirror the underlying `IUnityGraphics*` C interfaces. To call any method, bring the matching trait into scope:

```rust
use unity_native_plugin::d3d11::UnityGraphicsD3D11Interface;
use unity_native_plugin::d3d12::{
UnityGraphicsD3D12Interface, // for UnityGraphicsD3D12
UnityGraphicsD3D12V2Interface, // for UnityGraphicsD3D12v2
UnityGraphicsD3D12v3Interface, // ... v3 .. v8Interface for the corresponding interface versions
};
use unity_native_plugin::metal::{UnityGraphicsMetalV1Interface, UnityGraphicsMetalV2Interface};
use unity_native_plugin::vulkan::{UnityGraphicsVulkanInterface, UnityGraphicsVulkanV2Interface};
```

Without the corresponding `use`, methods such as `device()`, `command_queue()` or `command_recording_state()` will appear to be missing.

### Renamed identifiers

* D3D11 typo fixes (call sites must be updated):
* `texture_from_natvie_texture` → `texture_from_native_texture`
* `srv_from_natvie_texture` → `srv_from_native_texture`
* `graphics::GfxRenderer::ReservedCFE` → `graphics::GfxRenderer::Nvn2`

### Vulkan: `VulkanInstance::get_instance_proc_addr` return type

The return type changed from a sys-defined enum to the standard `ash` function-pointer type, so the caller now matches on `Option` instead of the custom `None` variant.

```rust
// Before (0.8)
match instance.get_instance_proc_addr(name) {
PFN_vkVoidFunction::None => { /* not found */ }
other => { /* use other */ }
}

// After (0.9)
if let Some(f) = instance.get_instance_proc_addr(name) {
// use f
}
```
2 changes: 1 addition & 1 deletion unity-native-plugin-sample-profiler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ crate-type = ["cdylib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
unity-native-plugin = { version = "0.9.0", path = "../unity-native-plugin", features = ["profiler_callbacks"] }
unity-native-plugin = { version = "0.9.0", path = "../unity-native-plugin", features = ["profiler"] }
unity-native-plugin-sys = { version = "0.9.0", path = "../unity-native-plugin-sys" }
log = "0.4"
env_logger = "0.8"
Expand Down
1 change: 1 addition & 0 deletions unity-native-plugin-sample/src/d3d11.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use unity_native_plugin::d3d11::UnityGraphicsD3D11Interface;
use winapi::shared::dxgiformat;
use winapi::um::{d3d11, unknwnbase::IUnknown};
use wio::com::ComPtr;
Expand Down
3 changes: 3 additions & 0 deletions unity-native-plugin-sample/src/d3d12.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use unity_native_plugin::d3d12::{
UnityGraphicsD3D12V2Interface, UnityGraphicsD3D12v6Interface, UnityGraphicsD3D12v8Interface,
};
use winapi::Interface;
use winapi::um::d3d12::*;
use wio::com::ComPtr;
Expand Down
3 changes: 3 additions & 0 deletions unity-native-plugin-sample/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ mod vulkan;
use std::ffi::c_void;
use std::os::raw::c_int;

#[cfg(windows)]
use unity_native_plugin::d3d12::UnityGraphicsD3D12v6Interface;
use unity_native_plugin::graphics::GfxRenderer;
use unity_native_plugin::vulkan::UnityGraphicsVulkanInterface;

const FILL_TEXTURE_EVENT_ID: c_int = 0;

Expand Down
2 changes: 1 addition & 1 deletion unity-native-plugin-sample/src/metal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use objc2_metal::{
};

use unity_native_plugin::interface::UnityInterfaces;
use unity_native_plugin::metal::objc2::{
use unity_native_plugin::metal::{
UnityGraphicsMetalV1, UnityGraphicsMetalV1Interface, UnityGraphicsMetalV2,
};

Expand Down
13 changes: 3 additions & 10 deletions unity-native-plugin-sample/src/vulkan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,9 @@ use std::ffi::c_void;
use unity_native_plugin::ash::vk;
use unity_native_plugin::ash::vk::Handle;
use unity_native_plugin::vulkan::{
UnityGraphicsVulkan, VulkanGraphicsQueueAccess, VulkanResourceAccessMode,
UnityGraphicsVulkan, UnityGraphicsVulkanInterface, VulkanGraphicsQueueAccess,
VulkanResourceAccessMode,
};
use unity_native_plugin_sys::PFN_vkVoidFunction;

unsafe fn unwrap_pfn(f: PFN_vkVoidFunction) -> Option<unsafe extern "system" fn()> {
match f {
PFN_vkVoidFunction::Some(f) => Some(f),
PFN_vkVoidFunction::None => None,
}
}

pub fn fill_texture(unity_texture: *mut c_void, x: f32, y: f32, z: f32, w: f32) {
unsafe {
Expand Down Expand Up @@ -50,7 +43,7 @@ pub fn fill_texture(unity_texture: *mut c_void, x: f32, y: f32, z: f32, w: f32)
// corrupting internal state and causing a crash.
let vk_instance = intf.instance();

let pfn = unwrap_pfn(vk_instance.get_instance_proc_addr(c"vkGetDeviceProcAddr".as_ptr()));
let pfn = vk_instance.get_instance_proc_addr(c"vkGetDeviceProcAddr".as_ptr());
let vk_get_device_proc_addr: vk::PFN_vkGetDeviceProcAddr = match pfn {
Some(f) => std::mem::transmute::<
unsafe extern "system" fn(),
Expand Down
1 change: 0 additions & 1 deletion unity-native-plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ d3d12 = []
metal = ["dep:objc2", "dep:objc2-foundation", "dep:objc2-metal"]
vulkan = ["dep:ash", "unity-native-plugin-sys/vulkan"]
profiler = []
profiler_callbacks = ["profiler"]

[dependencies]
ash = { version = "0.38.0", optional = true }
Expand Down
101 changes: 58 additions & 43 deletions unity-native-plugin/src/d3d11.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::define_unity_interface;
use crate::graphics;
use crate::interface::UnityInterface;
use crate::windows::ComPtr;

define_unity_interface!(
UnityGraphicsD3D11,
Expand All @@ -9,54 +9,69 @@ define_unity_interface!(
0xBF76967F07EFB177_u64
);

pub type ComPtr = *mut std::ffi::c_void;
pub trait UnityGraphicsD3D11Interface {
unsafe fn device(&self) -> ComPtr;
unsafe fn texture_from_render_buffer(&self, buffer: graphics::RenderBuffer) -> ComPtr;
unsafe fn texture_from_native_texture(&self, texture: graphics::TextureID) -> ComPtr;
unsafe fn rtv_from_render_buffer(&self, buffer: graphics::RenderBuffer) -> ComPtr;
unsafe fn srv_from_native_texture(&self, texture: graphics::TextureID) -> ComPtr;
unsafe fn swap_chain(&self) -> ComPtr;
fn sync_interval(&self) -> u32;
fn present_flags(&self) -> u32;
}

impl UnityGraphicsD3D11 {
pub unsafe fn device(&self) -> ComPtr {
unsafe { self.interface().GetDevice.expect("GetDevice")() as ComPtr }
}
macro_rules! impl_d3d11 {
($intf:ty) => {
impl UnityGraphicsD3D11Interface for $intf {
unsafe fn device(&self) -> ComPtr {
unsafe { self.interface().GetDevice.expect("GetDevice")() as ComPtr }
}

pub unsafe fn texture_from_render_buffer(&self, buffer: graphics::RenderBuffer) -> ComPtr {
unsafe {
self.interface()
.TextureFromRenderBuffer
.expect("TextureFromRenderBuffer")(buffer) as ComPtr
}
}
unsafe fn texture_from_render_buffer(&self, buffer: graphics::RenderBuffer) -> ComPtr {
unsafe {
self.interface()
.TextureFromRenderBuffer
.expect("TextureFromRenderBuffer")(buffer) as ComPtr
}
}

pub unsafe fn texture_from_natvie_texture(&self, texture: graphics::TextureID) -> ComPtr {
unsafe {
self.interface()
.TextureFromNativeTexture
.expect("TextureFromNativeTexture")(texture) as ComPtr
}
}
unsafe fn texture_from_native_texture(&self, texture: graphics::TextureID) -> ComPtr {
unsafe {
self.interface()
.TextureFromNativeTexture
.expect("TextureFromNativeTexture")(texture) as ComPtr
}
}

pub unsafe fn rtv_from_render_buffer(&self, buffer: graphics::RenderBuffer) -> ComPtr {
unsafe {
self.interface()
.RTVFromRenderBuffer
.expect("RTVFromRenderBuffer")(buffer) as ComPtr
}
}
unsafe fn rtv_from_render_buffer(&self, buffer: graphics::RenderBuffer) -> ComPtr {
unsafe {
self.interface()
.RTVFromRenderBuffer
.expect("RTVFromRenderBuffer")(buffer) as ComPtr
}
}

pub unsafe fn srv_from_natvie_texture(&self, texture: graphics::TextureID) -> ComPtr {
unsafe {
self.interface()
.SRVFromNativeTexture
.expect("SRVFromNativeTexture")(texture) as ComPtr
}
}
unsafe fn srv_from_native_texture(&self, texture: graphics::TextureID) -> ComPtr {
unsafe {
self.interface()
.SRVFromNativeTexture
.expect("SRVFromNativeTexture")(texture) as ComPtr
}
}

pub unsafe fn swap_chain(&self) -> ComPtr {
unsafe { self.interface().GetSwapChain.expect("GetSwapChain")() as ComPtr }
}
unsafe fn swap_chain(&self) -> ComPtr {
unsafe { self.interface().GetSwapChain.expect("GetSwapChain")() as ComPtr }
}

pub fn sync_interval(&self) -> u32 {
unsafe { self.interface().GetSyncInterval.expect("GetSyncInterval")() }
}
fn sync_interval(&self) -> u32 {
unsafe { self.interface().GetSyncInterval.expect("GetSyncInterval")() }
}

pub fn present_flags(&self) -> u32 {
unsafe { self.interface().GetPresentFlags.expect("GetPresentFlags")() }
}
fn present_flags(&self) -> u32 {
unsafe { self.interface().GetPresentFlags.expect("GetPresentFlags")() }
}
}
};
}

impl_d3d11!(UnityGraphicsD3D11);
Loading
Loading