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