diff --git a/README.md b/README.md index 492029c..716a240 100644 --- a/README.md +++ b/README.md @@ -94,22 +94,39 @@ let intf = unity_native_plugin::interface::UnityInterfaces::get() * `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 +### Methods are now provided through 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: +The inherent `impl` blocks on the wrapper types have been replaced with traits. Each trait is published under **two names**: + +* a Rust-conventional `*Interface` name (the canonical one — e.g. `UnityGraphicsD3D11Interface`) +* an `IUnity*` alias that matches Unity's C header name 1:1 (e.g. `IUnityGraphicsD3D11`) + +Use whichever name you prefer; they refer to the same trait. To call any method, bring it into scope: ```rust +// Pick either form per import; both resolve to the same trait. +use unity_native_plugin::graphics::UnityGraphicsInterface; // or IUnityGraphics +use unity_native_plugin::log::UnityLogInterface; // or IUnityLog +use unity_native_plugin::memory_manager::UnityMemoryManagerInterface; // or IUnityMemoryManager +use unity_native_plugin::profiler::{UnityProfilerInterface, UnityProfilerV2Interface}; +use unity_native_plugin::profiler_callbacks::{ + UnityProfilerCallbacksInterface, UnityProfilerCallbacksV2Interface, +}; + 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 + UnityGraphicsD3D12v2Interface, // for UnityGraphicsD3D12v2 + UnityGraphicsD3D12v3Interface, // ... v3 .. v8 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. +Without the corresponding `use`, methods such as `renderer()`, `log()`, `device()`, `command_queue()`, `emit_event()`, `register_create_marker()` etc. will appear to be missing. + +Notes: +* The marker trait `unity_native_plugin::interface::UnityInterface` is **not** a Unity-API wrapper — it is a Rust-only marker used by `UnityInterfaces::interface::()` for GUID-based lookup. It does not have an `IUnity*` alias because it does not correspond 1:1 to any Unity header type. ### Renamed identifiers diff --git a/unity-native-plugin-sample-profiler/src/lib.rs b/unity-native-plugin-sample-profiler/src/lib.rs index 5ee2a95..de5733b 100644 --- a/unity-native-plugin-sample-profiler/src/lib.rs +++ b/unity-native-plugin-sample-profiler/src/lib.rs @@ -3,7 +3,7 @@ use std::io::*; use std::num::NonZeroU64; use std::time::*; use unity_native_plugin::profiler::*; -use unity_native_plugin::profiler_callbacks::*; +use unity_native_plugin::profiler_callbacks::{IUnityProfilerCallbacks, *}; unity_native_plugin::unity_native_plugin_entry_point! { fn unity_plugin_load(interfaces: &unity_native_plugin::interface::UnityInterfaces) { diff --git a/unity-native-plugin-sample/src/d3d11.rs b/unity-native-plugin-sample/src/d3d11.rs index eb9d71b..7d85b67 100644 --- a/unity-native-plugin-sample/src/d3d11.rs +++ b/unity-native-plugin-sample/src/d3d11.rs @@ -1,4 +1,4 @@ -use unity_native_plugin::d3d11::UnityGraphicsD3D11Interface; +use unity_native_plugin::d3d11::IUnityGraphicsD3D11; use winapi::shared::dxgiformat; use winapi::um::{d3d11, unknwnbase::IUnknown}; use wio::com::ComPtr; diff --git a/unity-native-plugin-sample/src/d3d12.rs b/unity-native-plugin-sample/src/d3d12.rs index 0fd490b..695ecd3 100644 --- a/unity-native-plugin-sample/src/d3d12.rs +++ b/unity-native-plugin-sample/src/d3d12.rs @@ -1,5 +1,5 @@ use unity_native_plugin::d3d12::{ - UnityGraphicsD3D12V2Interface, UnityGraphicsD3D12v6Interface, UnityGraphicsD3D12v8Interface, + IUnityGraphicsD3D12v2, IUnityGraphicsD3D12v6, IUnityGraphicsD3D12v8, }; use winapi::Interface; use winapi::um::d3d12::*; diff --git a/unity-native-plugin-sample/src/lib.rs b/unity-native-plugin-sample/src/lib.rs index abf7783..b1764e7 100644 --- a/unity-native-plugin-sample/src/lib.rs +++ b/unity-native-plugin-sample/src/lib.rs @@ -10,9 +10,9 @@ 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; +use unity_native_plugin::d3d12::IUnityGraphicsD3D12v6; +use unity_native_plugin::graphics::{GfxRenderer, IUnityGraphics}; +use unity_native_plugin::vulkan::IUnityGraphicsVulkan; const FILL_TEXTURE_EVENT_ID: c_int = 0; diff --git a/unity-native-plugin-sample/src/metal.rs b/unity-native-plugin-sample/src/metal.rs index 32c08dd..71cc08b 100644 --- a/unity-native-plugin-sample/src/metal.rs +++ b/unity-native-plugin-sample/src/metal.rs @@ -8,9 +8,7 @@ use objc2_metal::{ }; use unity_native_plugin::interface::UnityInterfaces; -use unity_native_plugin::metal::{ - UnityGraphicsMetalV1, UnityGraphicsMetalV1Interface, UnityGraphicsMetalV2, -}; +use unity_native_plugin::metal::IUnityGraphicsMetalV1; pub fn fill_texture(unity_texture: *mut c_void, x: f32, y: f32, z: f32, w: f32) { if unity_texture.is_null() { @@ -20,22 +18,25 @@ pub fn fill_texture(unity_texture: *mut c_void, x: f32, y: f32, z: f32, w: f32) unsafe { let interfaces = UnityInterfaces::get(); - let cmd_buffer: Retained> = - if let Some(intf) = interfaces.interface::() { - intf.end_current_command_encoder(); - match intf.current_command_buffer() { - Some(cb) => cb, - None => return, - } - } else if let Some(intf) = interfaces.interface::() { - intf.end_current_command_encoder(); - match intf.current_command_buffer() { - Some(cb) => cb, - None => return, - } - } else { - return; - }; + let cmd_buffer: Retained> = if let Some(intf) = + interfaces.interface::() + { + intf.end_current_command_encoder(); + match intf.current_command_buffer() { + Some(cb) => cb, + None => return, + } + } else if let Some(intf) = + interfaces.interface::() + { + intf.end_current_command_encoder(); + match intf.current_command_buffer() { + Some(cb) => cb, + None => return, + } + } else { + return; + }; // Unity returns id directly from GetNativeTexturePtr() under Metal. let texture: Retained> = diff --git a/unity-native-plugin-sample/src/vulkan.rs b/unity-native-plugin-sample/src/vulkan.rs index 01b1039..550a5d9 100644 --- a/unity-native-plugin-sample/src/vulkan.rs +++ b/unity-native-plugin-sample/src/vulkan.rs @@ -2,8 +2,7 @@ use std::ffi::c_void; use unity_native_plugin::ash::vk; use unity_native_plugin::ash::vk::Handle; use unity_native_plugin::vulkan::{ - UnityGraphicsVulkan, UnityGraphicsVulkanInterface, VulkanGraphicsQueueAccess, - VulkanResourceAccessMode, + IUnityGraphicsVulkan, VulkanGraphicsQueueAccess, VulkanResourceAccessMode, }; pub fn fill_texture(unity_texture: *mut c_void, x: f32, y: f32, z: f32, w: f32) { @@ -13,7 +12,7 @@ pub fn fill_texture(unity_texture: *mut c_void, x: f32, y: f32, z: f32, w: f32) } let intf = match unity_native_plugin::interface::UnityInterfaces::get() - .interface::() + .interface::() { Some(i) => i, None => return, diff --git a/unity-native-plugin-tester/src/graphics.rs b/unity-native-plugin-tester/src/graphics.rs index b6df417..ab0dde8 100644 --- a/unity-native-plugin-tester/src/graphics.rs +++ b/unity-native-plugin-tester/src/graphics.rs @@ -62,6 +62,8 @@ pub fn initialize_interface(renderer: unity_native_plugin::graphics::GfxRenderer #[test] fn register_graphics() { + use unity_native_plugin::graphics::UnityGraphicsInterface; + crate::interface::initialize_unity_interfaces(); crate::graphics::initialize_interface(unity_native_plugin::graphics::GfxRenderer::D3D11); diff --git a/unity-native-plugin/src/d3d11.rs b/unity-native-plugin/src/d3d11.rs index f9fe350..8ca9b88 100644 --- a/unity-native-plugin/src/d3d11.rs +++ b/unity-native-plugin/src/d3d11.rs @@ -20,6 +20,8 @@ pub trait UnityGraphicsD3D11Interface { fn present_flags(&self) -> u32; } +pub use UnityGraphicsD3D11Interface as IUnityGraphicsD3D11; + macro_rules! impl_d3d11 { ($intf:ty) => { impl UnityGraphicsD3D11Interface for $intf { diff --git a/unity-native-plugin/src/d3d12.rs b/unity-native-plugin/src/d3d12.rs index c22217f..b7b4d5d 100644 --- a/unity-native-plugin/src/d3d12.rs +++ b/unity-native-plugin/src/d3d12.rs @@ -35,15 +35,17 @@ pub struct PluginEventConfig { pub ensure_active_render_texture_is_bound: bool, } -pub trait UnityGraphicsD3D12V2Interface { +pub trait UnityGraphicsD3D12v2Interface { unsafe fn device(&self) -> ComPtr; unsafe fn frame_fence(&self) -> ComPtr; fn next_frame_fence_value(&self) -> u64; } +pub use UnityGraphicsD3D12v2Interface as IUnityGraphicsD3D12v2; + macro_rules! impl_d3d12_v2 { ($intf:ty) => { - impl UnityGraphicsD3D12V2Interface for $intf { + impl UnityGraphicsD3D12v2Interface for $intf { unsafe fn device(&self) -> ComPtr { unsafe { self.interface().GetDevice.expect("GetDevice")() as ComPtr } } @@ -65,27 +67,46 @@ macro_rules! impl_d3d12_v2 { define_unity_interface!( UnityGraphicsD3D12v2, - IUnityGraphicsD3D12v2, + unity_native_plugin_sys::IUnityGraphicsD3D12v2, 0xEC39D2F18446C745_u64, 0xB1A2626641D6B11F_u64 ); impl_d3d12_v2!(UnityGraphicsD3D12v2); -pub trait UnityGraphicsD3D12Interface: UnityGraphicsD3D12V2Interface { +pub trait UnityGraphicsD3D12Interface { + unsafe fn device(&self) -> ComPtr; unsafe fn command_queue(&self) -> ComPtr; + unsafe fn frame_fence(&self) -> ComPtr; + fn next_frame_fence_value(&self) -> u64; fn resource_state(&self, resource: ComPtr) -> Option; fn set_resource_state(&self, resource: ComPtr, state: i32); } +pub use UnityGraphicsD3D12Interface as IUnityGraphicsD3D12; + macro_rules! impl_d3d12 { ($intf:ty) => { - impl_d3d12_v2!($intf); - impl UnityGraphicsD3D12Interface for $intf { + unsafe fn device(&self) -> ComPtr { + unsafe { self.interface().GetDevice.expect("GetDevice")() as ComPtr } + } + unsafe fn command_queue(&self) -> ComPtr { unsafe { self.interface().GetCommandQueue.expect("GetCommandQueue")() as ComPtr } } + unsafe fn frame_fence(&self) -> ComPtr { + unsafe { self.interface().GetFrameFence.expect("GetFrameFence")() as ComPtr } + } + + fn next_frame_fence_value(&self) -> u64 { + unsafe { + self.interface() + .GetNextFrameFenceValue + .expect("GetNextFrameFenceValue")() as u64 + } + } + fn resource_state(&self, resource: ComPtr) -> Option { unsafe { let mut ret: D3D12_RESOURCE_STATES = D3D12_RESOURCE_STATES::default(); @@ -114,16 +135,18 @@ macro_rules! impl_d3d12 { define_unity_interface!( UnityGraphicsD3D12, - IUnityGraphicsD3D12, + unity_native_plugin_sys::IUnityGraphicsD3D12, 0xEF4CEC88A45F4C4C_u64, 0xBD295B6F2A38D9DE_u64 ); impl_d3d12!(UnityGraphicsD3D12); -pub trait UnityGraphicsD3D12v3Interface: UnityGraphicsD3D12V2Interface { +pub trait UnityGraphicsD3D12v3Interface: UnityGraphicsD3D12v2Interface { fn set_physical_video_memory_control_values(&self, mem_info: &PhysicalVideoMemoryControlValues); } +pub use UnityGraphicsD3D12v3Interface as IUnityGraphicsD3D12v3; + macro_rules! impl_d3d12_v3 { ($intf:ty) => { impl_d3d12_v2!($intf); @@ -147,7 +170,7 @@ macro_rules! impl_d3d12_v3 { define_unity_interface!( UnityGraphicsD3D12v3, - IUnityGraphicsD3D12v3, + unity_native_plugin_sys::IUnityGraphicsD3D12v3, 0x57C3FAFE59E5E843_u64, 0xBF4F5998474BB600_u64 ); @@ -157,6 +180,8 @@ pub trait UnityGraphicsD3D12v4Interface: UnityGraphicsD3D12v3Interface { unsafe fn command_queue(&self) -> ComPtr; } +pub use UnityGraphicsD3D12v4Interface as IUnityGraphicsD3D12v4; + macro_rules! impl_d3d12_v4 { ($intf:ty) => { impl_d3d12_v3!($intf); @@ -171,7 +196,7 @@ macro_rules! impl_d3d12_v4 { define_unity_interface!( UnityGraphicsD3D12v4, - IUnityGraphicsD3D12v4, + unity_native_plugin_sys::IUnityGraphicsD3D12v4, 0x498FFCC13EC94006_u64, 0xB18F8B0FF67778C8_u64 ); @@ -181,6 +206,8 @@ pub trait UnityGraphicsD3D12v5Interface: UnityGraphicsD3D12v4Interface { unsafe fn texture_from_render_buffer(&self, rb: graphics::RenderBuffer) -> ComPtr; } +pub use UnityGraphicsD3D12v5Interface as IUnityGraphicsD3D12v5; + macro_rules! impl_d3d12_v5 { ($intf:ty) => { impl_d3d12_v4!($intf); @@ -199,7 +226,7 @@ macro_rules! impl_d3d12_v5 { define_unity_interface!( UnityGraphicsD3D12v5, - IUnityGraphicsD3D12v5, + unity_native_plugin_sys::IUnityGraphicsD3D12v5, 0xF5C8D8A37D37BC42_u64, 0xB02DFE93B5064A27_u64 ); @@ -210,6 +237,8 @@ pub trait UnityGraphicsD3D12v6Interface: UnityGraphicsD3D12v5Interface { unsafe fn command_recording_state(&self) -> Option; } +pub use UnityGraphicsD3D12v6Interface as IUnityGraphicsD3D12v6; + macro_rules! impl_d3d12_v6 { ($intf:ty) => { impl_d3d12_v5!($intf); @@ -248,7 +277,7 @@ macro_rules! impl_d3d12_v6 { define_unity_interface!( UnityGraphicsD3D12v6, - IUnityGraphicsD3D12v6, + unity_native_plugin_sys::IUnityGraphicsD3D12v6, 0xA396DCE58CAC4D78_u64, 0xAFDD9B281F20B840_u64 ); @@ -260,6 +289,8 @@ pub trait UnityGraphicsD3D12v7Interface: UnityGraphicsD3D12v6Interface { fn present_flags(&self) -> u32; } +pub use UnityGraphicsD3D12v7Interface as IUnityGraphicsD3D12v7; + macro_rules! impl_d3d12_v7 { ($intf:ty) => { impl_d3d12_v6!($intf); @@ -282,7 +313,7 @@ macro_rules! impl_d3d12_v7 { define_unity_interface!( UnityGraphicsD3D12v7, - IUnityGraphicsD3D12v7, + unity_native_plugin_sys::IUnityGraphicsD3D12v7, 0x4624B0DA41B64AAC_u64, 0x915AABCB9BC3F0D3_u64 ); @@ -293,6 +324,8 @@ pub trait UnityGraphicsD3D12v8Interface: UnityGraphicsD3D12v7Interface { fn notify_resource_state(&self, resource: ComPtr, state: i32, uav_access: bool); } +pub use UnityGraphicsD3D12v8Interface as IUnityGraphicsD3D12v8; + macro_rules! impl_d3d12_v8 { ($intf:ty) => { impl_d3d12_v7!($intf); @@ -325,7 +358,7 @@ macro_rules! impl_d3d12_v8 { define_unity_interface!( UnityGraphicsD3D12v8, - IUnityGraphicsD3D12v8, + unity_native_plugin_sys::IUnityGraphicsD3D12v8, 0x9D303045D00D4CFD_u64, 0x8FEBB42968B423B6_u64 ); diff --git a/unity-native-plugin/src/graphics.rs b/unity-native-plugin/src/graphics.rs index 6456cf5..2951e78 100644 --- a/unity-native-plugin/src/graphics.rs +++ b/unity-native-plugin/src/graphics.rs @@ -40,15 +40,24 @@ pub enum GfxDeviceEventType { define_unity_interface!( UnityGraphics, - IUnityGraphics, + unity_native_plugin_sys::IUnityGraphics, 0x7CBA0A9CA4DDB544_u64, 0x8C5AD4926EB17B11_u64 ); pub type GraphicsDeviceEventCallback = extern "system" fn(event_type: GfxDeviceEventType); -impl UnityGraphics { - pub fn renderer(&self) -> GfxRenderer { +pub trait UnityGraphicsInterface { + fn renderer(&self) -> GfxRenderer; + fn register_device_event_callback(&self, callback: Option); + fn unregister_device_event_callback(&self, callback: Option); + fn reserve_event_id_range(&self, count: c_int) -> c_int; +} + +pub use UnityGraphicsInterface as IUnityGraphics; + +impl UnityGraphicsInterface for UnityGraphics { + fn renderer(&self) -> GfxRenderer { unsafe { match self.interface().GetRenderer { Some(intf) => std::mem::transmute::(intf()), @@ -57,7 +66,7 @@ impl UnityGraphics { } } - pub fn register_device_event_callback(&self, callback: Option) { + fn register_device_event_callback(&self, callback: Option) { unsafe { if let Some(intf) = self.interface().RegisterDeviceEventCallback { intf(std::mem::transmute::< @@ -68,7 +77,7 @@ impl UnityGraphics { } } - pub fn unregister_device_event_callback(&self, callback: Option) { + fn unregister_device_event_callback(&self, callback: Option) { unsafe { if let Some(intf) = self.interface().UnregisterDeviceEventCallback { intf(std::mem::transmute::< @@ -79,7 +88,7 @@ impl UnityGraphics { } } - pub fn reserve_event_id_range(&self, count: c_int) -> c_int { + fn reserve_event_id_range(&self, count: c_int) -> c_int { unsafe { self.interface() .ReserveEventIDRange diff --git a/unity-native-plugin/src/log.rs b/unity-native-plugin/src/log.rs index 4b4bd2e..349df27 100644 --- a/unity-native-plugin/src/log.rs +++ b/unity-native-plugin/src/log.rs @@ -13,13 +13,19 @@ pub enum LogType { define_unity_interface!( UnityLog, - IUnityLog, + unity_native_plugin_sys::IUnityLog, 0x9E7507FA5B444D5D_u64, 0x92FB979515EA83FC_u64 ); -impl UnityLog { - pub fn log(&self, log_type: LogType, message: &CStr, file_name: &CStr, file_line: i32) { +pub trait UnityLogInterface { + fn log(&self, log_type: LogType, message: &CStr, file_name: &CStr, file_line: i32); +} + +pub use UnityLogInterface as IUnityLog; + +impl UnityLogInterface for UnityLog { + fn log(&self, log_type: LogType, message: &CStr, file_name: &CStr, file_line: i32) { unsafe { self.interface().Log.expect("Log")( log_type as UnityLogType, diff --git a/unity-native-plugin/src/memory_manager.rs b/unity-native-plugin/src/memory_manager.rs index 0248bb6..af93467 100644 --- a/unity-native-plugin/src/memory_manager.rs +++ b/unity-native-plugin/src/memory_manager.rs @@ -1,14 +1,26 @@ use crate::interface::UnityInterface; use std::ffi::{CStr, c_void}; -use unity_native_plugin_sys::*; define_unity_interface!( UnityMemoryManager, - IUnityMemoryManager, + unity_native_plugin_sys::IUnityMemoryManager, 0xBAF9E57C61A811EC_u64, 0xC5A7CC7861A811EC_u64 ); +pub trait UnityMemoryManagerInterface { + /// # Safety + /// `area_name` and `object_name` must remain valid for the lifetime of the + /// returned [`UnityAllocator`]. + unsafe fn create_allocator( + &self, + area_name: &CStr, + object_name: &CStr, + ) -> Option; +} + +pub use UnityMemoryManagerInterface as IUnityMemoryManager; + pub struct UnityAllocator { allocator: *mut unity_native_plugin_sys::UnityAllocator, memory_manager: UnityMemoryManager, @@ -58,8 +70,8 @@ impl UnityAllocator { } } -impl UnityMemoryManager { - pub unsafe fn create_allocator( +impl UnityMemoryManagerInterface for UnityMemoryManager { + unsafe fn create_allocator( &self, area_name: &CStr, object_name: &CStr, @@ -79,7 +91,9 @@ impl UnityMemoryManager { } } } +} +impl UnityMemoryManager { pub(crate) unsafe fn destroy_allocator( &self, allocator: *mut unity_native_plugin_sys::UnityAllocator, diff --git a/unity-native-plugin/src/metal.rs b/unity-native-plugin/src/metal.rs index 4678988..4bf9adc 100644 --- a/unity-native-plugin/src/metal.rs +++ b/unity-native-plugin/src/metal.rs @@ -4,7 +4,7 @@ use objc2_metal::{ MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue, MTLDevice, MTLRenderPassDescriptor, MTLTexture, }; -use unity_native_plugin_sys::{IUnityGraphicsMetalV1, IUnityGraphicsMetalV2, UnityRenderBuffer}; +use unity_native_plugin_sys::UnityRenderBuffer; use crate::graphics; use crate::interface::UnityInterface; @@ -34,6 +34,8 @@ pub trait UnityGraphicsMetalV1Interface { ) -> Option>>; } +pub use UnityGraphicsMetalV1Interface as IUnityGraphicsMetalV1; + macro_rules! impl_metal_v1 { ($intf:ty) => { impl UnityGraphicsMetalV1Interface for $intf { @@ -158,7 +160,7 @@ impl_metal_v1!(UnityGraphicsMetalV1); define_unity_interface!( UnityGraphicsMetalV1, - IUnityGraphicsMetalV1, + unity_native_plugin_sys::IUnityGraphicsMetalV1, 0x29F8F3D03833465E_u64, 0x92138551C15D823D_u64 ); @@ -170,6 +172,8 @@ pub trait UnityGraphicsMetalV2Interface: UnityGraphicsMetalV1Interface { fn command_queue(&self) -> Option>>; } +pub use UnityGraphicsMetalV2Interface as IUnityGraphicsMetalV2; + macro_rules! impl_metal_v2 { ($intf:ty) => { impl_metal_v1!($intf); @@ -204,7 +208,7 @@ impl_metal_v2!(UnityGraphicsMetalV2); define_unity_interface!( UnityGraphicsMetalV2, - IUnityGraphicsMetalV2, + unity_native_plugin_sys::IUnityGraphicsMetalV2, 0xF58857784FEF46EC_u64, 0x9DB7A8803B87DA3D_u64 ); diff --git a/unity-native-plugin/src/profiler.rs b/unity-native-plugin/src/profiler.rs index cef77db..200d26b 100644 --- a/unity-native-plugin/src/profiler.rs +++ b/unity-native-plugin/src/profiler.rs @@ -4,7 +4,7 @@ use unity_native_plugin_sys::*; define_unity_interface!( UnityProfiler, - IUnityProfiler, + unity_native_plugin_sys::IUnityProfiler, 0x2CE79ED8316A4833_u64, 0x87076B2013E1571F_u64 ); @@ -256,120 +256,155 @@ bitflag!( pub type ProfilerThreadId = UnityProfilerThreadId; +pub trait UnityProfilerInterface { + fn emit_event( + &self, + marker_desc: &ProfilerMarkerDesc, + event_type: ProfilerMarkerEventType, + event_data: &[ProfilerMarkerData], + ); + fn is_enabled(&self) -> bool; + fn is_available(&self) -> bool; + fn create_marker( + &self, + name: &std::ffi::CStr, + category: ProfilerCategoryId, + flags: ProfilerMarkerFlags, + event_data_count: ::std::os::raw::c_int, + ) -> Result; + fn set_marker_metadata_name( + &self, + desc: &ProfilerMarkerDesc, + index: ::std::os::raw::c_int, + metadata_name: &std::ffi::CStr, + metadata_type: ProfilerMarkerDataType, + metadata_unit: ProfilerMarkerDataUnit, + ) -> Result<(), ::std::os::raw::c_int>; + fn register_thread( + &self, + group_name: &std::ffi::CStr, + name: &std::ffi::CStr, + ) -> Result; + fn unregister_thread(&self, thread_id: ProfilerThreadId) -> Result<(), ::std::os::raw::c_int>; +} + +pub use UnityProfilerInterface as IUnityProfiler; + macro_rules! impl_profiler { - () => { - pub fn emit_event( - &self, - marker_desc: &ProfilerMarkerDesc, - event_type: ProfilerMarkerEventType, - event_data: &[ProfilerMarkerData], - ) { - unsafe { - self.interface().EmitEvent.expect("EmitEvent")( - marker_desc.native, - event_type as UnityProfilerMarkerEventType, - event_data.len() as u16, - event_data.as_ptr() as *const _, - ); + ($intf:ty) => { + impl UnityProfilerInterface for $intf { + fn emit_event( + &self, + marker_desc: &ProfilerMarkerDesc, + event_type: ProfilerMarkerEventType, + event_data: &[ProfilerMarkerData], + ) { + unsafe { + self.interface().EmitEvent.expect("EmitEvent")( + marker_desc.native, + event_type as UnityProfilerMarkerEventType, + event_data.len() as u16, + event_data.as_ptr() as *const _, + ); + } } - } - pub fn is_enabled(&self) -> bool { - unsafe { self.interface().IsEnabled.expect("IsEnabled")() != 0 } - } + fn is_enabled(&self) -> bool { + unsafe { self.interface().IsEnabled.expect("IsEnabled")() != 0 } + } - pub fn is_available(&self) -> bool { - unsafe { self.interface().IsAvailable.expect("IsAvailable")() != 0 } - } + fn is_available(&self) -> bool { + unsafe { self.interface().IsAvailable.expect("IsAvailable")() != 0 } + } - pub fn create_marker( - &self, - name: &std::ffi::CStr, - category: ProfilerCategoryId, - flags: ProfilerMarkerFlags, - event_data_count: ::std::os::raw::c_int, - ) -> Result { - unsafe { - let mut ret = std::ptr::null::(); - let result = self.interface().CreateMarker.expect("CreateMarker")( - &mut ret, - name.as_ptr(), - category as _, - flags.flag as _, - event_data_count, - ); - if result > 0 { - Err(result) - } else { - Ok(ProfilerMarkerDesc { native: ret }) + fn create_marker( + &self, + name: &std::ffi::CStr, + category: ProfilerCategoryId, + flags: ProfilerMarkerFlags, + event_data_count: ::std::os::raw::c_int, + ) -> Result { + unsafe { + let mut ret = std::ptr::null::(); + let result = self.interface().CreateMarker.expect("CreateMarker")( + &mut ret, + name.as_ptr(), + category as _, + flags.flag as _, + event_data_count, + ); + if result > 0 { + Err(result) + } else { + Ok(ProfilerMarkerDesc { native: ret }) + } } } - } - pub fn set_marker_metadata_name( - &self, - desc: &ProfilerMarkerDesc, - index: ::std::os::raw::c_int, - metadata_name: &std::ffi::CStr, - metadata_type: ProfilerMarkerDataType, - metadata_unit: ProfilerMarkerDataUnit, - ) -> Result<(), ::std::os::raw::c_int> { - unsafe { - let result = self - .interface() - .SetMarkerMetadataName - .expect("SetMarkerMetadataName")( - desc.native, - index, - metadata_name.as_ptr(), - metadata_type as _, - metadata_unit as _, - ); - if result > 0 { Err(result) } else { Ok(()) } + fn set_marker_metadata_name( + &self, + desc: &ProfilerMarkerDesc, + index: ::std::os::raw::c_int, + metadata_name: &std::ffi::CStr, + metadata_type: ProfilerMarkerDataType, + metadata_unit: ProfilerMarkerDataUnit, + ) -> Result<(), ::std::os::raw::c_int> { + unsafe { + let result = self + .interface() + .SetMarkerMetadataName + .expect("SetMarkerMetadataName")( + desc.native, + index, + metadata_name.as_ptr(), + metadata_type as _, + metadata_unit as _, + ); + if result > 0 { Err(result) } else { Ok(()) } + } } - } - pub fn register_thread( - &self, - group_name: &std::ffi::CStr, - name: &std::ffi::CStr, - ) -> Result { - unsafe { - let mut thread_id = std::mem::zeroed::(); - - let result = self.interface().RegisterThread.expect("RegisterThread")( - &mut thread_id, - group_name.as_ptr(), - name.as_ptr(), - ); - if result > 0 { - Err(result) - } else { - Ok(thread_id) + fn register_thread( + &self, + group_name: &std::ffi::CStr, + name: &std::ffi::CStr, + ) -> Result { + unsafe { + let mut thread_id = std::mem::zeroed::(); + + let result = self.interface().RegisterThread.expect("RegisterThread")( + &mut thread_id, + group_name.as_ptr(), + name.as_ptr(), + ); + if result > 0 { + Err(result) + } else { + Ok(thread_id) + } } } - } - pub fn unregister_thread( - &self, - thread_id: ProfilerThreadId, - ) -> Result<(), ::std::os::raw::c_int> { - unsafe { - let result = - self.interface().UnregisterThread.expect("UnregisterThread")(thread_id); - if result > 0 { Err(result) } else { Ok(()) } + fn unregister_thread( + &self, + thread_id: ProfilerThreadId, + ) -> Result<(), ::std::os::raw::c_int> { + unsafe { + let result = + self.interface().UnregisterThread.expect("UnregisterThread")(thread_id); + if result > 0 { Err(result) } else { Ok(()) } + } } } }; } -impl UnityProfiler { - impl_profiler!(); -} +impl_profiler!(UnityProfiler); +impl_profiler!(UnityProfilerV2); define_unity_interface!( UnityProfilerV2, - IUnityProfilerV2, + unity_native_plugin_sys::IUnityProfilerV2, 0xB957E0189CB6A30B_u64, 0x83CE589AE85B9068_u64 ); @@ -390,112 +425,136 @@ impl ProfilerCounter { } } -macro_rules! impl_profiler_v2 { - () => { - impl_profiler!(); - - pub fn create_category( - &self, - name: &std::ffi::CStr, - unused: u32, - ) -> Option { - unsafe { - let mut category: UnityProfilerCategoryId = std::mem::zeroed(); - let r = self.interface().CreateCategory.expect("CreateCategory")( - &mut category as *mut UnityProfilerCategoryId, - name.as_ptr(), - unused, - ); - if r > 0 { Some(category) } else { None } +pub trait UnityProfilerV2Interface: UnityProfilerInterface { + fn create_category(&self, name: &std::ffi::CStr, unused: u32) -> Option; + + /// # Safety + /// `activate_func`/`deactivate_func` are called by Unity from arbitrary + /// threads with the supplied `user_data`. The caller must ensure that + /// `user_data` outlives the counter and is safe to access from those + /// threads. + #[allow(clippy::too_many_arguments)] + unsafe fn create_counter_value( + &self, + category: ProfilerCategoryId, + name: &std::ffi::CStr, + flags: ProfilerMarkerFlags, + value_type: ProfilerMarkerDataType, + value_unit: ProfilerMarkerDataUnit, + value_size: usize, + counter_flags: ProfilerCounterFlags, + activate_func: ProfilerCounterStatePtrCallback, + deactivate_func: ProfilerCounterStatePtrCallback, + user_data: *mut ::std::os::raw::c_void, + ) -> *mut ::std::os::raw::c_void; + + /// # Safety + /// `counter` must be a pointer obtained from [`create_counter_value`] on + /// the same profiler instance and must still be live. + unsafe fn flush_counter_value(&self, counter: *mut ::std::os::raw::c_void); + + /// # Safety + /// See [`create_counter_value`]. + #[allow(clippy::too_many_arguments)] + unsafe fn create_counter( + &self, + category: ProfilerCategoryId, + name: &std::ffi::CStr, + flags: ProfilerMarkerFlags, + value_type: ProfilerMarkerDataType, + value_unit: ProfilerMarkerDataUnit, + counter_flags: ProfilerCounterFlags, + activate_func: ProfilerCounterStatePtrCallback, + deactivate_func: ProfilerCounterStatePtrCallback, + user_data: *mut ::std::os::raw::c_void, + ) -> Option> { + unsafe { + let r = self.create_counter_value( + category, + name, + flags, + value_type, + value_unit, + std::mem::size_of::(), + counter_flags, + activate_func, + deactivate_func, + user_data, + ); + if !r.is_null() { + Some(ProfilerCounter:: { + counter: r as *mut T, + }) + } else { + None } } + } - #[allow(clippy::too_many_arguments)] - pub unsafe fn create_counter_value( - &self, - category: ProfilerCategoryId, - name: &std::ffi::CStr, - flags: ProfilerMarkerFlags, - value_type: ProfilerMarkerDataType, - value_unit: ProfilerMarkerDataUnit, - value_size: usize, - counter_flags: ProfilerCounterFlags, - activate_func: ProfilerCounterStatePtrCallback, - deactivate_func: ProfilerCounterStatePtrCallback, - user_data: *mut ::std::os::raw::c_void, - ) -> *mut ::std::os::raw::c_void { - unsafe { - self.interface() - .CreateCounterValue - .expect("CreateCounterValue")( - category, - name.as_ptr(), - flags.into(), - value_type as u8, - value_unit as u8, - value_size, - counter_flags.into(), - activate_func, - deactivate_func, - user_data, - ) - } + /// # Safety + /// `counter` must wrap a live pointer originally obtained from + /// [`create_counter`]. + unsafe fn flush_counter(&self, counter: &mut ProfilerCounter) { + unsafe { + self.flush_counter_value(counter.counter as *mut ::std::os::raw::c_void); } + } +} - pub unsafe fn flush_counter_value(&self, counter: *mut ::std::os::raw::c_void) { - unsafe { - self.interface() - .FlushCounterValue - .expect("FlushCounterValue")(counter) - } - } +pub use UnityProfilerV2Interface as IUnityProfilerV2; - #[allow(clippy::too_many_arguments)] - pub unsafe fn create_counter( - &self, - category: ProfilerCategoryId, - name: &std::ffi::CStr, - flags: ProfilerMarkerFlags, - value_type: ProfilerMarkerDataType, - value_unit: ProfilerMarkerDataUnit, - counter_flags: ProfilerCounterFlags, - activate_func: ProfilerCounterStatePtrCallback, - deactivate_func: ProfilerCounterStatePtrCallback, - user_data: *mut ::std::os::raw::c_void, - ) -> Option> { - unsafe { - let r = self.create_counter_value( - category, - name, - flags, - value_type, - value_unit, - std::mem::size_of::(), - counter_flags.into(), - activate_func, - deactivate_func, - user_data, - ); - if !r.is_null() { - Some(ProfilerCounter:: { - counter: r as *mut T, - }) - } else { - None - } - } +impl UnityProfilerV2Interface for UnityProfilerV2 { + fn create_category(&self, name: &std::ffi::CStr, unused: u32) -> Option { + unsafe { + let mut category: UnityProfilerCategoryId = std::mem::zeroed(); + let r = self.interface().CreateCategory.expect("CreateCategory")( + &mut category as *mut UnityProfilerCategoryId, + name.as_ptr(), + unused, + ); + if r > 0 { Some(category) } else { None } } + } - pub unsafe fn flush_counter(&self, counter: &mut ProfilerCounter) { - unsafe { - self.flush_counter_value(counter.counter as *mut ::std::os::raw::c_void); - } + #[allow(clippy::too_many_arguments)] + unsafe fn create_counter_value( + &self, + category: ProfilerCategoryId, + name: &std::ffi::CStr, + flags: ProfilerMarkerFlags, + value_type: ProfilerMarkerDataType, + value_unit: ProfilerMarkerDataUnit, + value_size: usize, + counter_flags: ProfilerCounterFlags, + activate_func: ProfilerCounterStatePtrCallback, + deactivate_func: ProfilerCounterStatePtrCallback, + user_data: *mut ::std::os::raw::c_void, + ) -> *mut ::std::os::raw::c_void { + unsafe { + self.interface() + .CreateCounterValue + .expect("CreateCounterValue")( + category, + name.as_ptr(), + flags.into(), + value_type as u8, + value_unit as u8, + value_size, + counter_flags.into(), + activate_func, + deactivate_func, + user_data, + ) } - }; -} + } -impl UnityProfilerV2 { - impl_profiler_v2!(); + unsafe fn flush_counter_value(&self, counter: *mut ::std::os::raw::c_void) { + unsafe { + self.interface() + .FlushCounterValue + .expect("FlushCounterValue")(counter) + } + } } #[cfg(test)] diff --git a/unity-native-plugin/src/profiler_callbacks.rs b/unity-native-plugin/src/profiler_callbacks.rs index 2492cba..62bae86 100644 --- a/unity-native-plugin/src/profiler_callbacks.rs +++ b/unity-native-plugin/src/profiler_callbacks.rs @@ -236,10 +236,38 @@ macro_rules! iface_fn { }; } +pub trait UnityProfilerCallbacksInterface { + fn register_create_category( + &self, + f: Box, + ) -> CreateCategoryRegister; + fn unregister_create_category(&self, register: CreateCategoryRegister); + fn register_create_marker( + &self, + f: Box, + ) -> CreateMarkerRegister; + fn unregister_create_marker(&self, register: CreateMarkerRegister); + fn register_marker_event( + &self, + desc: &ProfilerMarkerDesc, + f: Box, + ) -> MarkerEventRegister; + fn unregister_marker_event(&self, register: MarkerEventRegister); + fn register_frame(&self, f: Box) -> FrameRegister; + fn unregister_frame(&self, register: FrameRegister); + fn register_create_thread( + &self, + f: Box, + ) -> CreateThreadRegister; + fn unregister_create_thread(&self, register: CreateThreadRegister); +} + +pub use UnityProfilerCallbacksInterface as IUnityProfilerCallbacks; + macro_rules! common_impl { ($name: tt) => { - impl $name { - pub fn register_create_category( + impl UnityProfilerCallbacksInterface for $name { + fn register_create_category( &self, f: Box, ) -> CreateCategoryRegister { @@ -254,7 +282,7 @@ macro_rules! common_impl { CreateCategoryRegister(ptr) } - pub fn unregister_create_category(&self, register: CreateCategoryRegister) { + fn unregister_create_category(&self, register: CreateCategoryRegister) { unsafe { iface_fn!(self, UnregisterCreateCategoryCallback)( Some(create_category_bridge), @@ -263,7 +291,7 @@ macro_rules! common_impl { } } - pub fn register_create_marker( + fn register_create_marker( &self, f: Box, ) -> CreateMarkerRegister { @@ -275,7 +303,7 @@ macro_rules! common_impl { CreateMarkerRegister(ptr) } - pub fn unregister_create_marker(&self, register: CreateMarkerRegister) { + fn unregister_create_marker(&self, register: CreateMarkerRegister) { unsafe { iface_fn!(self, UnregisterCreateMarkerCallback)( Some(create_marker_bridge), @@ -284,7 +312,7 @@ macro_rules! common_impl { } } - pub fn register_marker_event( + fn register_marker_event( &self, desc: &ProfilerMarkerDesc, f: Box, @@ -304,7 +332,7 @@ macro_rules! common_impl { } } - pub fn unregister_marker_event(&self, register: MarkerEventRegister) { + fn unregister_marker_event(&self, register: MarkerEventRegister) { unsafe { iface_fn!(self, UnregisterMarkerEventCallback)( register.desc, @@ -314,7 +342,7 @@ macro_rules! common_impl { } } - pub fn register_frame(&self, f: Box) -> FrameRegister { + fn register_frame(&self, f: Box) -> FrameRegister { let ptr = Box::into_raw(Box::new(f)) as *mut c_void; unsafe { @@ -323,13 +351,13 @@ macro_rules! common_impl { FrameRegister(ptr) } - pub fn unregister_frame(&self, register: FrameRegister) { + fn unregister_frame(&self, register: FrameRegister) { unsafe { iface_fn!(self, UnregisterFrameCallback)(Some(frame_bridge), register.0); } } - pub fn register_create_thread( + fn register_create_thread( &self, f: Box, ) -> CreateThreadRegister { @@ -341,7 +369,7 @@ macro_rules! common_impl { CreateThreadRegister(ptr) } - pub fn unregister_create_thread(&self, register: CreateThreadRegister) { + fn unregister_create_thread(&self, register: CreateThreadRegister) { unsafe { iface_fn!(self, UnregisterCreateThreadCallback)( Some(create_thread_bridge), @@ -390,8 +418,19 @@ extern "system" fn flow_event_bridge( pub struct FlowEventRegister(*mut c_void); common_impl!(UnityProfilerCallbacksV2); -impl UnityProfilerCallbacksV2 { - pub fn register_flow_event( + +pub trait UnityProfilerCallbacksV2Interface: UnityProfilerCallbacksInterface { + fn register_flow_event( + &self, + f: Box, + ) -> FlowEventRegister; + fn unregister_flow_event(&self, register: FlowEventRegister); +} + +pub use UnityProfilerCallbacksV2Interface as IUnityProfilerCallbacksV2; + +impl UnityProfilerCallbacksV2Interface for UnityProfilerCallbacksV2 { + fn register_flow_event( &self, f: Box, ) -> FlowEventRegister { @@ -403,7 +442,7 @@ impl UnityProfilerCallbacksV2 { FlowEventRegister(ptr) } - pub fn unregister_flow_event(&self, register: FlowEventRegister) { + fn unregister_flow_event(&self, register: FlowEventRegister) { unsafe { iface_fn!(self, UnregisterFlowEventCallback)(Some(flow_event_bridge), register.0); } diff --git a/unity-native-plugin/src/vulkan.rs b/unity-native-plugin/src/vulkan.rs index 2432b8e..ce12556 100644 --- a/unity-native-plugin/src/vulkan.rs +++ b/unity-native-plugin/src/vulkan.rs @@ -4,7 +4,7 @@ use unity_native_plugin_sys::*; define_unity_interface!( UnityGraphicsVulkan, - IUnityGraphicsVulkan, + unity_native_plugin_sys::IUnityGraphicsVulkan, 0x95355348d4ef4e11_u64, 0x9789313dfcffcc87_u64 ); @@ -330,6 +330,8 @@ pub trait UnityGraphicsVulkanInterface { ) -> Option; } +pub use UnityGraphicsVulkanInterface as IUnityGraphicsVulkan; + macro_rules! impl_vulkan { ($intf:ty) => { impl UnityGraphicsVulkanInterface for $intf { @@ -609,7 +611,7 @@ impl_vulkan!(UnityGraphicsVulkan); define_unity_interface!( UnityGraphicsVulkanV2, - IUnityGraphicsVulkanV2, + unity_native_plugin_sys::IUnityGraphicsVulkanV2, 0x329334c09dca4787_u64, 0xb347dd92a0097ffc_u64 ); @@ -624,6 +626,8 @@ pub trait UnityGraphicsVulkanV2Interface: UnityGraphicsVulkanInterface { unsafe fn remove_intercept_initialization(&self, func: VulkanInitCallback) -> bool; } +pub use UnityGraphicsVulkanV2Interface as IUnityGraphicsVulkanV2; + macro_rules! impl_vulkan_v2 { ($intf:ty) => { impl_vulkan!($intf);