use unity_native_plugin::define_unity_interface;
use unity_native_plugin::interface::UnityInterface;
use unity_native_plugin_sys::*;
define_unity_interface!(
UnityGraphicsVulkan,
unity_native_plugin_sys::IUnityGraphicsVulkan,
0x95355348d4ef4e11_u64,
0x9789313dfcffcc87_u64
);
pub type VulkanInitCallback = UnityVulkanInitCallback;
#[repr(C)]
pub struct VulkanInstance {
pub pipeline_cache: ash::vk::PipelineCache,
pub instance: ash::vk::Instance,
pub physical_device: ash::vk::PhysicalDevice,
pub device: ash::vk::Device,
pub graphics_queue: ash::vk::Queue,
get_instance_proc_addr: ash::vk::PFN_vkGetInstanceProcAddr,
pub queue_family_index: ::std::os::raw::c_uint,
reserved: [*mut ::std::os::raw::c_void; 8usize],
}
impl VulkanInstance {
pub unsafe fn get_instance_proc_addr(
&self,
name: *const std::os::raw::c_char,
) -> ash::vk::PFN_vkVoidFunction {
std::mem::transmute((self.get_instance_proc_addr)(self.instance, name))
}
}
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum VulkanEventRenderPassPreCondition {
DontCare = UnityVulkanEventRenderPassPreCondition_kUnityVulkanRenderPass_DontCare,
EnsureInside = UnityVulkanEventRenderPassPreCondition_kUnityVulkanRenderPass_EnsureInside,
EnsureOutside = UnityVulkanEventRenderPassPreCondition_kUnityVulkanRenderPass_EnsureOutside,
}
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum VulkanGraphicsQueueAccess {
DontCare = UnityVulkanGraphicsQueueAccess_kUnityVulkanGraphicsQueueAccess_DontCare,
Allow = UnityVulkanGraphicsQueueAccess_kUnityVulkanGraphicsQueueAccess_Allow,
}
#[repr(C)]
pub struct VulkanPluginEventConfig {
pub render_pass_precondition: VulkanEventRenderPassPreCondition,
pub graphics_queue_access: VulkanGraphicsQueueAccess,
pub flags: u32,
}
#[repr(C)]
pub struct VulkanRecordingState {
pub command_buffer: ash::vk::CommandBuffer,
pub command_buffer_level: ash::vk::CommandBufferLevel,
pub render_pass: ash::vk::RenderPass,
pub framebuffer: ash::vk::Framebuffer,
pub sub_pass_index: ::std::os::raw::c_int,
pub current_frame_number: ::std::os::raw::c_ulonglong,
pub safe_frame_number: ::std::os::raw::c_ulonglong,
reserved: [*mut ::std::os::raw::c_void; 4usize],
}
#[repr(C)]
pub struct VulkanMemory {
pub memory: ash::vk::DeviceMemory,
pub offset: ash::vk::DeviceSize,
pub size: ash::vk::DeviceSize,
pub mapped: *mut ::std::os::raw::c_void,
pub flags: ash::vk::MemoryPropertyFlags,
pub memory_type_index: ::std::os::raw::c_uint,
reserved: [*mut ::std::os::raw::c_void; 4usize],
}
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum VulkanResourceAccessMode {
ObserveOnly = UnityVulkanResourceAccessMode_kUnityVulkanResourceAccess_ObserveOnly,
PipelineBarrier = UnityVulkanResourceAccessMode_kUnityVulkanResourceAccess_PipelineBarrier,
Recreate = UnityVulkanResourceAccessMode_kUnityVulkanResourceAccess_Recreate,
}
#[repr(C)]
pub struct VulkanImage {
pub memory: VulkanMemory,
pub image: ash::vk::Image,
pub layout: ash::vk::ImageLayout,
pub aspect: ash::vk::ImageAspectFlags,
pub usage: ash::vk::ImageUsageFlags,
pub format: ash::vk::Format,
pub extent: ash::vk::Extent3D,
pub tiling: ash::vk::ImageTiling,
pub type_: ash::vk::ImageType,
pub samples: ash::vk::SampleCountFlags,
pub layers: ::std::os::raw::c_int,
pub mip_count: ::std::os::raw::c_int,
reserved: [*mut ::std::os::raw::c_void; 4usize],
}
#[repr(u32)]
#[derive(Copy, Clone)]
pub enum VulkanSwapchainMode {
Default = UnityVulkanSwapchainMode_kUnityVulkanSwapchainMode_Default,
Offscreen = UnityVulkanSwapchainMode_kUnityVulkanSwapchainMode_Offscreen,
}
#[repr(C)]
pub struct VulkanSwapchainConfiguration {
pub mode: VulkanSwapchainMode,
}
impl UnityGraphicsVulkan {
pub unsafe fn intercept_initialization(
&self,
func: VulkanInitCallback,
userdata: *mut ::std::os::raw::c_void,
) {
self.interface()
.InterceptInitialization
.expect("InterceptInitialization")(func, userdata);
}
pub unsafe fn intercept_vulkan_api(
&self,
name: *const ::std::os::raw::c_char,
func: ash::vk::PFN_vkVoidFunction,
) -> ash::vk::PFN_vkVoidFunction {
std::mem::transmute(self
.interface()
.InterceptVulkanAPI
.expect("InterceptVulkanAPI")(
name, std::mem::transmute(func)
))
}
pub fn configure_event(&self, event_id: i32, plugin_event_config: &VulkanPluginEventConfig) {
unsafe {
self.interface().ConfigureEvent.expect("ConfigureEvent")(
event_id,
std::mem::transmute(plugin_event_config),
)
}
}
pub fn instance(&self) -> VulkanInstance {
unsafe { std::mem::transmute(self.interface().Instance.expect("Instance")()) }
}
pub fn command_recording_state(
&self,
queue_access: VulkanGraphicsQueueAccess,
) -> Option<VulkanRecordingState> {
unsafe {
let mut ret = std::mem::zeroed::<VulkanRecordingState>();
if self
.interface()
.CommandRecordingState
.expect("CommandRecordingState")(
std::mem::transmute(&mut ret),
queue_access as UnityVulkanGraphicsQueueAccess,
) {
Some(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<VulkanImage> {
let mut ret = std::mem::zeroed::<VulkanImage>();
if self.interface().AccessTexture.expect("AccessTexture")(
native_texture,
match sub_resource {
Some(t) => std::mem::transmute(t),
None => std::ptr::null(),
},
std::mem::transmute(layout),
std::mem::transmute(pipeline_stage_flags),
std::mem::transmute(access_flags),
access_mode as UnityVulkanResourceAccessMode,
std::mem::transmute(&mut ret),
) {
Some(ret)
} else {
None
}
}
pub unsafe fn access_render_buffer_texture(
&self,
native_render_buffer: unity_native_plugin::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<VulkanImage> {
let mut ret = std::mem::zeroed::<VulkanImage>();
if self
.interface()
.AccessRenderBufferTexture
.expect("AccessRenderBufferTexture")(
native_render_buffer,
match sub_resource {
Some(t) => std::mem::transmute(t),
None => std::ptr::null(),
},
std::mem::transmute(layout),
std::mem::transmute(pipeline_stage_flags),
std::mem::transmute(access_flags),
access_mode as UnityVulkanResourceAccessMode,
std::mem::transmute(&mut ret),
) {
Some(ret)
} else {
None
}
}
pub unsafe fn access_render_buffer_resolve_texture(
&self,
native_render_buffer: unity_native_plugin::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<VulkanImage> {
let mut ret = std::mem::zeroed::<VulkanImage>();
if self
.interface()
.AccessRenderBufferResolveTexture
.expect("AccessRenderBufferResolveTexture")(
native_render_buffer,
match sub_resource {
Some(t) => std::mem::transmute(t),
None => std::ptr::null(),
},
std::mem::transmute(layout),
std::mem::transmute(pipeline_stage_flags),
std::mem::transmute(access_flags),
access_mode as UnityVulkanResourceAccessMode,
std::mem::transmute(&mut ret),
) {
Some(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<VulkanImage> {
let mut ret = std::mem::zeroed::<VulkanImage>();
if self.interface().AccessBuffer.expect("AccessTexture")(
native_buffer,
std::mem::transmute(pipeline_stage_flags),
std::mem::transmute(access_flags),
access_mode as UnityVulkanResourceAccessMode,
std::mem::transmute(&mut ret),
) {
Some(ret)
} else {
None
}
}
pub 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")()
}
}
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,
) {
self.interface().AccessQueue.expect("AccessQueue")(callback, event_id, user_data, flush);
}
pub fn config_swapchain(&self, swapchain_config: &VulkanSwapchainConfiguration) -> bool {
unsafe {
self.interface()
.ConfigureSwapchain
.expect("ConfigureSwapchain")(std::mem::transmute(swapchain_config))
}
}
pub unsafe fn access_texture_by_id(
&self,
texture_id: unity_native_plugin::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<VulkanImage> {
let mut ret = std::mem::zeroed::<VulkanImage>();
if self
.interface()
.AccessTextureByID
.expect("AccessTextureByID")(
texture_id,
match sub_resource {
Some(t) => std::mem::transmute(t),
None => std::ptr::null(),
},
std::mem::transmute(layout),
std::mem::transmute(pipeline_stage_flags),
std::mem::transmute(access_flags),
access_mode as UnityVulkanResourceAccessMode,
std::mem::transmute(&mut ret),
) {
Some(ret)
} else {
None
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn size_test() {
assert_eq!(
::std::mem::size_of::<VulkanInstance>(),
::std::mem::size_of::<unity_native_plugin_sys::UnityVulkanInstance>()
);
assert_eq!(
::std::mem::size_of::<VulkanPluginEventConfig>(),
::std::mem::size_of::<unity_native_plugin_sys::UnityVulkanPluginEventConfig>()
);
assert_eq!(
::std::mem::size_of::<VulkanRecordingState>(),
::std::mem::size_of::<unity_native_plugin_sys::UnityVulkanRecordingState>()
);
assert_eq!(
::std::mem::size_of::<VulkanMemory>(),
::std::mem::size_of::<unity_native_plugin_sys::UnityVulkanMemory>()
);
assert_eq!(
::std::mem::size_of::<VulkanImage>(),
::std::mem::size_of::<unity_native_plugin_sys::UnityVulkanImage>()
);
assert_eq!(
::std::mem::size_of::<VulkanSwapchainConfiguration>(),
::std::mem::size_of::<unity_native_plugin_sys::UnityVulkanSwapchainConfiguration>()
);
}
}