unity-native-plugin 0.8.0

Unity Native Plugin API for Rust
Documentation
use crate::{bitflag, define_unity_interface};
use crate::graphics;
use crate::interface::UnityInterface;
use unity_native_plugin_sys::*;

define_unity_interface!(
    UnityGraphicsD3D12,
    IUnityGraphicsD3D12,
    0xEF4CEC88A45F4C4C_u64,
    0xBD295B6F2A38D9DE_u64
);

pub type ComPtr = *mut std::ffi::c_void;

#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum GraphicsQueueAccess {
    DontCare = UnityD3D12GraphicsQueueAccess_kUnityD3D12GraphicsQueueAccess_DontCare,
    Allow = UnityD3D12GraphicsQueueAccess_kUnityD3D12GraphicsQueueAccess_Allow,
}

#[repr(u32)]
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum EventConfigFlagBit {
    EnsurePreviousFrameSubmission = UnityD3D12EventConfigFlagBits_kUnityD3D12EventConfigFlag_EnsurePreviousFrameSubmission,
    FlushCommandBuffers = UnityD3D12EventConfigFlagBits_kUnityD3D12EventConfigFlag_FlushCommandBuffers,
    SyncWorkerThreads = UnityD3D12EventConfigFlagBits_kUnityD3D12EventConfigFlag_SyncWorkerThreads,
    ModifiesCommandBuffersState = UnityD3D12EventConfigFlagBits_kUnityD3D12EventConfigFlag_ModifiesCommandBuffersState,
}

bitflag!(EventConfigFlagBits, EventConfigFlagBit, u32);

#[derive(Copy, Clone)]
pub struct PluginEventConfig {
    pub graphics_queue_access: GraphicsQueueAccess,
    pub flags: EventConfigFlagBits,
    pub ensure_active_render_texture_is_bound: bool,
}

macro_rules! impl_d3d12_v2 {
    () => {
        pub unsafe fn device(&self) -> ComPtr {
            unsafe {
                self.interface().GetDevice.expect("GetDevice")() as ComPtr
            }
        }

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

        pub fn next_frame_fence_value(&self) -> u64 {
            unsafe {
                self.interface()
                    .GetNextFrameFenceValue
                    .expect("GetNextFrameFenceValue")() as u64
            }
        }
    };
}

macro_rules! impl_d3d12 {
    () => {
        impl_d3d12_v2!();

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

        pub fn resource_state(&self, resource: ComPtr) -> Option<i32> {
            unsafe {
                let mut ret: D3D12_RESOURCE_STATES = D3D12_RESOURCE_STATES::default();
                if self.interface().GetResourceState.expect("GetResourceState")(
                    resource as *mut ID3D12Resource,
                    &mut ret as *mut D3D12_RESOURCE_STATES,
                ) {
                    Some(ret)
                } else {
                    None
                }
            }
        }

        pub fn set_resource_state(&self, resource: ComPtr, state: i32) {
            unsafe {
                self.interface().SetResourceState.expect("SetResourceState")(
                    resource as *mut ID3D12Resource,
                    state,
                )
            }
        }
    };
}

impl UnityGraphicsD3D12 {
    impl_d3d12!();
}

define_unity_interface!(
    UnityGraphicsD3D12v2,
    IUnityGraphicsD3D12v2,
    0xEC39D2F18446C745_u64,
    0xB1A2626641D6B11F_u64
);

pub type ResourceState = UnityGraphicsD3D12ResourceState;

impl UnityGraphicsD3D12v2 {
    impl_d3d12_v2!();
}

define_unity_interface!(
    UnityGraphicsD3D12v3,
    IUnityGraphicsD3D12v3,
    0x57C3FAFE59E5E843_u64,
    0xBF4F5998474BB600_u64
);

macro_rules! impl_d3d12_v3 {
    () => {
        impl_d3d12_v2!();

        pub fn set_physical_video_memory_control_values(
            &self,
            mem_info: &PhysicalVideoMemoryControlValues,
        ) {
            unsafe {
                self.interface()
                    .SetPhysicalVideoMemoryControlValues
                    .expect("SetPhysicalVideoMemoryControlValues")(
                    mem_info as *const UnityGraphicsD3D12PhysicalVideoMemoryControlValues,
                )
            }
        }
    };
}

pub type PhysicalVideoMemoryControlValues = UnityGraphicsD3D12PhysicalVideoMemoryControlValues;

impl UnityGraphicsD3D12v3 {
    impl_d3d12_v3!();
}

define_unity_interface!(
    UnityGraphicsD3D12v4,
    IUnityGraphicsD3D12v4,
    0x498FFCC13EC94006_u64,
    0xB18F8B0FF67778C8_u64
);

macro_rules! impl_d3d12_v4 {
    () => {
        impl_d3d12_v3!();

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

impl UnityGraphicsD3D12v4 {
    impl_d3d12_v4!();
}

define_unity_interface!(
    UnityGraphicsD3D12v5,
    IUnityGraphicsD3D12v5,
    0xF5C8D8A37D37BC42_u64,
    0xB02DFE93B5064A27_u64
);

macro_rules! impl_d3d12_v5 {
    () => {
        impl_d3d12_v4!();

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

impl UnityGraphicsD3D12v5 {
    impl_d3d12_v5!();
}

define_unity_interface!(
    UnityGraphicsD3D12v6,
    IUnityGraphicsD3D12v6,
    0xA396DCE58CAC4D78_u64,
    0xAFDD9B281F20B840_u64
);

macro_rules! impl_d3d12_v6 {
    () => {
        impl_d3d12_v5!();

        pub fn configure_event(&self, event_id: i32, plugin_event_config: &PluginEventConfig) {
            unsafe {
                let cfg = UnityD3D12PluginEventConfig {
                    graphicsQueueAccess: plugin_event_config.graphics_queue_access as UnityD3D12GraphicsQueueAccess,
                    flags: plugin_event_config.flags.flag,
                    ensureActiveRenderTextureIsBound: plugin_event_config.ensure_active_render_texture_is_bound,
                };
                self.interface()
                    .ConfigureEvent
                    .expect("ConfigureEvent")(event_id, &cfg)
            }
        }

        pub unsafe fn command_recording_state(&self) -> Option<ComPtr> {
            unsafe {
                let mut state: UnityGraphicsD3D12RecordingState = std::mem::zeroed();
                if self.interface().CommandRecordingState.expect("CommandRecordingState")(&mut state) {
                    Some(state.commandList as ComPtr)
                } else {
                    None
                }
            }
        }
    }
}
impl UnityGraphicsD3D12v6 {
    impl_d3d12_v6!();
}

define_unity_interface!(
    UnityGraphicsD3D12v7,
    IUnityGraphicsD3D12v7,
    0x4624B0DA41B64AAC_u64,
    0x915AABCB9BC3F0D3_u64
);

macro_rules! impl_d3d12_v7 {
    () => {
        impl_d3d12_v6!();

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

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

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