1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
use crate::*;
use std::ffi::c_void;
use ae_sys:: { A_u_long, PF_EffectWorld, PF_InData, PF_ProgPtr };
define_suite!(
GPUDeviceSuite,
PF_GPUDeviceSuite1,
kPFGPUDeviceSuite,
kPFGPUDeviceSuiteVersion1
);
impl GPUDeviceSuite {
/// Acquire this suite from the host. Returns error if the suite is not available.
/// Suite is released on drop.
pub fn new() -> Result<Self, Error> {
crate::Suite::new()
}
/// This will return the number of gpu devices the host supports.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
///
/// Returns the number of available devices.
pub fn device_count(&self, effect_ref: impl AsPtr<PF_ProgPtr>) -> Result<usize, Error> {
Ok(call_suite_fn_single!(self, GetDeviceCount -> A_u_long, effect_ref.as_ptr())? as usize)
}
/// This will return the device info with given device index, which includes necessary context/queue information
/// needed to dispatch task to the device. Refer PF_GPUDeviceInfo for details.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `device_index` - The device index for the requested device.
///
/// Returns the device info will to be filled.
pub fn device_info(&self, effect_ref: impl AsPtr<PF_ProgPtr>, device_index: usize) -> Result<ae_sys::PF_GPUDeviceInfo, Error> {
call_suite_fn_single!(self, GetDeviceInfo -> ae_sys::PF_GPUDeviceInfo, effect_ref.as_ptr(), device_index as _)
}
/// Acquire/release exclusive access to `device_index`. All calls below this point generally require access be held.
/// For full GPU plugins (those that use a separate entry point for GPU rendering) exclusive access is always held.
/// These calls do not need to be made in that case.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `device_index` - The device index for the requested device.
pub fn acquire_exclusive_device_access(&self, effect_ref: impl AsPtr<PF_ProgPtr>, device_index: usize) -> Result<(), Error> {
call_suite_fn!(self, AcquireExclusiveDeviceAccess, effect_ref.as_ptr(), device_index as _)
}
/// Acquire/release exclusive access to `device_index`. All calls below this point generally require access be held.
/// For full GPU plugins (those that use a separate entry point for GPU rendering) exclusive access is always held.
/// These calls do not need to be made in that case.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `device_index` - The device index for the requested device.
pub fn release_exclusive_device_access(&self, effect_ref: impl AsPtr<PF_ProgPtr>, device_index: usize) -> Result<(), Error> {
call_suite_fn!(self, ReleaseExclusiveDeviceAccess, effect_ref.as_ptr(), device_index as _)
}
/// All device memory must be allocated through this suite.
/// Purge should be called only in emergency situations when working with GPU memory that cannot be allocated through this suite (eg OpenGL memory).
/// Returned pointer value represents memory allocated through cuMemAlloc or clCreateBuffer.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `device_index` - The device index for the requested device.
/// * `size_bytes` - The size of the memory to allocate.
///
/// Returns the pointer to the allocated memory.
pub fn allocate_device_memory(&self, effect_ref: impl AsPtr<PF_ProgPtr>, device_index: usize, size_bytes: usize) -> Result<*mut c_void, Error> {
call_suite_fn_single!(self, AllocateDeviceMemory -> *mut c_void, effect_ref.as_ptr(), device_index as _, size_bytes)
}
/// Free the device memory.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `device_index` - The device index for the requested device.
/// * `memory` - The pointer to the memory to free.
pub fn free_device_memory(&self, effect_ref: impl AsPtr<PF_ProgPtr>, device_index: usize, memory: *mut c_void) -> Result<(), Error> {
call_suite_fn!(self, FreeDeviceMemory, effect_ref.as_ptr(), device_index as _, memory)
}
/// Purge the device memory.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `device_index` - The device index for the requested device.
/// * `size_bytes` - The size of the memory to purge.
///
/// Returns the number of bytes purged.
pub fn purge_device_memory(&self, effect_ref: impl AsPtr<PF_ProgPtr>, device_index: usize, size_bytes: usize) -> Result<usize, Error> {
Ok(call_suite_fn_single!(self, PurgeDeviceMemory -> usize, effect_ref.as_ptr(), device_index as _, size_bytes)?)
}
/// All host (pinned) memory must be allocated through this suite.
/// Purge should be called only in emergency situations when working with GPU memory that cannot be allocated through this suite (eg OpenGL memory).
/// Returned pointer value represents memory allocated through cuMemHostAlloc or malloc.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `device_index` - The device index for the requested device.
/// * `size_bytes` - The size of the memory to allocate.
///
/// Returns the pointer to the allocated memory.
pub fn allocate_host_memory(&self, effect_ref: impl AsPtr<PF_ProgPtr>, device_index: usize, size_bytes: usize) -> Result<*mut c_void, Error> {
call_suite_fn_single!(self, AllocateHostMemory -> *mut c_void, effect_ref.as_ptr(), device_index as _, size_bytes)
}
/// Free the host memory.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `device_index` - The device index for the requested device.
/// * `memory` - The pointer to the memory to free.
pub fn free_host_memory(&self, effect_ref: impl AsPtr<PF_ProgPtr>, device_index: usize, memory: *mut c_void) -> Result<(), Error> {
call_suite_fn!(self, FreeHostMemory, effect_ref.as_ptr(), device_index as _, memory)
}
/// Purge the host memory.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `device_index` - The device index for the requested device.
/// * `bytes_to_purge` - The size of the memory to purge.
///
/// Returns the number of bytes purged.
pub fn purge_host_memory(&self, effect_ref: impl AsPtr<PF_ProgPtr>, device_index: usize, bytes_to_purge: usize) -> Result<usize, Error> {
Ok(call_suite_fn_single!(self, PurgeHostMemory -> usize, effect_ref.as_ptr(), device_index as _, bytes_to_purge)?)
}
/// This will allocate a gpu effect world. Caller is responsible for deallocating the buffer with [`dispose_gpu_world()`](Self::dispose_gpu_world).
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `device_index` - The device you want your gpu effect world allocated with.
/// * `width` - Width of the effect world.
/// * `height` - Height of the effect world.
/// * `pixel_aspect_ratio` - Pixel Aspect Ratio of the effect world.
/// * `field_type` - The field of the effect world.
/// * `pixel_format` - The pixel format of the effect world, only gpu formats are accepted.
/// * `clear_pix` - Pass in 'true' for a transparent black frame.
///
/// Returns the handle to the effect world to be created.
pub fn create_gpu_world(&self, in_data: impl AsPtr<*const PF_InData>, device_index: usize, width: i32, height: i32, pixel_aspect_ratio: RationalScale, field_type: Field, pixel_format: pf::PixelFormat, clear_pix: bool) -> Result<Layer, Error> {
let layer = call_suite_fn_single!(self, CreateGPUWorld -> *mut PF_EffectWorld, (*in_data.as_ptr()).effect_ref, device_index as _, width, height, pixel_aspect_ratio.into(), field_type.into(), pixel_format.into(), clear_pix as _)?;
Ok(Layer::from_raw(layer, in_data, Some(|self_layer| {
GPUDeviceSuite::new().unwrap().dispose_gpu_world(unsafe { (*self_layer.in_data_ptr).effect_ref }, self_layer.as_mut_ptr()).unwrap();
})))
}
/// This will free this effect world. The effect world is no longer valid after this function is called.
/// Plugin module is only allowed to dispose of gpu effect worlds they create.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `world` - The effect world you want to dispose.
pub fn dispose_gpu_world(&self, effect_ref: impl AsPtr<PF_ProgPtr>, world: *mut ae_sys::PF_EffectWorld) -> Result<(), Error> {
call_suite_fn!(self, DisposeGPUWorld, effect_ref.as_ptr(), world)
}
/// This will return the gpu buffer address of the given effect world.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `world` - The effect world you want to operate on, has to be a gpu effect world.
///
/// Returns the gpu buffer address.
pub fn gpu_world_data(&self, effect_ref: impl AsPtr<PF_ProgPtr>, mut world: impl AsMutPtr<*mut ae_sys::PF_EffectWorld>) -> Result<*mut std::ffi::c_void, Error> {
call_suite_fn_single!(self, GetGPUWorldData -> *mut c_void, effect_ref.as_ptr(), world.as_mut_ptr())
}
/// This will return the size of the total data in the effect world.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `world` - The effect world you want to operate on, has to be a gpu effect world.
///
/// Returns the size of the total data in the effect world.
pub fn gpu_world_size(&self, effect_ref: impl AsPtr<PF_ProgPtr>, world: impl AsPtr<*mut ae_sys::PF_EffectWorld>) -> Result<usize, Error> {
Ok(call_suite_fn_single!(self, GetGPUWorldSize -> usize, effect_ref.as_ptr(), world.as_ptr())?)
}
/// This will return device index the gpu effect world is associated with.
/// * `effect_ref` - Effect reference from [`InData`](crate::InData::effect_ref).
/// * `world` - The effect world you want to operate on, has to be a gpu effect world.
///
/// Returns the device index of the given effect world.
pub fn gpu_world_device_index(&self, effect_ref: impl AsPtr<PF_ProgPtr>, world: impl AsPtr<*mut ae_sys::PF_EffectWorld>) -> Result<usize, Error> {
Ok(call_suite_fn_single!(self, GetGPUWorldDeviceIndex -> A_u_long, effect_ref.as_ptr(), world.as_ptr())? as usize)
}
}