unity_native_plugin_vulkan/
vulkan.rs1use ash::vk::Handle;
2use unity_native_plugin::define_unity_interface;
3use unity_native_plugin::interface::UnityInterface;
4use unity_native_plugin_sys::*;
5
6define_unity_interface!(
7 UnityGraphicsVulkan,
8 IUnityGraphicsVulkan,
9 0x95355348d4ef4e11_u64,
10 0x9789313dfcffcc87_u64
11);
12
13pub type VulkanInitCallback = Option<
14 unsafe extern "system" fn(
15 get_instance_proc_addr: ash::vk::PFN_vkGetInstanceProcAddr,
16 user_data: *mut ::std::os::raw::c_void,
17 ) -> ash::vk::PFN_vkGetInstanceProcAddr,
18>;
19
20pub struct VulkanInstance {
21 native: UnityVulkanInstance,
22}
23
24impl VulkanInstance {
25 pub fn pipeline_cache(&self) -> ash::vk::PipelineCache {
26 ash::vk::PipelineCache::from_raw(self.native.pipelineCache as u64)
27 }
28
29 pub fn instance(&self) -> ash::vk::Instance {
30 ash::vk::Instance::from_raw(self.native.instance as u64)
31 }
32
33 pub fn physical_device(&self) -> ash::vk::PhysicalDevice {
34 ash::vk::PhysicalDevice::from_raw(self.native.physicalDevice as u64)
35 }
36
37 pub fn device(&self) -> ash::vk::Device {
38 ash::vk::Device::from_raw(self.native.device as u64)
39 }
40
41 pub fn graphics_queue(&self) -> ash::vk::Queue {
42 ash::vk::Queue::from_raw(self.native.graphicsQueue as u64)
43 }
44
45 pub fn queue_family_index(&self) -> ::std::os::raw::c_uint {
46 self.native.queueFamilyIndex
47 }
48
49 pub unsafe fn get_instance_proc_addr(
50 &self,
51 name: *const std::os::raw::c_char,
52 ) -> PFN_vkVoidFunction {
53 if let Some(f) = self.native.getInstanceProcAddr {
54 unsafe {
55 (f)(self.native.instance, name)
56 }
57 } else {
58 PFN_vkVoidFunction::None
59 }
60 }
61}
62
63#[repr(u32)]
64#[derive(Copy, Clone, PartialEq, Eq, Debug)]
65pub enum VulkanEventRenderPassPreCondition {
66 DontCare = UnityVulkanEventRenderPassPreCondition_kUnityVulkanRenderPass_DontCare,
67 EnsureInside = UnityVulkanEventRenderPassPreCondition_kUnityVulkanRenderPass_EnsureInside,
68 EnsureOutside = UnityVulkanEventRenderPassPreCondition_kUnityVulkanRenderPass_EnsureOutside,
69}
70
71#[repr(u32)]
72#[derive(Copy, Clone, PartialEq, Eq, Debug)]
73pub enum VulkanGraphicsQueueAccess {
74 DontCare = UnityVulkanGraphicsQueueAccess_kUnityVulkanGraphicsQueueAccess_DontCare,
75 Allow = UnityVulkanGraphicsQueueAccess_kUnityVulkanGraphicsQueueAccess_Allow,
76}
77
78pub struct VulkanPluginEventConfig {
79 native: UnityVulkanPluginEventConfig,
80}
81
82impl VulkanPluginEventConfig {
83 pub fn render_pass_precondition(&self) -> VulkanEventRenderPassPreCondition {
84 unsafe { std::mem::transmute(self.native.renderPassPrecondition) }
85 }
86
87 pub fn graphics_queue_access(&self) -> VulkanGraphicsQueueAccess {
88 unsafe { std::mem::transmute(self.native.graphicsQueueAccess) }
89 }
90
91 pub fn flags(&self) -> u32 {
92 unsafe { std::mem::transmute(self.native.flags) }
93 }
94}
95
96pub struct VulkanRecordingState {
97 native: UnityVulkanRecordingState,
98}
99
100impl VulkanRecordingState {
101 pub fn command_buffer(&self) -> ash::vk::CommandBuffer {
102 ash::vk::CommandBuffer::from_raw(self.native.commandBuffer as u64)
103 }
104
105 pub fn command_buffer_level(&self) -> ash::vk::CommandBufferLevel {
106 unsafe { std::mem::transmute(self.native.commandBufferLevel) }
107 }
108
109 pub fn render_pass(&self) -> ash::vk::RenderPass {
110 ash::vk::RenderPass::from_raw(self.native.renderPass as u64)
111 }
112
113 pub fn framebuffer(&self) -> ash::vk::Framebuffer {
114 ash::vk::Framebuffer::from_raw(self.native.framebuffer as u64)
115 }
116
117 pub fn sub_pass_index(&self) -> ::std::os::raw::c_int {
118 self.native.subPassIndex
119 }
120
121 pub fn current_frame_number(&self) -> ::std::os::raw::c_ulonglong {
122 self.native.currentFrameNumber
123 }
124
125 pub fn safe_frame_number(&self) -> ::std::os::raw::c_ulonglong {
126 self.native.safeFrameNumber
127 }
128}
129
130pub struct VulkanMemory<'a> {
131 native: &'a UnityVulkanMemory,
132}
133
134impl VulkanMemory<'_> {
135 pub fn memory(&self) -> ash::vk::DeviceMemory {
136 ash::vk::DeviceMemory::from_raw(self.native.memory as u64)
137 }
138
139 pub fn offset(&self) -> ash::vk::DeviceSize {
140 self.native.offset
141 }
142
143 pub fn size(&self) -> ash::vk::DeviceSize {
144 self.native.size
145 }
146
147 pub fn mapped(&self) -> *mut ::std::os::raw::c_void {
148 self.native.mapped
149 }
150
151 pub fn flags(&self) -> ash::vk::MemoryPropertyFlags {
152 unsafe { std::mem::transmute(self.native.flags) }
153 }
154
155 pub fn memory_type_index(&self) -> ::std::os::raw::c_uint {
156 self.native.memoryTypeIndex
157 }
158}
159
160#[repr(u32)]
161#[derive(Copy, Clone, PartialEq, Eq, Debug)]
162pub enum VulkanResourceAccessMode {
163 ObserveOnly = UnityVulkanResourceAccessMode_kUnityVulkanResourceAccess_ObserveOnly,
164 PipelineBarrier = UnityVulkanResourceAccessMode_kUnityVulkanResourceAccess_PipelineBarrier,
165 Recreate = UnityVulkanResourceAccessMode_kUnityVulkanResourceAccess_Recreate,
166}
167
168pub struct VulkanImage {
169 native: UnityVulkanImage,
170}
171
172impl VulkanImage {
173 pub fn memory(&self) -> VulkanMemory {
174 VulkanMemory {
175 native: &self.native.memory,
176 }
177 }
178
179 pub fn image(&self) -> ash::vk::Image {
180 ash::vk::Image::from_raw(self.native.image as u64)
181 }
182
183 pub fn layout(&self) -> ash::vk::ImageLayout {
184 unsafe { ash::vk::ImageLayout::from_raw(std::mem::transmute(self.native.layout)) }
185 }
186
187 pub fn aspect(&self) -> ash::vk::ImageAspectFlags {
188 unsafe { std::mem::transmute(self.native.aspect) }
189 }
190
191 pub fn usage(&self) -> ash::vk::ImageUsageFlags {
192 unsafe { std::mem::transmute(self.native.usage) }
193 }
194
195 pub fn format(&self) -> ash::vk::Format {
196 unsafe { std::mem::transmute(self.native.format) }
197 }
198
199 pub fn extent(&self) -> ash::vk::Extent3D {
200 unsafe { std::mem::transmute(self.native.extent) }
201 }
202
203 pub fn tiling(&self) -> ash::vk::ImageTiling {
204 unsafe { std::mem::transmute(self.native.tiling) }
205 }
206
207 pub fn image_type(&self) -> ash::vk::ImageType {
208 unsafe { std::mem::transmute(self.native.type_) }
209 }
210
211 pub fn samples(&self) -> ash::vk::SampleCountFlags {
212 unsafe { std::mem::transmute(self.native.samples) }
213 }
214
215 pub fn layers(&self) -> ::std::os::raw::c_int {
216 self.native.layers
217 }
218
219 pub fn mip_count(&self) -> ::std::os::raw::c_int {
220 self.native.mipCount
221 }
222}
223
224#[repr(u32)]
225#[derive(Copy, Clone, PartialEq, Eq, Debug)]
226pub enum VulkanSwapchainMode {
227 Default = UnityVulkanSwapchainMode_kUnityVulkanSwapchainMode_Default,
228 Offscreen = UnityVulkanSwapchainMode_kUnityVulkanSwapchainMode_Offscreen,
229}
230
231#[repr(C)]
232pub struct VulkanSwapchainConfiguration {
233 pub mode: VulkanSwapchainMode,
234}
235
236macro_rules! impl_vulkan {
237 () => {
238 pub unsafe fn intercept_initialization(
239 &self,
240 func: VulkanInitCallback,
241 user_data: *mut ::std::os::raw::c_void,
242 ) {
243 unsafe {
244 self.interface()
245 .InterceptInitialization
246 .expect("InterceptInitialization")(std::mem::transmute(func), user_data);
247 }
248 }
249
250 pub unsafe fn intercept_vulkan_api(
251 &self,
252 name: *const ::std::os::raw::c_char,
253 func: ash::vk::PFN_vkVoidFunction,
254 ) -> ash::vk::PFN_vkVoidFunction {
255 unsafe {
256 std::mem::transmute(self
257 .interface()
258 .InterceptVulkanAPI
259 .expect("InterceptVulkanAPI")(
260 name, std::mem::transmute(func)
261 ))
262 }
263 }
264
265 pub fn configure_event(&self, event_id: i32, plugin_event_config: &VulkanPluginEventConfig) {
266 unsafe {
267 self.interface().ConfigureEvent.expect("ConfigureEvent")(
268 event_id,
269 &plugin_event_config.native,
270 )
271 }
272 }
273
274 pub fn instance(&self) -> VulkanInstance {
275 unsafe {
276 VulkanInstance {
277 native: self.interface().Instance.expect("Instance")(),
278 }
279 }
280 }
281
282 pub fn command_recording_state(
283 &self,
284 queue_access: VulkanGraphicsQueueAccess,
285 ) -> Option<VulkanRecordingState> {
286 unsafe {
287 let mut ret = std::mem::zeroed::<UnityVulkanRecordingState>();
288 if self
289 .interface()
290 .CommandRecordingState
291 .expect("CommandRecordingState")(
292 std::mem::transmute(&mut ret),
293 queue_access as UnityVulkanGraphicsQueueAccess,
294 ) {
295 Some(VulkanRecordingState { native: ret })
296 } else {
297 None
298 }
299 }
300 }
301
302 pub unsafe fn access_texture(
303 &self,
304 native_texture: *mut ::std::os::raw::c_void,
305 sub_resource: Option<&ash::vk::ImageSubresource>,
306 layout: ash::vk::ImageLayout,
307 pipeline_stage_flags: ash::vk::PipelineStageFlags,
308 access_flags: ash::vk::AccessFlags,
309 access_mode: VulkanResourceAccessMode,
310 ) -> Option<VulkanImage> {
311 unsafe {
312 let mut ret = std::mem::zeroed::<UnityVulkanImage>();
313 if self.interface().AccessTexture.expect("AccessTexture")(
314 native_texture,
315 match sub_resource {
316 Some(t) => std::mem::transmute(t),
317 None => std::ptr::null(),
318 },
319 std::mem::transmute(layout),
320 std::mem::transmute(pipeline_stage_flags),
321 std::mem::transmute(access_flags),
322 access_mode as UnityVulkanResourceAccessMode,
323 std::mem::transmute(&mut ret),
324 ) {
325 Some(VulkanImage { native: ret })
326 } else {
327 None
328 }
329 }
330 }
331
332 pub unsafe fn access_render_buffer_texture(
333 &self,
334 native_render_buffer: unity_native_plugin::graphics::RenderBuffer,
335 sub_resource: Option<&ash::vk::ImageSubresource>,
336 layout: ash::vk::ImageLayout,
337 pipeline_stage_flags: ash::vk::PipelineStageFlags,
338 access_flags: ash::vk::AccessFlags,
339 access_mode: VulkanResourceAccessMode,
340 ) -> Option<VulkanImage> {
341 unsafe {
342 let mut ret = std::mem::zeroed::<UnityVulkanImage>();
343 if self
344 .interface()
345 .AccessRenderBufferTexture
346 .expect("AccessRenderBufferTexture")(
347 native_render_buffer,
348 match sub_resource {
349 Some(t) => std::mem::transmute(t),
350 None => std::ptr::null(),
351 },
352 std::mem::transmute(layout),
353 std::mem::transmute(pipeline_stage_flags),
354 std::mem::transmute(access_flags),
355 access_mode as UnityVulkanResourceAccessMode,
356 std::mem::transmute(&mut ret),
357 ) {
358 Some(VulkanImage { native: ret })
359 } else {
360 None
361 }
362 }
363 }
364
365 pub unsafe fn access_render_buffer_resolve_texture(
366 &self,
367 native_render_buffer: unity_native_plugin::graphics::RenderBuffer,
368 sub_resource: Option<&ash::vk::ImageSubresource>,
369 layout: ash::vk::ImageLayout,
370 pipeline_stage_flags: ash::vk::PipelineStageFlags,
371 access_flags: ash::vk::AccessFlags,
372 access_mode: VulkanResourceAccessMode,
373 ) -> Option<VulkanImage> {
374 unsafe {
375 let mut ret = std::mem::zeroed::<UnityVulkanImage>();
376 if self
377 .interface()
378 .AccessRenderBufferResolveTexture
379 .expect("AccessRenderBufferResolveTexture")(
380 native_render_buffer,
381 match sub_resource {
382 Some(t) => std::mem::transmute(t),
383 None => std::ptr::null(),
384 },
385 std::mem::transmute(layout),
386 std::mem::transmute(pipeline_stage_flags),
387 std::mem::transmute(access_flags),
388 access_mode as UnityVulkanResourceAccessMode,
389 std::mem::transmute(&mut ret),
390 ) {
391 Some(VulkanImage { native: ret })
392 } else {
393 None
394 }
395 }
396 }
397
398 pub unsafe fn access_buffer(
399 &self,
400 native_buffer: *mut ::std::os::raw::c_void,
401 pipeline_stage_flags: ash::vk::PipelineStageFlags,
402 access_flags: ash::vk::AccessFlags,
403 access_mode: VulkanResourceAccessMode,
404 ) -> Option<VulkanImage> {
405 unsafe {
406 let mut ret = std::mem::zeroed::<UnityVulkanImage>();
407 if self.interface().AccessBuffer.expect("AccessTexture")(
408 native_buffer,
409 std::mem::transmute(pipeline_stage_flags),
410 std::mem::transmute(access_flags),
411 access_mode as UnityVulkanResourceAccessMode,
412 std::mem::transmute(&mut ret),
413 ) {
414 Some(VulkanImage { native: ret })
415 } else {
416 None
417 }
418 }
419 }
420
421 pub fn ensure_outside_render_pass(&self) {
422 unsafe {
423 self.interface()
424 .EnsureOutsideRenderPass
425 .expect("EnsureOutsideRenderPass")()
426 }
427 }
428
429 pub fn ensure_inside_render_pass(&self) {
430 unsafe {
431 self.interface()
432 .EnsureInsideRenderPass
433 .expect("EnsureInsideRenderPass")()
434 }
435 }
436
437 pub unsafe fn access_queue(
438 &self,
439 callback: UnityRenderingEventAndData,
440 event_id: ::std::os::raw::c_int,
441 user_data: *mut ::std::os::raw::c_void,
442 flush: bool,
443 ) {
444 unsafe {
445 self.interface().AccessQueue.expect("AccessQueue")(callback, event_id, user_data, flush);
446 }
447 }
448
449 pub fn configure_swapchain(&self, swapchain_config: &VulkanSwapchainConfiguration) -> bool {
450 unsafe {
451 self.interface()
452 .ConfigureSwapchain
453 .expect("ConfigureSwapchain")(std::mem::transmute(swapchain_config))
454 }
455 }
456
457 pub unsafe fn access_texture_by_id(
458 &self,
459 texture_id: unity_native_plugin::graphics::TextureID,
460 sub_resource: Option<&ash::vk::ImageSubresource>,
461 layout: ash::vk::ImageLayout,
462 pipeline_stage_flags: ash::vk::PipelineStageFlags,
463 access_flags: ash::vk::AccessFlags,
464 access_mode: VulkanResourceAccessMode,
465 ) -> Option<VulkanImage> {
466 unsafe {
467 let mut ret = std::mem::zeroed::<UnityVulkanImage>();
468 if self
469 .interface()
470 .AccessTextureByID
471 .expect("AccessTextureByID")(
472 texture_id,
473 match sub_resource {
474 Some(t) => std::mem::transmute(t),
475 None => std::ptr::null(),
476 },
477 std::mem::transmute(layout),
478 std::mem::transmute(pipeline_stage_flags),
479 std::mem::transmute(access_flags),
480 access_mode as UnityVulkanResourceAccessMode,
481 std::mem::transmute(&mut ret),
482 ) {
483 Some(VulkanImage { native: ret })
484 } else {
485 None
486 }
487 }
488 }
489 }
490}
491
492impl UnityGraphicsVulkan {
493 impl_vulkan!();
494}
495
496
497define_unity_interface!(
498 UnityGraphicsVulkanV2,
499 IUnityGraphicsVulkanV2,
500 0xEC39D2F18446C745_u64,
501 0xB1A2626641D6B11F_u64
502);
503
504macro_rules! impl_vulkan_v2 {
505 () => {
506 impl_vulkan!();
507
508 pub unsafe fn add_intercept_initialization(
509 &self,
510 func: VulkanInitCallback,
511 user_data: *mut ::std::os::raw::c_void,
512 priority: i32) -> bool {
513 unsafe {
514 self.interface().AddInterceptInitialization.expect("AddInterceptInitialization")(std::mem::transmute(func), user_data, priority)
515 }
516 }
517
518 pub unsafe fn remove_intercept_initialization(
519 &self,
520 func: VulkanInitCallback) -> bool {
521 unsafe {
522 self.interface().RemoveInterceptInitialization.expect("RemoveInterceptInitialization")(std::mem::transmute(func))
523 }
524 }
525 }
526}
527
528impl UnityGraphicsVulkanV2 {
529 impl_vulkan_v2!();
530}
531
532
533#[cfg(test)]
534mod test {
535 use super::*;
536
537 #[test]
538 fn size_test() {
539 assert_eq!(
540 ::std::mem::size_of::<VulkanSwapchainConfiguration>(),
541 ::std::mem::size_of::<unity_native_plugin_sys::UnityVulkanSwapchainConfiguration>()
542 );
543 }
544}