From 4c89e5c17c374bc765f2242c814a17954db25b86 Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Sun, 3 May 2026 20:04:35 +0900 Subject: [PATCH 01/14] Remove `metal/objc2.rs`, inline its content into `metal.rs`, and adjust imports in `unity-native-plugin-sample` to simplify structure and avoid redundant module. --- unity-native-plugin-sample/src/metal.rs | 2 +- unity-native-plugin/src/metal.rs | 211 +++++++++++++++++++++++- unity-native-plugin/src/metal/objc2.rs | 210 ----------------------- 3 files changed, 211 insertions(+), 212 deletions(-) delete mode 100644 unity-native-plugin/src/metal/objc2.rs diff --git a/unity-native-plugin-sample/src/metal.rs b/unity-native-plugin-sample/src/metal.rs index 05dbb5a..32c08dd 100644 --- a/unity-native-plugin-sample/src/metal.rs +++ b/unity-native-plugin-sample/src/metal.rs @@ -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, }; diff --git a/unity-native-plugin/src/metal.rs b/unity-native-plugin/src/metal.rs index 1acebdc..2c20712 100644 --- a/unity-native-plugin/src/metal.rs +++ b/unity-native-plugin/src/metal.rs @@ -1 +1,210 @@ -pub mod objc2; +use objc2::{rc::Retained, runtime::ProtocolObject}; +use objc2_foundation::NSBundle; +use objc2_metal::{ + MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue, MTLDevice, MTLRenderPassDescriptor, + MTLTexture, +}; +use unity_native_plugin_sys::{IUnityGraphicsMetalV1, IUnityGraphicsMetalV2, UnityRenderBuffer}; + +use crate::interface::UnityInterface; +use crate::{define_unity_interface, graphics}; + +pub trait UnityGraphicsMetalV1Interface { + fn metal_bundle(&self) -> Option>; + fn metal_device(&self) -> Option>>; + fn current_command_buffer(&self) -> Option>>; + fn current_command_encoder(&self) -> Option>>; + fn end_current_command_encoder(&self); + fn current_render_pass_descriptor(&self) -> Option>; + unsafe fn render_buffer_from_handle( + &self, + buffer_handle: *mut ::std::os::raw::c_void, + ) -> graphics::RenderBuffer; + unsafe fn texture_from_render_buffer( + &self, + buffer: UnityRenderBuffer, + ) -> Option>>; + unsafe fn aa_resolved_texture_from_render_buffer( + &self, + buffer: UnityRenderBuffer, + ) -> Option>>; + unsafe fn stencil_texture_from_render_buffer( + &self, + buffer: UnityRenderBuffer, + ) -> Option>>; +} + +macro_rules! impl_metal_v1 { + ($intf:ty) => { + impl UnityGraphicsMetalV1Interface for $intf { + fn metal_bundle(&self) -> Option> { + unsafe { + Retained::retain(self.interface().MetalBundle.expect("MetalBundle")() as *mut _) + } + } + + fn metal_device(&self) -> Option>> { + unsafe { + Retained::>::retain(self + .interface() + .MetalDevice + .expect("MetalDevice")( + ) as *mut _) + } + } + + fn current_command_buffer( + &self, + ) -> Option>> { + unsafe { + Retained::>::retain(self + .interface() + .CurrentCommandBuffer + .expect("CurrentCommandBuffer")( + ) + as *mut _) + } + } + + fn current_command_encoder( + &self, + ) -> Option>> { + unsafe { + Retained::>::retain(self + .interface() + .CurrentCommandEncoder + .expect("CurrentCommandEncoder")( + ) + as *mut _) + } + } + + fn end_current_command_encoder(&self) { + unsafe { + self.interface() + .EndCurrentCommandEncoder + .expect("EndCurrentCommandEncoder")() + } + } + + fn current_render_pass_descriptor(&self) -> Option> { + unsafe { + Retained::retain(self + .interface() + .CurrentRenderPassDescriptor + .expect("CurrentRenderPassDescriptor")() + as *mut _) + } + } + + unsafe fn render_buffer_from_handle( + &self, + buffer_handle: *mut ::std::os::raw::c_void, + ) -> graphics::RenderBuffer { + unsafe { + (self + .interface() + .RenderBufferFromHandle + .expect("RenderBufferFromHandle"))(buffer_handle) + } + } + + unsafe fn texture_from_render_buffer( + &self, + buffer: graphics::RenderBuffer, + ) -> Option>> { + unsafe { + Retained::>::retain(self + .interface() + .TextureFromRenderBuffer + .expect("TextureFromRenderBuffer")( + buffer + ) as *mut _) + } + } + + unsafe fn aa_resolved_texture_from_render_buffer( + &self, + buffer: graphics::RenderBuffer, + ) -> Option>> { + unsafe { + Retained::>::retain(self + .interface() + .AAResolvedTextureFromRenderBuffer + .expect("AAResolvedTextureFromRenderBuffer")( + buffer + ) as *mut _) + } + } + + unsafe fn stencil_texture_from_render_buffer( + &self, + buffer: graphics::RenderBuffer, + ) -> Option>> { + unsafe { + Retained::>::retain(self + .interface() + .StencilTextureFromRenderBuffer + .expect("StencilTextureFromRenderBuffer")( + buffer + ) as *mut _) + } + } + } + }; +} + +impl_metal_v1!(UnityGraphicsMetalV1); + +define_unity_interface!( + UnityGraphicsMetalV1, + IUnityGraphicsMetalV1, + 0x29F8F3D03833465E_u64, + 0x92138551C15D823D_u64 +); + +pub trait UnityGraphicsMetalV2Interface { + fn commit_current_command_buffer( + &self, + ) -> Option>>; + fn command_queue(&self) -> Option>>; +} + +macro_rules! impl_metal_v2 { + ($intf:ty) => { + impl_metal_v1!($intf); + + impl UnityGraphicsMetalV2Interface for $intf { + fn commit_current_command_buffer( + &self, + ) -> Option>> { + unsafe { + Retained::>::retain(self + .interface() + .CommitCurrentCommandBuffer + .expect("CommitCurrentCommandBuffer")( + ) + as *mut _) + } + } + + fn command_queue(&self) -> Option>> { + unsafe { + Retained::>::retain(self + .interface() + .CommandQueue + .expect("CommandQueue")( + ) as *mut _) + } + } + } + }; +} +impl_metal_v2!(UnityGraphicsMetalV2); + +define_unity_interface!( + UnityGraphicsMetalV2, + IUnityGraphicsMetalV2, + 0xF58857784FEF46EC_u64, + 0x9DB7A8803B87DA3D_u64 +); diff --git a/unity-native-plugin/src/metal/objc2.rs b/unity-native-plugin/src/metal/objc2.rs deleted file mode 100644 index 2c20712..0000000 --- a/unity-native-plugin/src/metal/objc2.rs +++ /dev/null @@ -1,210 +0,0 @@ -use objc2::{rc::Retained, runtime::ProtocolObject}; -use objc2_foundation::NSBundle; -use objc2_metal::{ - MTLCommandBuffer, MTLCommandEncoder, MTLCommandQueue, MTLDevice, MTLRenderPassDescriptor, - MTLTexture, -}; -use unity_native_plugin_sys::{IUnityGraphicsMetalV1, IUnityGraphicsMetalV2, UnityRenderBuffer}; - -use crate::interface::UnityInterface; -use crate::{define_unity_interface, graphics}; - -pub trait UnityGraphicsMetalV1Interface { - fn metal_bundle(&self) -> Option>; - fn metal_device(&self) -> Option>>; - fn current_command_buffer(&self) -> Option>>; - fn current_command_encoder(&self) -> Option>>; - fn end_current_command_encoder(&self); - fn current_render_pass_descriptor(&self) -> Option>; - unsafe fn render_buffer_from_handle( - &self, - buffer_handle: *mut ::std::os::raw::c_void, - ) -> graphics::RenderBuffer; - unsafe fn texture_from_render_buffer( - &self, - buffer: UnityRenderBuffer, - ) -> Option>>; - unsafe fn aa_resolved_texture_from_render_buffer( - &self, - buffer: UnityRenderBuffer, - ) -> Option>>; - unsafe fn stencil_texture_from_render_buffer( - &self, - buffer: UnityRenderBuffer, - ) -> Option>>; -} - -macro_rules! impl_metal_v1 { - ($intf:ty) => { - impl UnityGraphicsMetalV1Interface for $intf { - fn metal_bundle(&self) -> Option> { - unsafe { - Retained::retain(self.interface().MetalBundle.expect("MetalBundle")() as *mut _) - } - } - - fn metal_device(&self) -> Option>> { - unsafe { - Retained::>::retain(self - .interface() - .MetalDevice - .expect("MetalDevice")( - ) as *mut _) - } - } - - fn current_command_buffer( - &self, - ) -> Option>> { - unsafe { - Retained::>::retain(self - .interface() - .CurrentCommandBuffer - .expect("CurrentCommandBuffer")( - ) - as *mut _) - } - } - - fn current_command_encoder( - &self, - ) -> Option>> { - unsafe { - Retained::>::retain(self - .interface() - .CurrentCommandEncoder - .expect("CurrentCommandEncoder")( - ) - as *mut _) - } - } - - fn end_current_command_encoder(&self) { - unsafe { - self.interface() - .EndCurrentCommandEncoder - .expect("EndCurrentCommandEncoder")() - } - } - - fn current_render_pass_descriptor(&self) -> Option> { - unsafe { - Retained::retain(self - .interface() - .CurrentRenderPassDescriptor - .expect("CurrentRenderPassDescriptor")() - as *mut _) - } - } - - unsafe fn render_buffer_from_handle( - &self, - buffer_handle: *mut ::std::os::raw::c_void, - ) -> graphics::RenderBuffer { - unsafe { - (self - .interface() - .RenderBufferFromHandle - .expect("RenderBufferFromHandle"))(buffer_handle) - } - } - - unsafe fn texture_from_render_buffer( - &self, - buffer: graphics::RenderBuffer, - ) -> Option>> { - unsafe { - Retained::>::retain(self - .interface() - .TextureFromRenderBuffer - .expect("TextureFromRenderBuffer")( - buffer - ) as *mut _) - } - } - - unsafe fn aa_resolved_texture_from_render_buffer( - &self, - buffer: graphics::RenderBuffer, - ) -> Option>> { - unsafe { - Retained::>::retain(self - .interface() - .AAResolvedTextureFromRenderBuffer - .expect("AAResolvedTextureFromRenderBuffer")( - buffer - ) as *mut _) - } - } - - unsafe fn stencil_texture_from_render_buffer( - &self, - buffer: graphics::RenderBuffer, - ) -> Option>> { - unsafe { - Retained::>::retain(self - .interface() - .StencilTextureFromRenderBuffer - .expect("StencilTextureFromRenderBuffer")( - buffer - ) as *mut _) - } - } - } - }; -} - -impl_metal_v1!(UnityGraphicsMetalV1); - -define_unity_interface!( - UnityGraphicsMetalV1, - IUnityGraphicsMetalV1, - 0x29F8F3D03833465E_u64, - 0x92138551C15D823D_u64 -); - -pub trait UnityGraphicsMetalV2Interface { - fn commit_current_command_buffer( - &self, - ) -> Option>>; - fn command_queue(&self) -> Option>>; -} - -macro_rules! impl_metal_v2 { - ($intf:ty) => { - impl_metal_v1!($intf); - - impl UnityGraphicsMetalV2Interface for $intf { - fn commit_current_command_buffer( - &self, - ) -> Option>> { - unsafe { - Retained::>::retain(self - .interface() - .CommitCurrentCommandBuffer - .expect("CommitCurrentCommandBuffer")( - ) - as *mut _) - } - } - - fn command_queue(&self) -> Option>> { - unsafe { - Retained::>::retain(self - .interface() - .CommandQueue - .expect("CommandQueue")( - ) as *mut _) - } - } - } - }; -} -impl_metal_v2!(UnityGraphicsMetalV2); - -define_unity_interface!( - UnityGraphicsMetalV2, - IUnityGraphicsMetalV2, - 0xF58857784FEF46EC_u64, - 0x9DB7A8803B87DA3D_u64 -); From c1c4aac5c3c5838a456168dd029fa7142c696d66 Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Sun, 3 May 2026 20:31:25 +0900 Subject: [PATCH 02/14] Inline `define_unity_interface` macro into `lib.rs` and remove unused imports across multiple modules for cleanup and organization. --- unity-native-plugin/src/d3d11.rs | 1 - unity-native-plugin/src/d3d12.rs | 2 +- unity-native-plugin/src/graphics.rs | 1 - unity-native-plugin/src/lib.rs | 67 +++++++++---------- unity-native-plugin/src/log.rs | 1 - unity-native-plugin/src/memory_manager.rs | 1 - unity-native-plugin/src/metal.rs | 2 +- unity-native-plugin/src/profiler.rs | 1 - unity-native-plugin/src/profiler_callbacks.rs | 1 - unity-native-plugin/src/vulkan.rs | 1 - 10 files changed, 35 insertions(+), 43 deletions(-) diff --git a/unity-native-plugin/src/d3d11.rs b/unity-native-plugin/src/d3d11.rs index c8b1043..0638561 100644 --- a/unity-native-plugin/src/d3d11.rs +++ b/unity-native-plugin/src/d3d11.rs @@ -1,4 +1,3 @@ -use crate::define_unity_interface; use crate::graphics; use crate::interface::UnityInterface; diff --git a/unity-native-plugin/src/d3d12.rs b/unity-native-plugin/src/d3d12.rs index 9ad3806..922a1d3 100644 --- a/unity-native-plugin/src/d3d12.rs +++ b/unity-native-plugin/src/d3d12.rs @@ -1,6 +1,6 @@ +use crate::bitflag; use crate::graphics; use crate::interface::UnityInterface; -use crate::{bitflag, define_unity_interface}; use unity_native_plugin_sys::*; define_unity_interface!( diff --git a/unity-native-plugin/src/graphics.rs b/unity-native-plugin/src/graphics.rs index 43a2be9..6456cf5 100644 --- a/unity-native-plugin/src/graphics.rs +++ b/unity-native-plugin/src/graphics.rs @@ -1,4 +1,3 @@ -use crate::define_unity_interface; use crate::interface::UnityInterface; use std::os::raw::c_int; use unity_native_plugin_sys::*; diff --git a/unity-native-plugin/src/lib.rs b/unity-native-plugin/src/lib.rs index d61ec14..325627c 100644 --- a/unity-native-plugin/src/lib.rs +++ b/unity-native-plugin/src/lib.rs @@ -1,5 +1,38 @@ #![allow(clippy::missing_safety_doc)] +macro_rules! define_unity_interface { + ($s:ident, $intf:ty, $guid_high:expr, $guid_low:expr) => { + #[derive(Clone, Copy)] + pub struct $s { + interface: *const $intf, + } + + // unity plugin interface should be thread-safe + unsafe impl Send for $s {} + unsafe impl Sync for $s {} + + impl UnityInterface for $s { + fn get_interface_guid() -> unity_native_plugin_sys::UnityInterfaceGUID { + unity_native_plugin_sys::UnityInterfaceGUID::new($guid_high, $guid_low) + } + + fn new(interface: *const unity_native_plugin_sys::IUnityInterface) -> Self { + $s { + interface: interface as *const $intf, + } + } + } + + impl $s { + #[allow(dead_code)] + #[inline] + fn interface(&self) -> &$intf { + unsafe { &*self.interface } + } + } + }; +} + #[cfg(all(feature = "d3d11", windows))] pub mod d3d11; @@ -55,37 +88,3 @@ macro_rules! unity_native_plugin_entry_point { } } } - -#[macro_export] -macro_rules! define_unity_interface { - ($s:ident, $intf:ty, $guid_high:expr, $guid_low:expr) => { - #[derive(Clone, Copy)] - pub struct $s { - interface: *const $intf, - } - - // unity plugin interface should be thread-safe - unsafe impl Send for $s {} - unsafe impl Sync for $s {} - - impl UnityInterface for $s { - fn get_interface_guid() -> unity_native_plugin_sys::UnityInterfaceGUID { - unity_native_plugin_sys::UnityInterfaceGUID::new($guid_high, $guid_low) - } - - fn new(interface: *const unity_native_plugin_sys::IUnityInterface) -> Self { - $s { - interface: interface as *const $intf, - } - } - } - - impl $s { - #[allow(dead_code)] - #[inline] - fn interface(&self) -> &$intf { - unsafe { &*self.interface } - } - } - }; -} diff --git a/unity-native-plugin/src/log.rs b/unity-native-plugin/src/log.rs index 63fe67e..4b4bd2e 100644 --- a/unity-native-plugin/src/log.rs +++ b/unity-native-plugin/src/log.rs @@ -1,4 +1,3 @@ -use crate::define_unity_interface; use crate::interface::UnityInterface; use std::ffi::CStr; use unity_native_plugin_sys::*; diff --git a/unity-native-plugin/src/memory_manager.rs b/unity-native-plugin/src/memory_manager.rs index 541a0f1..0248bb6 100644 --- a/unity-native-plugin/src/memory_manager.rs +++ b/unity-native-plugin/src/memory_manager.rs @@ -1,4 +1,3 @@ -use crate::define_unity_interface; use crate::interface::UnityInterface; use std::ffi::{CStr, c_void}; use unity_native_plugin_sys::*; diff --git a/unity-native-plugin/src/metal.rs b/unity-native-plugin/src/metal.rs index 2c20712..c5a6a0d 100644 --- a/unity-native-plugin/src/metal.rs +++ b/unity-native-plugin/src/metal.rs @@ -6,8 +6,8 @@ use objc2_metal::{ }; use unity_native_plugin_sys::{IUnityGraphicsMetalV1, IUnityGraphicsMetalV2, UnityRenderBuffer}; +use crate::graphics; use crate::interface::UnityInterface; -use crate::{define_unity_interface, graphics}; pub trait UnityGraphicsMetalV1Interface { fn metal_bundle(&self) -> Option>; diff --git a/unity-native-plugin/src/profiler.rs b/unity-native-plugin/src/profiler.rs index d580704..cef77db 100644 --- a/unity-native-plugin/src/profiler.rs +++ b/unity-native-plugin/src/profiler.rs @@ -1,5 +1,4 @@ use crate::bitflag; -use crate::define_unity_interface; use crate::interface::UnityInterface; use unity_native_plugin_sys::*; diff --git a/unity-native-plugin/src/profiler_callbacks.rs b/unity-native-plugin/src/profiler_callbacks.rs index 55d4941..2492cba 100644 --- a/unity-native-plugin/src/profiler_callbacks.rs +++ b/unity-native-plugin/src/profiler_callbacks.rs @@ -1,4 +1,3 @@ -use crate::define_unity_interface; use crate::interface::UnityInterface; use crate::profiler::*; use std::ffi::c_void; diff --git a/unity-native-plugin/src/vulkan.rs b/unity-native-plugin/src/vulkan.rs index 104174b..fa038d7 100644 --- a/unity-native-plugin/src/vulkan.rs +++ b/unity-native-plugin/src/vulkan.rs @@ -1,4 +1,3 @@ -use crate::define_unity_interface; use crate::interface::UnityInterface; use ash::vk::Handle; use unity_native_plugin_sys::*; From ad02a5b5781e4f1d03e60a6b7f63033043d0bee2 Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Sun, 3 May 2026 21:16:23 +0900 Subject: [PATCH 03/14] Rename `UnityGraphicsMetalV1Interface` and `UnityGraphicsMetalV2Interface` to `UnityGraphicsMetalV1Ext` and `UnityGraphicsMetalV2Ext`, respectively, and introduce `UnityGraphicsVulkanExt`/`UnityGraphicsVulkanV2Ext` to consolidate extension traits. --- unity-native-plugin-sample/src/lib.rs | 1 + unity-native-plugin-sample/src/metal.rs | 2 +- unity-native-plugin-sample/src/vulkan.rs | 3 +- unity-native-plugin/src/metal.rs | 8 +- unity-native-plugin/src/vulkan.rs | 614 +++++++++++++---------- 5 files changed, 356 insertions(+), 272 deletions(-) diff --git a/unity-native-plugin-sample/src/lib.rs b/unity-native-plugin-sample/src/lib.rs index 91c75de..664cc1d 100644 --- a/unity-native-plugin-sample/src/lib.rs +++ b/unity-native-plugin-sample/src/lib.rs @@ -10,6 +10,7 @@ use std::ffi::c_void; use std::os::raw::c_int; use unity_native_plugin::graphics::GfxRenderer; +use unity_native_plugin::vulkan::UnityGraphicsVulkanExt; 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..444f711 100644 --- a/unity-native-plugin-sample/src/metal.rs +++ b/unity-native-plugin-sample/src/metal.rs @@ -9,7 +9,7 @@ use objc2_metal::{ use unity_native_plugin::interface::UnityInterfaces; use unity_native_plugin::metal::{ - UnityGraphicsMetalV1, UnityGraphicsMetalV1Interface, UnityGraphicsMetalV2, + UnityGraphicsMetalV1, UnityGraphicsMetalV1Ext, UnityGraphicsMetalV2, }; pub fn fill_texture(unity_texture: *mut c_void, x: f32, y: f32, z: f32, w: f32) { diff --git a/unity-native-plugin-sample/src/vulkan.rs b/unity-native-plugin-sample/src/vulkan.rs index 3efe662..b8dbaed 100644 --- a/unity-native-plugin-sample/src/vulkan.rs +++ b/unity-native-plugin-sample/src/vulkan.rs @@ -2,7 +2,8 @@ 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, UnityGraphicsVulkanExt, VulkanGraphicsQueueAccess, + VulkanResourceAccessMode, }; use unity_native_plugin_sys::PFN_vkVoidFunction; diff --git a/unity-native-plugin/src/metal.rs b/unity-native-plugin/src/metal.rs index c5a6a0d..a1fe04e 100644 --- a/unity-native-plugin/src/metal.rs +++ b/unity-native-plugin/src/metal.rs @@ -9,7 +9,7 @@ use unity_native_plugin_sys::{IUnityGraphicsMetalV1, IUnityGraphicsMetalV2, Unit use crate::graphics; use crate::interface::UnityInterface; -pub trait UnityGraphicsMetalV1Interface { +pub trait UnityGraphicsMetalV1Ext { fn metal_bundle(&self) -> Option>; fn metal_device(&self) -> Option>>; fn current_command_buffer(&self) -> Option>>; @@ -36,7 +36,7 @@ pub trait UnityGraphicsMetalV1Interface { macro_rules! impl_metal_v1 { ($intf:ty) => { - impl UnityGraphicsMetalV1Interface for $intf { + impl UnityGraphicsMetalV1Ext for $intf { fn metal_bundle(&self) -> Option> { unsafe { Retained::retain(self.interface().MetalBundle.expect("MetalBundle")() as *mut _) @@ -163,7 +163,7 @@ define_unity_interface!( 0x92138551C15D823D_u64 ); -pub trait UnityGraphicsMetalV2Interface { +pub trait UnityGraphicsMetalV2Ext: UnityGraphicsMetalV1Ext { fn commit_current_command_buffer( &self, ) -> Option>>; @@ -174,7 +174,7 @@ macro_rules! impl_metal_v2 { ($intf:ty) => { impl_metal_v1!($intf); - impl UnityGraphicsMetalV2Interface for $intf { + impl UnityGraphicsMetalV2Ext for $intf { fn commit_current_command_buffer( &self, ) -> Option>> { diff --git a/unity-native-plugin/src/vulkan.rs b/unity-native-plugin/src/vulkan.rs index fa038d7..7cf52a2 100644 --- a/unity-native-plugin/src/vulkan.rs +++ b/unity-native-plugin/src/vulkan.rs @@ -258,282 +258,354 @@ pub struct VulkanSwapchainConfiguration { pub mode: VulkanSwapchainMode, } +pub trait UnityGraphicsVulkanExt { + unsafe fn intercept_initialization( + &self, + func: VulkanInitCallback, + user_data: *mut ::std::os::raw::c_void, + ); + unsafe fn intercept_vulkan_api( + &self, + name: *const ::std::os::raw::c_char, + func: ash::vk::PFN_vkVoidFunction, + ) -> ash::vk::PFN_vkVoidFunction; + fn configure_event(&self, event_id: i32, plugin_event_config: &VulkanPluginEventConfig); + fn instance(&self) -> VulkanInstance; + fn command_recording_state( + &self, + queue_access: VulkanGraphicsQueueAccess, + ) -> Option; + unsafe fn access_texture( + &self, + native_texture: *mut ::std::os::raw::c_void, + sub_resource: Option<&ash::vk::ImageSubresource>, + layout: ash::vk::ImageLayout, + pipeline_stage_flags: ash::vk::PipelineStageFlags, + access_flags: ash::vk::AccessFlags, + access_mode: VulkanResourceAccessMode, + ) -> Option; + unsafe fn access_render_buffer_texture( + &self, + native_render_buffer: crate::graphics::RenderBuffer, + sub_resource: Option<&ash::vk::ImageSubresource>, + layout: ash::vk::ImageLayout, + pipeline_stage_flags: ash::vk::PipelineStageFlags, + access_flags: ash::vk::AccessFlags, + access_mode: VulkanResourceAccessMode, + ) -> Option; + unsafe fn access_render_buffer_resolve_texture( + &self, + native_render_buffer: crate::graphics::RenderBuffer, + sub_resource: Option<&ash::vk::ImageSubresource>, + layout: ash::vk::ImageLayout, + pipeline_stage_flags: ash::vk::PipelineStageFlags, + access_flags: ash::vk::AccessFlags, + access_mode: VulkanResourceAccessMode, + ) -> Option; + unsafe fn access_buffer( + &self, + native_buffer: *mut ::std::os::raw::c_void, + pipeline_stage_flags: ash::vk::PipelineStageFlags, + access_flags: ash::vk::AccessFlags, + access_mode: VulkanResourceAccessMode, + ) -> Option; + fn ensure_outside_render_pass(&self); + fn ensure_inside_render_pass(&self); + unsafe fn access_queue( + &self, + callback: UnityRenderingEventAndData, + event_id: ::std::os::raw::c_int, + user_data: *mut ::std::os::raw::c_void, + flush: bool, + ); + fn configure_swapchain(&self, swapchain_config: &VulkanSwapchainConfiguration) -> bool; + unsafe fn access_texture_by_id( + &self, + texture_id: crate::graphics::TextureID, + sub_resource: Option<&ash::vk::ImageSubresource>, + layout: ash::vk::ImageLayout, + pipeline_stage_flags: ash::vk::PipelineStageFlags, + access_flags: ash::vk::AccessFlags, + access_mode: VulkanResourceAccessMode, + ) -> Option; +} + macro_rules! impl_vulkan { - () => { - pub unsafe fn intercept_initialization( - &self, - func: VulkanInitCallback, - user_data: *mut ::std::os::raw::c_void, - ) { - unsafe { - self.interface() - .InterceptInitialization - .expect("InterceptInitialization")( - std::mem::transmute::(func), - user_data, - ); + ($intf:ty) => { + impl UnityGraphicsVulkanExt for $intf { + unsafe fn intercept_initialization( + &self, + func: VulkanInitCallback, + user_data: *mut ::std::os::raw::c_void, + ) { + unsafe { + self.interface() + .InterceptInitialization + .expect("InterceptInitialization")( + std::mem::transmute::(func), + user_data, + ); + } } - } - pub unsafe fn intercept_vulkan_api( - &self, - name: *const ::std::os::raw::c_char, - func: ash::vk::PFN_vkVoidFunction, - ) -> ash::vk::PFN_vkVoidFunction { - unsafe { - self.interface() - .InterceptVulkanAPI - .expect("InterceptVulkanAPI")(name, func) + unsafe fn intercept_vulkan_api( + &self, + name: *const ::std::os::raw::c_char, + func: ash::vk::PFN_vkVoidFunction, + ) -> ash::vk::PFN_vkVoidFunction { + unsafe { + self.interface() + .InterceptVulkanAPI + .expect("InterceptVulkanAPI")(name, func) + } } - } - pub fn configure_event( - &self, - event_id: i32, - plugin_event_config: &VulkanPluginEventConfig, - ) { - unsafe { - self.interface().ConfigureEvent.expect("ConfigureEvent")( - event_id, - &plugin_event_config.native, - ) + fn configure_event( + &self, + event_id: i32, + plugin_event_config: &VulkanPluginEventConfig, + ) { + unsafe { + self.interface().ConfigureEvent.expect("ConfigureEvent")( + event_id, + &plugin_event_config.native, + ) + } } - } - pub fn instance(&self) -> VulkanInstance { - unsafe { - VulkanInstance { - native: self.interface().Instance.expect("Instance")(), + fn instance(&self) -> VulkanInstance { + unsafe { + VulkanInstance { + native: self.interface().Instance.expect("Instance")(), + } } } - } - pub fn command_recording_state( - &self, - queue_access: VulkanGraphicsQueueAccess, - ) -> Option { - unsafe { - let mut ret = std::mem::zeroed::(); - if self - .interface() - .CommandRecordingState - .expect("CommandRecordingState")( - &mut ret, - queue_access as UnityVulkanGraphicsQueueAccess, - ) { - Some(VulkanRecordingState { native: ret }) - } else { - None + fn command_recording_state( + &self, + queue_access: VulkanGraphicsQueueAccess, + ) -> Option { + unsafe { + let mut ret = std::mem::zeroed::(); + if self + .interface() + .CommandRecordingState + .expect("CommandRecordingState")( + &mut ret, + queue_access as UnityVulkanGraphicsQueueAccess, + ) { + Some(VulkanRecordingState { native: ret }) + } else { + None + } } } - } - pub unsafe fn access_texture( - &self, - native_texture: *mut ::std::os::raw::c_void, - sub_resource: Option<&ash::vk::ImageSubresource>, - layout: ash::vk::ImageLayout, - pipeline_stage_flags: ash::vk::PipelineStageFlags, - access_flags: ash::vk::AccessFlags, - access_mode: VulkanResourceAccessMode, - ) -> Option { - unsafe { - let mut ret = std::mem::zeroed::(); - if self.interface().AccessTexture.expect("AccessTexture")( - native_texture, - match sub_resource { - Some(t) => { - t as *const ash::vk::ImageSubresource as *const VkImageSubresource - } - None => std::ptr::null(), - }, - layout.as_raw() as VkImageLayout, - pipeline_stage_flags.as_raw(), - access_flags.as_raw(), - access_mode as UnityVulkanResourceAccessMode, - &mut ret, - ) { - Some(VulkanImage { native: ret }) - } else { - None + unsafe fn access_texture( + &self, + native_texture: *mut ::std::os::raw::c_void, + sub_resource: Option<&ash::vk::ImageSubresource>, + layout: ash::vk::ImageLayout, + pipeline_stage_flags: ash::vk::PipelineStageFlags, + access_flags: ash::vk::AccessFlags, + access_mode: VulkanResourceAccessMode, + ) -> Option { + unsafe { + let mut ret = std::mem::zeroed::(); + if self.interface().AccessTexture.expect("AccessTexture")( + native_texture, + match sub_resource { + Some(t) => { + t as *const ash::vk::ImageSubresource as *const VkImageSubresource + } + None => std::ptr::null(), + }, + layout.as_raw() as VkImageLayout, + pipeline_stage_flags.as_raw(), + access_flags.as_raw(), + access_mode as UnityVulkanResourceAccessMode, + &mut ret, + ) { + Some(VulkanImage { native: ret }) + } else { + None + } } } - } - pub unsafe fn access_render_buffer_texture( - &self, - native_render_buffer: crate::graphics::RenderBuffer, - sub_resource: Option<&ash::vk::ImageSubresource>, - layout: ash::vk::ImageLayout, - pipeline_stage_flags: ash::vk::PipelineStageFlags, - access_flags: ash::vk::AccessFlags, - access_mode: VulkanResourceAccessMode, - ) -> Option { - unsafe { - let mut ret = std::mem::zeroed::(); - if self - .interface() - .AccessRenderBufferTexture - .expect("AccessRenderBufferTexture")( - native_render_buffer, - match sub_resource { - Some(t) => { - t as *const ash::vk::ImageSubresource as *const VkImageSubresource - } - None => std::ptr::null(), - }, - layout.as_raw() as VkImageLayout, - pipeline_stage_flags.as_raw(), - access_flags.as_raw(), - access_mode as UnityVulkanResourceAccessMode, - &mut ret, - ) { - Some(VulkanImage { native: ret }) - } else { - None + unsafe fn access_render_buffer_texture( + &self, + native_render_buffer: crate::graphics::RenderBuffer, + sub_resource: Option<&ash::vk::ImageSubresource>, + layout: ash::vk::ImageLayout, + pipeline_stage_flags: ash::vk::PipelineStageFlags, + access_flags: ash::vk::AccessFlags, + access_mode: VulkanResourceAccessMode, + ) -> Option { + unsafe { + let mut ret = std::mem::zeroed::(); + if self + .interface() + .AccessRenderBufferTexture + .expect("AccessRenderBufferTexture")( + native_render_buffer, + match sub_resource { + Some(t) => { + t as *const ash::vk::ImageSubresource as *const VkImageSubresource + } + None => std::ptr::null(), + }, + layout.as_raw() as VkImageLayout, + pipeline_stage_flags.as_raw(), + access_flags.as_raw(), + access_mode as UnityVulkanResourceAccessMode, + &mut ret, + ) { + Some(VulkanImage { native: ret }) + } else { + None + } } } - } - pub unsafe fn access_render_buffer_resolve_texture( - &self, - native_render_buffer: crate::graphics::RenderBuffer, - sub_resource: Option<&ash::vk::ImageSubresource>, - layout: ash::vk::ImageLayout, - pipeline_stage_flags: ash::vk::PipelineStageFlags, - access_flags: ash::vk::AccessFlags, - access_mode: VulkanResourceAccessMode, - ) -> Option { - unsafe { - let mut ret = std::mem::zeroed::(); - if self - .interface() - .AccessRenderBufferResolveTexture - .expect("AccessRenderBufferResolveTexture")( - native_render_buffer, - match sub_resource { - Some(t) => { - t as *const ash::vk::ImageSubresource as *const VkImageSubresource - } - None => std::ptr::null(), - }, - layout.as_raw() as VkImageLayout, - pipeline_stage_flags.as_raw(), - access_flags.as_raw(), - access_mode as UnityVulkanResourceAccessMode, - &mut ret, - ) { - Some(VulkanImage { native: ret }) - } else { - None + unsafe fn access_render_buffer_resolve_texture( + &self, + native_render_buffer: crate::graphics::RenderBuffer, + sub_resource: Option<&ash::vk::ImageSubresource>, + layout: ash::vk::ImageLayout, + pipeline_stage_flags: ash::vk::PipelineStageFlags, + access_flags: ash::vk::AccessFlags, + access_mode: VulkanResourceAccessMode, + ) -> Option { + unsafe { + let mut ret = std::mem::zeroed::(); + if self + .interface() + .AccessRenderBufferResolveTexture + .expect("AccessRenderBufferResolveTexture")( + native_render_buffer, + match sub_resource { + Some(t) => { + t as *const ash::vk::ImageSubresource as *const VkImageSubresource + } + None => std::ptr::null(), + }, + layout.as_raw() as VkImageLayout, + pipeline_stage_flags.as_raw(), + access_flags.as_raw(), + access_mode as UnityVulkanResourceAccessMode, + &mut ret, + ) { + Some(VulkanImage { native: ret }) + } else { + None + } } } - } - pub unsafe fn access_buffer( - &self, - native_buffer: *mut ::std::os::raw::c_void, - pipeline_stage_flags: ash::vk::PipelineStageFlags, - access_flags: ash::vk::AccessFlags, - access_mode: VulkanResourceAccessMode, - ) -> Option { - unsafe { - let mut ret = std::mem::zeroed::(); - if self.interface().AccessBuffer.expect("AccessTexture")( - native_buffer, - pipeline_stage_flags.as_raw(), - access_flags.as_raw(), - access_mode as UnityVulkanResourceAccessMode, - &mut ret as *mut UnityVulkanImage as *mut UnityVulkanBuffer, - ) { - Some(VulkanImage { native: ret }) - } else { - None + unsafe fn access_buffer( + &self, + native_buffer: *mut ::std::os::raw::c_void, + pipeline_stage_flags: ash::vk::PipelineStageFlags, + access_flags: ash::vk::AccessFlags, + access_mode: VulkanResourceAccessMode, + ) -> Option { + unsafe { + let mut ret = std::mem::zeroed::(); + if self.interface().AccessBuffer.expect("AccessTexture")( + native_buffer, + pipeline_stage_flags.as_raw(), + access_flags.as_raw(), + access_mode as UnityVulkanResourceAccessMode, + &mut ret as *mut UnityVulkanImage as *mut UnityVulkanBuffer, + ) { + Some(VulkanImage { native: ret }) + } else { + None + } } } - } - pub fn ensure_outside_render_pass(&self) { - unsafe { - self.interface() - .EnsureOutsideRenderPass - .expect("EnsureOutsideRenderPass")() + fn ensure_outside_render_pass(&self) { + unsafe { + self.interface() + .EnsureOutsideRenderPass + .expect("EnsureOutsideRenderPass")() + } } - } - pub fn ensure_inside_render_pass(&self) { - unsafe { - self.interface() - .EnsureInsideRenderPass - .expect("EnsureInsideRenderPass")() + fn ensure_inside_render_pass(&self) { + unsafe { + self.interface() + .EnsureInsideRenderPass + .expect("EnsureInsideRenderPass")() + } } - } - pub unsafe fn access_queue( - &self, - callback: UnityRenderingEventAndData, - event_id: ::std::os::raw::c_int, - user_data: *mut ::std::os::raw::c_void, - flush: bool, - ) { - unsafe { - self.interface().AccessQueue.expect("AccessQueue")( - callback, event_id, user_data, flush, - ); + unsafe fn access_queue( + &self, + callback: UnityRenderingEventAndData, + event_id: ::std::os::raw::c_int, + user_data: *mut ::std::os::raw::c_void, + flush: bool, + ) { + unsafe { + self.interface().AccessQueue.expect("AccessQueue")( + callback, event_id, user_data, flush, + ); + } } - } - pub fn configure_swapchain(&self, swapchain_config: &VulkanSwapchainConfiguration) -> bool { - unsafe { - self.interface() - .ConfigureSwapchain - .expect("ConfigureSwapchain")( - swapchain_config as *const VulkanSwapchainConfiguration - as *const UnityVulkanSwapchainConfiguration, - ) + fn configure_swapchain(&self, swapchain_config: &VulkanSwapchainConfiguration) -> bool { + unsafe { + self.interface() + .ConfigureSwapchain + .expect("ConfigureSwapchain")( + swapchain_config as *const VulkanSwapchainConfiguration + as *const UnityVulkanSwapchainConfiguration, + ) + } } - } - pub unsafe fn access_texture_by_id( - &self, - texture_id: crate::graphics::TextureID, - sub_resource: Option<&ash::vk::ImageSubresource>, - layout: ash::vk::ImageLayout, - pipeline_stage_flags: ash::vk::PipelineStageFlags, - access_flags: ash::vk::AccessFlags, - access_mode: VulkanResourceAccessMode, - ) -> Option { - unsafe { - let mut ret = std::mem::zeroed::(); - if self - .interface() - .AccessTextureByID - .expect("AccessTextureByID")( - texture_id, - match sub_resource { - Some(t) => { - t as *const ash::vk::ImageSubresource as *const VkImageSubresource - } - None => std::ptr::null(), - }, - layout.as_raw() as VkImageLayout, - pipeline_stage_flags.as_raw(), - access_flags.as_raw(), - access_mode as UnityVulkanResourceAccessMode, - &mut ret, - ) { - Some(VulkanImage { native: ret }) - } else { - None + unsafe fn access_texture_by_id( + &self, + texture_id: crate::graphics::TextureID, + sub_resource: Option<&ash::vk::ImageSubresource>, + layout: ash::vk::ImageLayout, + pipeline_stage_flags: ash::vk::PipelineStageFlags, + access_flags: ash::vk::AccessFlags, + access_mode: VulkanResourceAccessMode, + ) -> Option { + unsafe { + let mut ret = std::mem::zeroed::(); + if self + .interface() + .AccessTextureByID + .expect("AccessTextureByID")( + texture_id, + match sub_resource { + Some(t) => { + t as *const ash::vk::ImageSubresource as *const VkImageSubresource + } + None => std::ptr::null(), + }, + layout.as_raw() as VkImageLayout, + pipeline_stage_flags.as_raw(), + access_flags.as_raw(), + access_mode as UnityVulkanResourceAccessMode, + &mut ret, + ) { + Some(VulkanImage { native: ret }) + } else { + None + } } } } }; } -impl UnityGraphicsVulkan { - impl_vulkan!(); -} +impl_vulkan!(UnityGraphicsVulkan); define_unity_interface!( UnityGraphicsVulkanV2, @@ -542,43 +614,53 @@ define_unity_interface!( 0xb347dd92a0097ffc_u64 ); +pub trait UnityGraphicsVulkanV2Ext: UnityGraphicsVulkanExt { + unsafe fn add_intercept_initialization( + &self, + func: VulkanInitCallback, + user_data: *mut ::std::os::raw::c_void, + priority: i32, + ) -> bool; + unsafe fn remove_intercept_initialization(&self, func: VulkanInitCallback) -> bool; +} + macro_rules! impl_vulkan_v2 { - () => { - impl_vulkan!(); - - pub unsafe fn add_intercept_initialization( - &self, - func: VulkanInitCallback, - user_data: *mut ::std::os::raw::c_void, - priority: i32, - ) -> bool { - unsafe { - self.interface() - .AddInterceptInitialization - .expect("AddInterceptInitialization")( - std::mem::transmute::(func), - user_data, - priority, - ) + ($intf:ty) => { + impl_vulkan!($intf); + + impl UnityGraphicsVulkanV2Ext for $intf { + unsafe fn add_intercept_initialization( + &self, + func: VulkanInitCallback, + user_data: *mut ::std::os::raw::c_void, + priority: i32, + ) -> bool { + unsafe { + self.interface() + .AddInterceptInitialization + .expect("AddInterceptInitialization")( + std::mem::transmute::(func), + user_data, + priority, + ) + } } - } - pub unsafe fn remove_intercept_initialization(&self, func: VulkanInitCallback) -> bool { - unsafe { - self.interface() - .RemoveInterceptInitialization - .expect("RemoveInterceptInitialization")(std::mem::transmute::< - VulkanInitCallback, - UnityVulkanInitCallback, - >(func)) + unsafe fn remove_intercept_initialization(&self, func: VulkanInitCallback) -> bool { + unsafe { + self.interface() + .RemoveInterceptInitialization + .expect("RemoveInterceptInitialization")(std::mem::transmute::< + VulkanInitCallback, + UnityVulkanInitCallback, + >(func)) + } } } }; } -impl UnityGraphicsVulkanV2 { - impl_vulkan_v2!(); -} +impl_vulkan_v2!(UnityGraphicsVulkanV2); #[cfg(test)] mod test { From f083b667f8ba9e2f8ee0a6ce6e26b7d43320b0ce Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Sun, 3 May 2026 23:50:30 +0900 Subject: [PATCH 04/14] Refactor D3D12 extension traits into distinct versions (`v2` to `v8`) and adjust implementations for modularity and clarity. Update sample project imports to reflect changes. --- unity-native-plugin-sample/src/d3d12.rs | 1 + unity-native-plugin-sample/src/lib.rs | 2 + unity-native-plugin/src/d3d12.rs | 372 +++++++++++++----------- 3 files changed, 206 insertions(+), 169 deletions(-) diff --git a/unity-native-plugin-sample/src/d3d12.rs b/unity-native-plugin-sample/src/d3d12.rs index a07f349..1e7c4a7 100644 --- a/unity-native-plugin-sample/src/d3d12.rs +++ b/unity-native-plugin-sample/src/d3d12.rs @@ -1,3 +1,4 @@ +use unity_native_plugin::d3d12::{UnityGraphicsD3D12V2Ext, UnityGraphicsD3D12v6Ext}; use winapi::Interface; use winapi::um::d3d12::*; use wio::com::ComPtr; diff --git a/unity-native-plugin-sample/src/lib.rs b/unity-native-plugin-sample/src/lib.rs index 664cc1d..92a1b3d 100644 --- a/unity-native-plugin-sample/src/lib.rs +++ b/unity-native-plugin-sample/src/lib.rs @@ -9,6 +9,8 @@ mod vulkan; use std::ffi::c_void; use std::os::raw::c_int; +#[cfg(windows)] +use unity_native_plugin::d3d12::UnityGraphicsD3D12v6Ext; use unity_native_plugin::graphics::GfxRenderer; use unity_native_plugin::vulkan::UnityGraphicsVulkanExt; diff --git a/unity-native-plugin/src/d3d12.rs b/unity-native-plugin/src/d3d12.rs index 922a1d3..07f02bd 100644 --- a/unity-native-plugin/src/d3d12.rs +++ b/unity-native-plugin/src/d3d12.rs @@ -3,14 +3,9 @@ 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; +pub type ResourceState = UnityGraphicsD3D12ResourceState; +pub type PhysicalVideoMemoryControlValues = UnityGraphicsD3D12PhysicalVideoMemoryControlValues; #[repr(u32)] #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -40,74 +35,114 @@ pub struct PluginEventConfig { pub ensure_active_render_texture_is_bound: bool, } +pub trait UnityGraphicsD3D12V2Ext { + unsafe fn device(&self) -> ComPtr; + unsafe fn frame_fence(&self) -> ComPtr; + fn next_frame_fence_value(&self) -> u64; +} + macro_rules! impl_d3d12_v2 { - () => { - pub unsafe fn device(&self) -> ComPtr { - unsafe { self.interface().GetDevice.expect("GetDevice")() as ComPtr } - } + ($intf:ty) => { + impl UnityGraphicsD3D12V2Ext for $intf { + 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 } - } + 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 + fn next_frame_fence_value(&self) -> u64 { + unsafe { + self.interface() + .GetNextFrameFenceValue + .expect("GetNextFrameFenceValue")() as u64 + } } } }; } +define_unity_interface!( + UnityGraphicsD3D12v2, + IUnityGraphicsD3D12v2, + 0xEC39D2F18446C745_u64, + 0xB1A2626641D6B11F_u64 +); +impl_d3d12_v2!(UnityGraphicsD3D12v2); + +pub trait UnityGraphicsD3D12Ext: UnityGraphicsD3D12V2Ext { + unsafe fn command_queue(&self) -> ComPtr; + fn resource_state(&self, resource: ComPtr) -> Option; + fn set_resource_state(&self, resource: ComPtr, state: i32); +} + macro_rules! impl_d3d12 { - () => { - impl_d3d12_v2!(); + ($intf:ty) => { + impl_d3d12_v2!($intf); - pub unsafe fn command_queue(&self) -> ComPtr { - unsafe { self.interface().GetCommandQueue.expect("GetCommandQueue")() as ComPtr } - } + impl UnityGraphicsD3D12Ext for $intf { + unsafe fn command_queue(&self) -> ComPtr { + unsafe { self.interface().GetCommandQueue.expect("GetCommandQueue")() as ComPtr } + } - pub fn resource_state(&self, resource: ComPtr) -> Option { - 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 + fn resource_state(&self, resource: ComPtr) -> Option { + 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, - ) + 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 + UnityGraphicsD3D12, + IUnityGraphicsD3D12, + 0xEF4CEC88A45F4C4C_u64, + 0xBD295B6F2A38D9DE_u64 ); +impl_d3d12!(UnityGraphicsD3D12); -pub type ResourceState = UnityGraphicsD3D12ResourceState; +pub trait UnityGraphicsD3D12v3Ext: UnityGraphicsD3D12V2Ext { + fn set_physical_video_memory_control_values(&self, mem_info: &PhysicalVideoMemoryControlValues); +} -impl UnityGraphicsD3D12v2 { - impl_d3d12_v2!(); +macro_rules! impl_d3d12_v3 { + ($intf:ty) => { + impl_d3d12_v2!($intf); + + impl UnityGraphicsD3D12v3Ext for $intf { + fn set_physical_video_memory_control_values( + &self, + mem_info: &PhysicalVideoMemoryControlValues, + ) { + unsafe { + self.interface() + .SetPhysicalVideoMemoryControlValues + .expect("SetPhysicalVideoMemoryControlValues")( + mem_info as *const UnityGraphicsD3D12PhysicalVideoMemoryControlValues, + ) + } + } + } + }; } define_unity_interface!( @@ -116,30 +151,22 @@ define_unity_interface!( 0x57C3FAFE59E5E843_u64, 0xBF4F5998474BB600_u64 ); +impl_d3d12_v3!(UnityGraphicsD3D12v3); -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 trait UnityGraphicsD3D12v4Ext: UnityGraphicsD3D12v3Ext { + unsafe fn command_queue(&self) -> ComPtr; } -pub type PhysicalVideoMemoryControlValues = UnityGraphicsD3D12PhysicalVideoMemoryControlValues; +macro_rules! impl_d3d12_v4 { + ($intf:ty) => { + impl_d3d12_v3!($intf); -impl UnityGraphicsD3D12v3 { - impl_d3d12_v3!(); + impl UnityGraphicsD3D12v4Ext for $intf { + unsafe fn command_queue(&self) -> ComPtr { + unsafe { self.interface().GetCommandQueue.expect("GetCommandQueue")() as ComPtr } + } + } + }; } define_unity_interface!( @@ -148,89 +175,110 @@ define_unity_interface!( 0x498FFCC13EC94006_u64, 0xB18F8B0FF67778C8_u64 ); +impl_d3d12_v4!(UnityGraphicsD3D12v4); -macro_rules! impl_d3d12_v4 { - () => { - impl_d3d12_v3!(); +pub trait UnityGraphicsD3D12v5Ext: UnityGraphicsD3D12v4Ext { + unsafe fn texture_from_render_buffer(&self, rb: graphics::RenderBuffer) -> ComPtr; +} - pub unsafe fn command_queue(&self) -> ComPtr { - unsafe { self.interface().GetCommandQueue.expect("GetCommandQueue")() as ComPtr } +macro_rules! impl_d3d12_v5 { + ($intf:ty) => { + impl_d3d12_v4!($intf); + + impl UnityGraphicsD3D12v5Ext for $intf { + unsafe fn texture_from_render_buffer(&self, rb: graphics::RenderBuffer) -> ComPtr { + unsafe { + self.interface() + .TextureFromRenderBuffer + .expect("TextureFromRenderBuffer")(rb) as ComPtr + } + } } }; } -impl UnityGraphicsD3D12v4 { - impl_d3d12_v4!(); -} - define_unity_interface!( UnityGraphicsD3D12v5, IUnityGraphicsD3D12v5, 0xF5C8D8A37D37BC42_u64, 0xB02DFE93B5064A27_u64 ); +impl_d3d12_v5!(UnityGraphicsD3D12v5); -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 +pub trait UnityGraphicsD3D12v6Ext: UnityGraphicsD3D12v5Ext { + fn configure_event(&self, event_id: i32, plugin_event_config: &PluginEventConfig); + unsafe fn command_recording_state(&self) -> Option; +} + +macro_rules! impl_d3d12_v6 { + ($intf:ty) => { + impl_d3d12_v5!($intf); + + impl UnityGraphicsD3D12v6Ext for $intf { + 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) + } + } + + unsafe fn command_recording_state(&self) -> Option { + unsafe { + let mut state: UnityGraphicsD3D12RecordingState = std::mem::zeroed(); + if self + .interface() + .CommandRecordingState + .expect("CommandRecordingState")(&mut state) + { + Some(state.commandList as ComPtr) + } else { + None + } + } } } }; } -impl UnityGraphicsD3D12v5 { - impl_d3d12_v5!(); -} - define_unity_interface!( UnityGraphicsD3D12v6, IUnityGraphicsD3D12v6, 0xA396DCE58CAC4D78_u64, 0xAFDD9B281F20B840_u64 ); +impl_d3d12_v6!(UnityGraphicsD3D12v6); -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 trait UnityGraphicsD3D12v7Ext: UnityGraphicsD3D12v6Ext { + unsafe fn swap_chain(&self) -> ComPtr; + fn sync_interval(&self) -> u32; + fn present_flags(&self) -> u32; +} + +macro_rules! impl_d3d12_v7 { + ($intf:ty) => { + impl_d3d12_v6!($intf); + + impl UnityGraphicsD3D12v7Ext for $intf { + unsafe fn swap_chain(&self) -> ComPtr { + unsafe { self.interface().GetSwapChain.expect("GetSwapChain")() as ComPtr } } - } - pub unsafe fn command_recording_state(&self) -> Option { - unsafe { - let mut state: UnityGraphicsD3D12RecordingState = std::mem::zeroed(); - if self - .interface() - .CommandRecordingState - .expect("CommandRecordingState")(&mut state) - { - Some(state.commandList as ComPtr) - } else { - None - } + fn sync_interval(&self) -> u32 { + unsafe { self.interface().GetSyncInterval.expect("GetSyncInterval")() } + } + + fn present_flags(&self) -> u32 { + unsafe { self.interface().GetPresentFlags.expect("GetPresentFlags")() } } } }; } -impl UnityGraphicsD3D12v6 { - impl_d3d12_v6!(); -} define_unity_interface!( UnityGraphicsD3D12v7, @@ -238,27 +286,42 @@ define_unity_interface!( 0x4624B0DA41B64AAC_u64, 0x915AABCB9BC3F0D3_u64 ); +impl_d3d12_v7!(UnityGraphicsD3D12v7); -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 trait UnityGraphicsD3D12v8Ext: UnityGraphicsD3D12v7Ext { + fn request_resource_state(&self, resource: ComPtr, state: i32); + fn notify_resource_state(&self, resource: ComPtr, state: i32, uav_access: bool); +} - pub fn sync_interval(&self) -> u32 { - unsafe { self.interface().GetSyncInterval.expect("GetSyncInterval")() } - } +macro_rules! impl_d3d12_v8 { + ($intf:ty) => { + impl_d3d12_v7!($intf); + + impl UnityGraphicsD3D12v8Ext for $intf { + fn request_resource_state(&self, resource: ComPtr, state: i32) { + unsafe { + self.interface() + .RequestResourceState + .expect("RequestResourceState")( + resource as *mut ID3D12Resource, state + ) + } + } - pub fn present_flags(&self) -> u32 { - unsafe { self.interface().GetPresentFlags.expect("GetPresentFlags")() } + fn notify_resource_state(&self, resource: ComPtr, state: i32, uav_access: bool) { + unsafe { + self.interface() + .NotifyResourceState + .expect("NotifyResourceState")( + resource as *mut ID3D12Resource, + state, + uav_access, + ) + } + } } }; } -impl UnityGraphicsD3D12v7 { - impl_d3d12_v7!(); -} define_unity_interface!( UnityGraphicsD3D12v8, @@ -266,33 +329,4 @@ define_unity_interface!( 0x9D303045D00D4CFD_u64, 0x8FEBB42968B423B6_u64 ); - -macro_rules! impl_d3d12_v8 { - () => { - impl_d3d12_v7!(); - - pub fn request_resource_state(&self, resource: ComPtr, state: i32) { - unsafe { - self.interface() - .RequestResourceState - .expect("RequestResourceState")(resource as *mut ID3D12Resource, state) - } - } - - pub fn notify_resource_state(&self, resource: ComPtr, state: i32, uav_access: bool) { - unsafe { - self.interface() - .NotifyResourceState - .expect("NotifyResourceState")( - resource as *mut ID3D12Resource, - state, - uav_access, - ) - } - } - }; -} - -impl UnityGraphicsD3D12v8 { - impl_d3d12_v8!(); -} +impl_d3d12_v8!(UnityGraphicsD3D12v8); From 4eaeb20524f57a416ec1eaa60c2e7af9474e95aa Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Sun, 3 May 2026 23:55:12 +0900 Subject: [PATCH 05/14] Extract `ComPtr` type into a shared `windows` module and remove redundant definitions from `d3d11` and `d3d12`. --- unity-native-plugin/src/d3d11.rs | 3 +-- unity-native-plugin/src/d3d12.rs | 2 +- unity-native-plugin/src/lib.rs | 3 +++ unity-native-plugin/src/windows.rs | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 unity-native-plugin/src/windows.rs diff --git a/unity-native-plugin/src/d3d11.rs b/unity-native-plugin/src/d3d11.rs index 0638561..959f1bc 100644 --- a/unity-native-plugin/src/d3d11.rs +++ b/unity-native-plugin/src/d3d11.rs @@ -1,3 +1,4 @@ +use crate::windows::ComPtr; use crate::graphics; use crate::interface::UnityInterface; @@ -8,8 +9,6 @@ define_unity_interface!( 0xBF76967F07EFB177_u64 ); -pub type ComPtr = *mut std::ffi::c_void; - impl UnityGraphicsD3D11 { pub unsafe fn device(&self) -> ComPtr { unsafe { self.interface().GetDevice.expect("GetDevice")() as ComPtr } diff --git a/unity-native-plugin/src/d3d12.rs b/unity-native-plugin/src/d3d12.rs index 07f02bd..5eb14e4 100644 --- a/unity-native-plugin/src/d3d12.rs +++ b/unity-native-plugin/src/d3d12.rs @@ -1,9 +1,9 @@ use crate::bitflag; +use crate::windows::ComPtr; use crate::graphics; use crate::interface::UnityInterface; use unity_native_plugin_sys::*; -pub type ComPtr = *mut std::ffi::c_void; pub type ResourceState = UnityGraphicsD3D12ResourceState; pub type PhysicalVideoMemoryControlValues = UnityGraphicsD3D12PhysicalVideoMemoryControlValues; diff --git a/unity-native-plugin/src/lib.rs b/unity-native-plugin/src/lib.rs index 325627c..bd6ee2b 100644 --- a/unity-native-plugin/src/lib.rs +++ b/unity-native-plugin/src/lib.rs @@ -33,6 +33,9 @@ macro_rules! define_unity_interface { }; } +#[cfg(all(windows, any(feature = "d3d11", feature = "d3d12")))] +pub mod windows; + #[cfg(all(feature = "d3d11", windows))] pub mod d3d11; diff --git a/unity-native-plugin/src/windows.rs b/unity-native-plugin/src/windows.rs new file mode 100644 index 0000000..39b43fc --- /dev/null +++ b/unity-native-plugin/src/windows.rs @@ -0,0 +1 @@ +pub type ComPtr = *mut std::ffi::c_void; From 18f01dfd246404b3d4a9b085cebeff738bc389a4 Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Sun, 3 May 2026 23:58:55 +0900 Subject: [PATCH 06/14] Refactor and modularize D3D11 extension traits with macro-based implementation; update imports for consistency. --- unity-native-plugin-sample/src/d3d11.rs | 1 + unity-native-plugin/src/d3d11.rs | 101 ++++++++++++++---------- unity-native-plugin/src/d3d12.rs | 2 +- 3 files changed, 61 insertions(+), 43 deletions(-) diff --git a/unity-native-plugin-sample/src/d3d11.rs b/unity-native-plugin-sample/src/d3d11.rs index 83db803..706476c 100644 --- a/unity-native-plugin-sample/src/d3d11.rs +++ b/unity-native-plugin-sample/src/d3d11.rs @@ -1,3 +1,4 @@ +use unity_native_plugin::d3d11::UnityGraphicsD3D11Ext; use winapi::shared::dxgiformat; use winapi::um::{d3d11, unknwnbase::IUnknown}; use wio::com::ComPtr; diff --git a/unity-native-plugin/src/d3d11.rs b/unity-native-plugin/src/d3d11.rs index 959f1bc..3ec5ccf 100644 --- a/unity-native-plugin/src/d3d11.rs +++ b/unity-native-plugin/src/d3d11.rs @@ -1,6 +1,6 @@ -use crate::windows::ComPtr; use crate::graphics; use crate::interface::UnityInterface; +use crate::windows::ComPtr; define_unity_interface!( UnityGraphicsD3D11, @@ -9,52 +9,69 @@ define_unity_interface!( 0xBF76967F07EFB177_u64 ); -impl UnityGraphicsD3D11 { - pub unsafe fn device(&self) -> ComPtr { - unsafe { self.interface().GetDevice.expect("GetDevice")() as ComPtr } - } +pub trait UnityGraphicsD3D11Ext { + 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; +} - pub unsafe fn texture_from_render_buffer(&self, buffer: graphics::RenderBuffer) -> ComPtr { - unsafe { - self.interface() - .TextureFromRenderBuffer - .expect("TextureFromRenderBuffer")(buffer) as ComPtr - } - } +macro_rules! impl_d3d11 { + ($intf:ty) => { + impl UnityGraphicsD3D11Ext for $intf { + unsafe fn device(&self) -> ComPtr { + unsafe { self.interface().GetDevice.expect("GetDevice")() 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_render_buffer(&self, buffer: graphics::RenderBuffer) -> ComPtr { + unsafe { + self.interface() + .TextureFromRenderBuffer + .expect("TextureFromRenderBuffer")(buffer) 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 texture_from_native_texture(&self, texture: graphics::TextureID) -> ComPtr { + unsafe { + self.interface() + .TextureFromNativeTexture + .expect("TextureFromNativeTexture")(texture) 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 rtv_from_render_buffer(&self, buffer: graphics::RenderBuffer) -> ComPtr { + unsafe { + self.interface() + .RTVFromRenderBuffer + .expect("RTVFromRenderBuffer")(buffer) 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); diff --git a/unity-native-plugin/src/d3d12.rs b/unity-native-plugin/src/d3d12.rs index 5eb14e4..4132d6a 100644 --- a/unity-native-plugin/src/d3d12.rs +++ b/unity-native-plugin/src/d3d12.rs @@ -1,7 +1,7 @@ use crate::bitflag; -use crate::windows::ComPtr; use crate::graphics; use crate::interface::UnityInterface; +use crate::windows::ComPtr; use unity_native_plugin_sys::*; pub type ResourceState = UnityGraphicsD3D12ResourceState; From 2f1b93da012ff8f852e2af37a5912caf74e41703 Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Mon, 4 May 2026 00:04:25 +0900 Subject: [PATCH 07/14] Simplify Vulkan function pointer handling by removing `unwrap_pfn` and updating `get_instance_proc_addr` return type. --- unity-native-plugin-sample/src/vulkan.rs | 10 +--------- unity-native-plugin/src/vulkan.rs | 4 ++-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/unity-native-plugin-sample/src/vulkan.rs b/unity-native-plugin-sample/src/vulkan.rs index b8dbaed..9176c26 100644 --- a/unity-native-plugin-sample/src/vulkan.rs +++ b/unity-native-plugin-sample/src/vulkan.rs @@ -5,14 +5,6 @@ use unity_native_plugin::vulkan::{ UnityGraphicsVulkan, UnityGraphicsVulkanExt, VulkanGraphicsQueueAccess, VulkanResourceAccessMode, }; -use unity_native_plugin_sys::PFN_vkVoidFunction; - -unsafe fn unwrap_pfn(f: PFN_vkVoidFunction) -> Option { - 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 { @@ -51,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(), diff --git a/unity-native-plugin/src/vulkan.rs b/unity-native-plugin/src/vulkan.rs index 7cf52a2..ebf31c0 100644 --- a/unity-native-plugin/src/vulkan.rs +++ b/unity-native-plugin/src/vulkan.rs @@ -48,11 +48,11 @@ impl VulkanInstance { pub unsafe fn get_instance_proc_addr( &self, name: *const std::os::raw::c_char, - ) -> PFN_vkVoidFunction { + ) -> ash::vk::PFN_vkVoidFunction { if let Some(f) = self.native.getInstanceProcAddr { unsafe { (f)(self.native.instance, name) } } else { - PFN_vkVoidFunction::None + None } } } From f02c4cb359ce5a1b3df51dbec224c1a3d8ac8f9c Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Mon, 4 May 2026 00:21:45 +0900 Subject: [PATCH 08/14] Document platform-specific feature gating and runtime behavior in README.md. --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 372c5dc..7e2f531 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,27 @@ unity-native-plugin = { version = "*", features = ["d3d11"] } * 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`, `profiler_callbacks` | 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! { From 1fbe592d7bc47a6f21015d2237e8cb7b6f864151 Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Mon, 4 May 2026 00:23:44 +0900 Subject: [PATCH 09/14] Consolidate `profiler` and `profiler_callbacks` features into a single `profiler` feature; update README and dependencies accordingly. --- README.md | 5 ++--- unity-native-plugin-sample-profiler/Cargo.toml | 2 +- unity-native-plugin/Cargo.toml | 1 - unity-native-plugin/src/lib.rs | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7e2f531..d8d20e8 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,7 @@ 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. @@ -30,7 +29,7 @@ The graphics features are gated by both a feature flag **and** a target `cfg`: | `d3d11`, `d3d12` | Windows (`cfg(windows)`) | | `metal` | Apple platforms (`cfg(target_vendor = "apple")`) | | `vulkan` | Cross-platform | -| `profiler`, `profiler_callbacks` | 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: diff --git a/unity-native-plugin-sample-profiler/Cargo.toml b/unity-native-plugin-sample-profiler/Cargo.toml index 503fd2e..e94812f 100644 --- a/unity-native-plugin-sample-profiler/Cargo.toml +++ b/unity-native-plugin-sample-profiler/Cargo.toml @@ -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" diff --git a/unity-native-plugin/Cargo.toml b/unity-native-plugin/Cargo.toml index d518681..eed2912 100644 --- a/unity-native-plugin/Cargo.toml +++ b/unity-native-plugin/Cargo.toml @@ -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 } diff --git a/unity-native-plugin/src/lib.rs b/unity-native-plugin/src/lib.rs index bd6ee2b..46dda3d 100644 --- a/unity-native-plugin/src/lib.rs +++ b/unity-native-plugin/src/lib.rs @@ -54,7 +54,7 @@ pub use ash; #[cfg(feature = "profiler")] pub mod profiler; -#[cfg(feature = "profiler_callbacks")] +#[cfg(feature = "profiler")] pub mod profiler_callbacks; mod bitflag; From 5e01aae116695db0c2f71f5b3be86e581f01a924 Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Mon, 4 May 2026 07:31:19 +0900 Subject: [PATCH 10/14] =?UTF-8?q?Fix=20typo=20in=20Vulkan=20interface=20er?= =?UTF-8?q?ror=20message:=20"AccessTexture"=20=E2=86=92=20"AccessBuffer"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- unity-native-plugin/src/vulkan.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unity-native-plugin/src/vulkan.rs b/unity-native-plugin/src/vulkan.rs index ebf31c0..dee3670 100644 --- a/unity-native-plugin/src/vulkan.rs +++ b/unity-native-plugin/src/vulkan.rs @@ -512,7 +512,7 @@ macro_rules! impl_vulkan { ) -> Option { unsafe { let mut ret = std::mem::zeroed::(); - if self.interface().AccessBuffer.expect("AccessTexture")( + if self.interface().AccessBuffer.expect("AccessBuffer")( native_buffer, pipeline_stage_flags.as_raw(), access_flags.as_raw(), From 75cbc2d91ad18753f5ab90f1b740fcec08c9532b Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Mon, 4 May 2026 08:07:14 +0900 Subject: [PATCH 11/14] =?UTF-8?q?Add=20migration=20guide=20for=200.8=20?= =?UTF-8?q?=E2=86=92=200.9=20in=20README.md,=20documenting=20feature=20con?= =?UTF-8?q?solidation,=20module=20path=20changes,=20renamed=20identifiers,?= =?UTF-8?q?=20and=20updated=20method=20traits.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/README.md b/README.md index d8d20e8..73ecfcd 100644 --- a/README.md +++ b/README.md @@ -64,3 +64,72 @@ 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 `*Ext` traits + +The inherent `impl` blocks on `UnityGraphicsD3D11`, `UnityGraphicsD3D12*` and `UnityGraphicsVulkan*` have been replaced with extension traits. To call any method, bring the matching trait into scope: + +```rust +use unity_native_plugin::d3d11::UnityGraphicsD3D11Ext; +use unity_native_plugin::d3d12::{ + UnityGraphicsD3D12Ext, // for UnityGraphicsD3D12 + UnityGraphicsD3D12V2Ext, // for UnityGraphicsD3D12v2 + UnityGraphicsD3D12v3Ext, // ... v3 .. v7Ext for the corresponding interface versions +}; +use unity_native_plugin::vulkan::{UnityGraphicsVulkanExt, UnityGraphicsVulkanV2Ext}; +``` + +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 +} +``` From 3ccd78654baee598b0d126370de5d7dba771a8ea Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Mon, 4 May 2026 08:22:09 +0900 Subject: [PATCH 12/14] Rename all `Ext` suffixes in graphics interface traits to `Interface` for consistency across modules; update imports and implementations accordingly. --- unity-native-plugin-sample/src/d3d11.rs | 2 +- unity-native-plugin-sample/src/d3d12.rs | 2 +- unity-native-plugin-sample/src/lib.rs | 4 +-- unity-native-plugin-sample/src/metal.rs | 2 +- unity-native-plugin-sample/src/vulkan.rs | 2 +- unity-native-plugin/src/d3d11.rs | 4 +-- unity-native-plugin/src/d3d12.rs | 32 ++++++++++++------------ unity-native-plugin/src/metal.rs | 8 +++--- unity-native-plugin/src/vulkan.rs | 8 +++--- 9 files changed, 32 insertions(+), 32 deletions(-) diff --git a/unity-native-plugin-sample/src/d3d11.rs b/unity-native-plugin-sample/src/d3d11.rs index 706476c..eb9d71b 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::UnityGraphicsD3D11Ext; +use unity_native_plugin::d3d11::UnityGraphicsD3D11Interface; 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 1e7c4a7..6e20289 100644 --- a/unity-native-plugin-sample/src/d3d12.rs +++ b/unity-native-plugin-sample/src/d3d12.rs @@ -1,4 +1,4 @@ -use unity_native_plugin::d3d12::{UnityGraphicsD3D12V2Ext, UnityGraphicsD3D12v6Ext}; +use unity_native_plugin::d3d12::{UnityGraphicsD3D12V2Interface, UnityGraphicsD3D12v6Interface}; use winapi::Interface; use winapi::um::d3d12::*; use wio::com::ComPtr; diff --git a/unity-native-plugin-sample/src/lib.rs b/unity-native-plugin-sample/src/lib.rs index 92a1b3d..abf7783 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::UnityGraphicsD3D12v6Ext; +use unity_native_plugin::d3d12::UnityGraphicsD3D12v6Interface; use unity_native_plugin::graphics::GfxRenderer; -use unity_native_plugin::vulkan::UnityGraphicsVulkanExt; +use unity_native_plugin::vulkan::UnityGraphicsVulkanInterface; 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 444f711..32c08dd 100644 --- a/unity-native-plugin-sample/src/metal.rs +++ b/unity-native-plugin-sample/src/metal.rs @@ -9,7 +9,7 @@ use objc2_metal::{ use unity_native_plugin::interface::UnityInterfaces; use unity_native_plugin::metal::{ - UnityGraphicsMetalV1, UnityGraphicsMetalV1Ext, UnityGraphicsMetalV2, + UnityGraphicsMetalV1, UnityGraphicsMetalV1Interface, UnityGraphicsMetalV2, }; pub fn fill_texture(unity_texture: *mut c_void, x: f32, y: f32, z: f32, w: f32) { diff --git a/unity-native-plugin-sample/src/vulkan.rs b/unity-native-plugin-sample/src/vulkan.rs index 9176c26..01b1039 100644 --- a/unity-native-plugin-sample/src/vulkan.rs +++ b/unity-native-plugin-sample/src/vulkan.rs @@ -2,7 +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, UnityGraphicsVulkanExt, VulkanGraphicsQueueAccess, + UnityGraphicsVulkan, UnityGraphicsVulkanInterface, VulkanGraphicsQueueAccess, VulkanResourceAccessMode, }; diff --git a/unity-native-plugin/src/d3d11.rs b/unity-native-plugin/src/d3d11.rs index 3ec5ccf..f9fe350 100644 --- a/unity-native-plugin/src/d3d11.rs +++ b/unity-native-plugin/src/d3d11.rs @@ -9,7 +9,7 @@ define_unity_interface!( 0xBF76967F07EFB177_u64 ); -pub trait UnityGraphicsD3D11Ext { +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; @@ -22,7 +22,7 @@ pub trait UnityGraphicsD3D11Ext { macro_rules! impl_d3d11 { ($intf:ty) => { - impl UnityGraphicsD3D11Ext for $intf { + impl UnityGraphicsD3D11Interface for $intf { unsafe fn device(&self) -> ComPtr { unsafe { self.interface().GetDevice.expect("GetDevice")() as ComPtr } } diff --git a/unity-native-plugin/src/d3d12.rs b/unity-native-plugin/src/d3d12.rs index 4132d6a..c22217f 100644 --- a/unity-native-plugin/src/d3d12.rs +++ b/unity-native-plugin/src/d3d12.rs @@ -35,7 +35,7 @@ pub struct PluginEventConfig { pub ensure_active_render_texture_is_bound: bool, } -pub trait UnityGraphicsD3D12V2Ext { +pub trait UnityGraphicsD3D12V2Interface { unsafe fn device(&self) -> ComPtr; unsafe fn frame_fence(&self) -> ComPtr; fn next_frame_fence_value(&self) -> u64; @@ -43,7 +43,7 @@ pub trait UnityGraphicsD3D12V2Ext { macro_rules! impl_d3d12_v2 { ($intf:ty) => { - impl UnityGraphicsD3D12V2Ext for $intf { + impl UnityGraphicsD3D12V2Interface for $intf { unsafe fn device(&self) -> ComPtr { unsafe { self.interface().GetDevice.expect("GetDevice")() as ComPtr } } @@ -71,7 +71,7 @@ define_unity_interface!( ); impl_d3d12_v2!(UnityGraphicsD3D12v2); -pub trait UnityGraphicsD3D12Ext: UnityGraphicsD3D12V2Ext { +pub trait UnityGraphicsD3D12Interface: UnityGraphicsD3D12V2Interface { unsafe fn command_queue(&self) -> ComPtr; fn resource_state(&self, resource: ComPtr) -> Option; fn set_resource_state(&self, resource: ComPtr, state: i32); @@ -81,7 +81,7 @@ macro_rules! impl_d3d12 { ($intf:ty) => { impl_d3d12_v2!($intf); - impl UnityGraphicsD3D12Ext for $intf { + impl UnityGraphicsD3D12Interface for $intf { unsafe fn command_queue(&self) -> ComPtr { unsafe { self.interface().GetCommandQueue.expect("GetCommandQueue")() as ComPtr } } @@ -120,7 +120,7 @@ define_unity_interface!( ); impl_d3d12!(UnityGraphicsD3D12); -pub trait UnityGraphicsD3D12v3Ext: UnityGraphicsD3D12V2Ext { +pub trait UnityGraphicsD3D12v3Interface: UnityGraphicsD3D12V2Interface { fn set_physical_video_memory_control_values(&self, mem_info: &PhysicalVideoMemoryControlValues); } @@ -128,7 +128,7 @@ macro_rules! impl_d3d12_v3 { ($intf:ty) => { impl_d3d12_v2!($intf); - impl UnityGraphicsD3D12v3Ext for $intf { + impl UnityGraphicsD3D12v3Interface for $intf { fn set_physical_video_memory_control_values( &self, mem_info: &PhysicalVideoMemoryControlValues, @@ -153,7 +153,7 @@ define_unity_interface!( ); impl_d3d12_v3!(UnityGraphicsD3D12v3); -pub trait UnityGraphicsD3D12v4Ext: UnityGraphicsD3D12v3Ext { +pub trait UnityGraphicsD3D12v4Interface: UnityGraphicsD3D12v3Interface { unsafe fn command_queue(&self) -> ComPtr; } @@ -161,7 +161,7 @@ macro_rules! impl_d3d12_v4 { ($intf:ty) => { impl_d3d12_v3!($intf); - impl UnityGraphicsD3D12v4Ext for $intf { + impl UnityGraphicsD3D12v4Interface for $intf { unsafe fn command_queue(&self) -> ComPtr { unsafe { self.interface().GetCommandQueue.expect("GetCommandQueue")() as ComPtr } } @@ -177,7 +177,7 @@ define_unity_interface!( ); impl_d3d12_v4!(UnityGraphicsD3D12v4); -pub trait UnityGraphicsD3D12v5Ext: UnityGraphicsD3D12v4Ext { +pub trait UnityGraphicsD3D12v5Interface: UnityGraphicsD3D12v4Interface { unsafe fn texture_from_render_buffer(&self, rb: graphics::RenderBuffer) -> ComPtr; } @@ -185,7 +185,7 @@ macro_rules! impl_d3d12_v5 { ($intf:ty) => { impl_d3d12_v4!($intf); - impl UnityGraphicsD3D12v5Ext for $intf { + impl UnityGraphicsD3D12v5Interface for $intf { unsafe fn texture_from_render_buffer(&self, rb: graphics::RenderBuffer) -> ComPtr { unsafe { self.interface() @@ -205,7 +205,7 @@ define_unity_interface!( ); impl_d3d12_v5!(UnityGraphicsD3D12v5); -pub trait UnityGraphicsD3D12v6Ext: UnityGraphicsD3D12v5Ext { +pub trait UnityGraphicsD3D12v6Interface: UnityGraphicsD3D12v5Interface { fn configure_event(&self, event_id: i32, plugin_event_config: &PluginEventConfig); unsafe fn command_recording_state(&self) -> Option; } @@ -214,7 +214,7 @@ macro_rules! impl_d3d12_v6 { ($intf:ty) => { impl_d3d12_v5!($intf); - impl UnityGraphicsD3D12v6Ext for $intf { + impl UnityGraphicsD3D12v6Interface for $intf { fn configure_event(&self, event_id: i32, plugin_event_config: &PluginEventConfig) { unsafe { let cfg = UnityD3D12PluginEventConfig { @@ -254,7 +254,7 @@ define_unity_interface!( ); impl_d3d12_v6!(UnityGraphicsD3D12v6); -pub trait UnityGraphicsD3D12v7Ext: UnityGraphicsD3D12v6Ext { +pub trait UnityGraphicsD3D12v7Interface: UnityGraphicsD3D12v6Interface { unsafe fn swap_chain(&self) -> ComPtr; fn sync_interval(&self) -> u32; fn present_flags(&self) -> u32; @@ -264,7 +264,7 @@ macro_rules! impl_d3d12_v7 { ($intf:ty) => { impl_d3d12_v6!($intf); - impl UnityGraphicsD3D12v7Ext for $intf { + impl UnityGraphicsD3D12v7Interface for $intf { unsafe fn swap_chain(&self) -> ComPtr { unsafe { self.interface().GetSwapChain.expect("GetSwapChain")() as ComPtr } } @@ -288,7 +288,7 @@ define_unity_interface!( ); impl_d3d12_v7!(UnityGraphicsD3D12v7); -pub trait UnityGraphicsD3D12v8Ext: UnityGraphicsD3D12v7Ext { +pub trait UnityGraphicsD3D12v8Interface: UnityGraphicsD3D12v7Interface { fn request_resource_state(&self, resource: ComPtr, state: i32); fn notify_resource_state(&self, resource: ComPtr, state: i32, uav_access: bool); } @@ -297,7 +297,7 @@ macro_rules! impl_d3d12_v8 { ($intf:ty) => { impl_d3d12_v7!($intf); - impl UnityGraphicsD3D12v8Ext for $intf { + impl UnityGraphicsD3D12v8Interface for $intf { fn request_resource_state(&self, resource: ComPtr, state: i32) { unsafe { self.interface() diff --git a/unity-native-plugin/src/metal.rs b/unity-native-plugin/src/metal.rs index a1fe04e..4678988 100644 --- a/unity-native-plugin/src/metal.rs +++ b/unity-native-plugin/src/metal.rs @@ -9,7 +9,7 @@ use unity_native_plugin_sys::{IUnityGraphicsMetalV1, IUnityGraphicsMetalV2, Unit use crate::graphics; use crate::interface::UnityInterface; -pub trait UnityGraphicsMetalV1Ext { +pub trait UnityGraphicsMetalV1Interface { fn metal_bundle(&self) -> Option>; fn metal_device(&self) -> Option>>; fn current_command_buffer(&self) -> Option>>; @@ -36,7 +36,7 @@ pub trait UnityGraphicsMetalV1Ext { macro_rules! impl_metal_v1 { ($intf:ty) => { - impl UnityGraphicsMetalV1Ext for $intf { + impl UnityGraphicsMetalV1Interface for $intf { fn metal_bundle(&self) -> Option> { unsafe { Retained::retain(self.interface().MetalBundle.expect("MetalBundle")() as *mut _) @@ -163,7 +163,7 @@ define_unity_interface!( 0x92138551C15D823D_u64 ); -pub trait UnityGraphicsMetalV2Ext: UnityGraphicsMetalV1Ext { +pub trait UnityGraphicsMetalV2Interface: UnityGraphicsMetalV1Interface { fn commit_current_command_buffer( &self, ) -> Option>>; @@ -174,7 +174,7 @@ macro_rules! impl_metal_v2 { ($intf:ty) => { impl_metal_v1!($intf); - impl UnityGraphicsMetalV2Ext for $intf { + impl UnityGraphicsMetalV2Interface for $intf { fn commit_current_command_buffer( &self, ) -> Option>> { diff --git a/unity-native-plugin/src/vulkan.rs b/unity-native-plugin/src/vulkan.rs index dee3670..2432b8e 100644 --- a/unity-native-plugin/src/vulkan.rs +++ b/unity-native-plugin/src/vulkan.rs @@ -258,7 +258,7 @@ pub struct VulkanSwapchainConfiguration { pub mode: VulkanSwapchainMode, } -pub trait UnityGraphicsVulkanExt { +pub trait UnityGraphicsVulkanInterface { unsafe fn intercept_initialization( &self, func: VulkanInitCallback, @@ -332,7 +332,7 @@ pub trait UnityGraphicsVulkanExt { macro_rules! impl_vulkan { ($intf:ty) => { - impl UnityGraphicsVulkanExt for $intf { + impl UnityGraphicsVulkanInterface for $intf { unsafe fn intercept_initialization( &self, func: VulkanInitCallback, @@ -614,7 +614,7 @@ define_unity_interface!( 0xb347dd92a0097ffc_u64 ); -pub trait UnityGraphicsVulkanV2Ext: UnityGraphicsVulkanExt { +pub trait UnityGraphicsVulkanV2Interface: UnityGraphicsVulkanInterface { unsafe fn add_intercept_initialization( &self, func: VulkanInitCallback, @@ -628,7 +628,7 @@ macro_rules! impl_vulkan_v2 { ($intf:ty) => { impl_vulkan!($intf); - impl UnityGraphicsVulkanV2Ext for $intf { + impl UnityGraphicsVulkanV2Interface for $intf { unsafe fn add_intercept_initialization( &self, func: VulkanInitCallback, From 39469e0f1bdadad20e1ab7586bfee9a78a986de2 Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Mon, 4 May 2026 08:30:56 +0900 Subject: [PATCH 13/14] Update README: rename `*Ext` suffixes to `*Interface` in examples; document trait changes and add Metal interfaces. --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 73ecfcd..492029c 100644 --- a/README.md +++ b/README.md @@ -94,18 +94,19 @@ 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 `*Ext` traits +### Methods are now provided through `*Interface` traits -The inherent `impl` blocks on `UnityGraphicsD3D11`, `UnityGraphicsD3D12*` and `UnityGraphicsVulkan*` have been replaced with extension traits. To call any method, bring the matching trait into scope: +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::UnityGraphicsD3D11Ext; +use unity_native_plugin::d3d11::UnityGraphicsD3D11Interface; use unity_native_plugin::d3d12::{ - UnityGraphicsD3D12Ext, // for UnityGraphicsD3D12 - UnityGraphicsD3D12V2Ext, // for UnityGraphicsD3D12v2 - UnityGraphicsD3D12v3Ext, // ... v3 .. v7Ext for the corresponding interface versions + UnityGraphicsD3D12Interface, // for UnityGraphicsD3D12 + UnityGraphicsD3D12V2Interface, // for UnityGraphicsD3D12v2 + UnityGraphicsD3D12v3Interface, // ... v3 .. v8Interface for the corresponding interface versions }; -use unity_native_plugin::vulkan::{UnityGraphicsVulkanExt, UnityGraphicsVulkanV2Ext}; +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. From b478fbcb7f2b3b9f4d31676163423dc5c469425e Mon Sep 17 00:00:00 2001 From: Yasuhiro Taniuchi Date: Mon, 4 May 2026 08:44:05 +0900 Subject: [PATCH 14/14] Import UnityGraphicsD3D12v8Interface in sample to fix Windows clippy --- unity-native-plugin-sample/src/d3d12.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/unity-native-plugin-sample/src/d3d12.rs b/unity-native-plugin-sample/src/d3d12.rs index 6e20289..0fd490b 100644 --- a/unity-native-plugin-sample/src/d3d12.rs +++ b/unity-native-plugin-sample/src/d3d12.rs @@ -1,4 +1,6 @@ -use unity_native_plugin::d3d12::{UnityGraphicsD3D12V2Interface, UnityGraphicsD3D12v6Interface}; +use unity_native_plugin::d3d12::{ + UnityGraphicsD3D12V2Interface, UnityGraphicsD3D12v6Interface, UnityGraphicsD3D12v8Interface, +}; use winapi::Interface; use winapi::um::d3d12::*; use wio::com::ComPtr;