文档列表见:Rust 移动端跨平台复杂图形渲染项目开发系列总结(目录)
CommandPool定义
/// Strong-typed command pool.
///
/// This a safer wrapper around `RawCommandPool` which ensures that only **one**
/// command buffer is recorded at the same time from the current queue.
/// Command buffers are stored internally and can only be obtained via a strong-typed
/// `CommandBuffer` wrapper for encoding.
pub struct CommandPool<B: Backend, C> {
buffers: Vec<B::CommandBuffer>,
secondary_buffers: Vec<B::CommandBuffer>,
raw: B::CommandPool,
next_buffer: usize,
next_secondary_buffer: usize,
_capability: PhantomData<C>,
}
复制代码
CommandPool与RawCommandPool的关系
实现抽象数据结构CommandPool
时需要满足RawCommandPool
约束,如下所示。
type CommandPool: pool::RawCommandPool<Self>;
复制代码
RawCommandPool定义
/// The allocated command buffers are associated with the creating command queue.
pub trait RawCommandPool<B: Backend>: Any + Send + Sync {
/// Reset the command pool and the corresponding command buffers.
///
/// # Synchronization: You may _not_ free the pool if a command buffer is still in use (pool memory still in use)
fn reset(&mut self);
/// Allocate new command buffers from the pool.
fn allocate(&mut self, num: usize, level: RawLevel) -> Vec<B::CommandBuffer>;
/// Free command buffers which are allocated from this pool.
unsafe fn free(&mut self, buffers: Vec<B::CommandBuffer>);
}
复制代码
CommandPool主要操作
初始化
let mut command_pool = device.create_command_pool_typed(
&queue_group,
pool::CommandPoolCreateFlags::empty(),
16 /* max_buffers */,
).expect("Can't create staging command pool");
复制代码
类似Adapter和Device,CommandPool也只需要一个,初始化HAL环境后创建一个实例通常是够用的。
create_command_pool_typed定义
/// Create a strongly typed command pool wrapper.
fn create_command_pool_typed<C>(
&self,
group: &QueueGroup<B, C>,
flags: CommandPoolCreateFlags,
max_buffers: usize,
) -> CommandPool<B, C> {
let raw = self.create_command_pool(group.family(), flags);
let mut pool = unsafe { CommandPool::new(raw) };
pool.reserve(max_buffers);
pool
}
复制代码
HAL中这些数据结构差不多都这个套路,将C接口从unsafe包装成Safe Rust,函数内部进行unsafe操作,收敛内存风险操作范围。
获取CommandBuffer
/// Get a primary command buffer for recording.
///
/// You can only record to one command buffer per pool at the same time.
/// If more command buffers are requested than allocated, new buffers will be reserved.
/// The command buffer will be returned in 'recording' state.
pub fn acquire_command_buffer<S: Shot>(
&mut self, allow_pending_resubmit: bool
) -> CommandBuffer<B, C, S> {
self.reserve(1);
let buffer = &mut self.buffers[self.next_buffer];
let mut flags = S::FLAGS;
if allow_pending_resubmit {
flags |= CommandBufferFlags::SIMULTANEOUS_USE;
}
buffer.begin(flags, CommandBufferInheritanceInfo::default());
self.next_buffer += 1;
unsafe {
CommandBuffer::new(buffer)
}
}
复制代码
重置
/// Reset the command pool and the corresponding command buffers.
///
/// # Synchronization: You may _not_ free the pool if a command buffer is still in use (pool memory still in use)
pub fn reset(&mut self) {
self.raw.reset();
self.next_buffer = 0;
self.next_secondary_buffer = 0;
}
复制代码
销毁CommandPool
device.destroy_command_pool(command_pool.into_raw());
复制代码