use crate::vk;
use crate::vk::command_buffer::pool::standard::StandardCommandPoolBuilder;
use crate::vk::command_buffer::{
AutoCommandBufferBuilderContextError, BeginRenderPassError, BlitImageError,
ClearColorImageError, CopyBufferError, CopyBufferImageError, DrawError, DrawIndexedError,
DynamicState, FillBufferError, UpdateBufferError,
};
use crate::vk::pipeline::input_assembly::Index;
use crate::window;
use crate::window::SwapchainImage;
use std::sync::{Arc, Mutex};
pub struct RawFrame {
command_buffer_builder: Mutex<Option<AutoCommandBufferBuilder>>,
window_id: window::Id,
nth: u64,
swapchain_image_index: usize,
swapchain_image: Arc<SwapchainImage>,
swapchain_frame_created: u64,
queue: Arc<vk::Queue>,
}
pub struct AddCommands<'a> {
frame: &'a RawFrame,
}
type AutoCommandBufferBuilder = vk::AutoCommandBufferBuilder<StandardCommandPoolBuilder>;
impl RawFrame {
pub(crate) fn new_empty(
queue: Arc<vk::Queue>,
window_id: window::Id,
nth: u64,
swapchain_image_index: usize,
swapchain_image: Arc<SwapchainImage>,
swapchain_frame_created: u64,
) -> Result<Self, vk::OomError> {
let device = queue.device().clone();
let cb_builder = AutoCommandBufferBuilder::primary_one_time_submit(device, queue.family())?;
let command_buffer_builder = Mutex::new(Some(cb_builder));
let frame = RawFrame {
command_buffer_builder,
window_id,
nth,
swapchain_image_index,
swapchain_image,
swapchain_frame_created,
queue,
};
Ok(frame)
}
pub(crate) fn finish(self) -> AutoCommandBufferBuilder {
self.command_buffer_builder
.lock()
.expect("failed to lock `command_buffer_builder`")
.take()
.expect("`command_buffer_builder` was `None`")
}
pub fn swapchain_image_is_new(&self) -> bool {
(self.nth - self.swapchain_image_index as u64) == self.swapchain_frame_created
}
pub fn add_commands(&self) -> AddCommands {
let frame = self;
AddCommands { frame }
}
pub fn window_id(&self) -> window::Id {
self.window_id
}
pub fn nth(&self) -> u64 {
self.nth
}
pub fn swapchain_image(&self) -> &Arc<SwapchainImage> {
&self.swapchain_image
}
pub fn swapchain_image_index(&self) -> usize {
self.swapchain_image_index
}
pub fn queue(&self) -> &Arc<vk::Queue> {
&self.queue
}
}
impl<'a> AddCommands<'a> {
fn map_cb<F, E>(self, map: F) -> Result<Self, E>
where
F: FnOnce(AutoCommandBufferBuilder) -> Result<AutoCommandBufferBuilder, E>,
{
{
let mut guard = self
.frame
.command_buffer_builder
.lock()
.expect("failed to lock `RawFrame`'s inner command buffer builder");
let mut builder = guard
.take()
.expect("the `RawFrame`'s inner command buffer should always be `Some`");
builder = map(builder)?;
*guard = Some(builder);
}
Ok(self)
}
pub fn begin_render_pass<F, C>(
self,
framebuffer: F,
secondary: bool,
clear_values: C,
) -> Result<Self, BeginRenderPassError>
where
F: vk::FramebufferAbstract
+ vk::RenderPassDescClearValues<C>
+ Clone
+ Send
+ Sync
+ 'static,
{
self.map_cb(move |cb| cb.begin_render_pass(framebuffer, secondary, clear_values))
}
pub fn next_subpass(
self,
secondary: bool,
) -> Result<Self, AutoCommandBufferBuilderContextError> {
self.map_cb(move |cb| cb.next_subpass(secondary))
}
pub fn end_render_pass(self) -> Result<Self, AutoCommandBufferBuilderContextError> {
self.map_cb(move |cb| cb.end_render_pass())
}
pub fn blit_image<S, D>(
self,
source: S,
source_top_left: [i32; 3],
source_bottom_right: [i32; 3],
source_base_array_layer: u32,
source_mip_level: u32,
destination: D,
destination_top_left: [i32; 3],
destination_bottom_right: [i32; 3],
destination_base_array_layer: u32,
destination_mip_level: u32,
layer_count: u32,
filter: vk::sampler::Filter,
) -> Result<Self, BlitImageError>
where
S: vk::ImageAccess + Send + Sync + 'static,
D: vk::ImageAccess + Send + Sync + 'static,
{
self.map_cb(move |cb| {
cb.blit_image(
source,
source_top_left,
source_bottom_right,
source_base_array_layer,
source_mip_level,
destination,
destination_top_left,
destination_bottom_right,
destination_base_array_layer,
destination_mip_level,
layer_count,
filter,
)
})
}
pub fn copy_image<S, D>(
self,
source: S,
source_offset: [i32; 3],
source_base_array_layer: u32,
source_mip_level: u32,
destination: D,
destination_offset: [i32; 3],
destination_base_array_layer: u32,
destination_mip_level: u32,
extent: [u32; 3],
layer_count: u32,
) -> Result<Self, ()>
where
S: vk::ImageAccess + Send + Sync + 'static,
D: vk::ImageAccess + Send + Sync + 'static,
{
self.map_cb(move |cb| {
cb.copy_image(
source,
source_offset,
source_base_array_layer,
source_mip_level,
destination,
destination_offset,
destination_base_array_layer,
destination_mip_level,
extent,
layer_count,
)
})
.map_err(|err| panic!("{}", err))
}
pub fn clear_color_image<I>(
self,
image: I,
color: vk::ClearValue,
) -> Result<Self, ClearColorImageError>
where
I: vk::ImageAccess + Send + Sync + 'static,
{
self.map_cb(move |cb| cb.clear_color_image(image, color))
}
pub fn clear_color_image_dimensions<I>(
self,
image: I,
first_layer: u32,
num_layers: u32,
first_mipmap: u32,
num_mipmaps: u32,
color: vk::ClearValue,
) -> Result<Self, ClearColorImageError>
where
I: vk::ImageAccess + Send + Sync + 'static,
{
self.map_cb(move |cb| {
cb.clear_color_image_dimensions(
image,
first_layer,
num_layers,
first_mipmap,
num_mipmaps,
color,
)
})
}
pub fn copy_buffer<S, D, T>(self, source: S, destination: D) -> Result<Self, CopyBufferError>
where
S: vk::TypedBufferAccess<Content = T> + Send + Sync + 'static,
D: vk::TypedBufferAccess<Content = T> + Send + Sync + 'static,
T: ?Sized,
{
self.map_cb(move |cb| cb.copy_buffer(source, destination))
}
pub fn copy_buffer_to_image<S, D, Px>(
self,
source: S,
destination: D,
) -> Result<Self, CopyBufferImageError>
where
S: vk::TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
D: vk::ImageAccess + Send + Sync + 'static,
vk::Format: vk::AcceptsPixels<Px>,
{
self.map_cb(move |cb| cb.copy_buffer_to_image(source, destination))
}
pub fn copy_buffer_to_image_dimensions<S, D, Px>(
self,
source: S,
destination: D,
offset: [u32; 3],
size: [u32; 3],
first_layer: u32,
num_layers: u32,
mipmap: u32,
) -> Result<Self, CopyBufferImageError>
where
S: vk::TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
D: vk::ImageAccess + Send + Sync + 'static,
vk::Format: vk::AcceptsPixels<Px>,
{
self.map_cb(move |cb| {
cb.copy_buffer_to_image_dimensions(
source,
destination,
offset,
size,
first_layer,
num_layers,
mipmap,
)
})
}
pub fn copy_image_to_buffer<S, D, Px>(
self,
source: S,
destination: D,
) -> Result<Self, CopyBufferImageError>
where
S: vk::ImageAccess + Send + Sync + 'static,
D: vk::TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
vk::Format: vk::AcceptsPixels<Px>,
{
self.map_cb(move |cb| cb.copy_image_to_buffer(source, destination))
}
pub fn copy_image_to_buffer_dimensions<S, D, Px>(
self,
source: S,
destination: D,
offset: [u32; 3],
size: [u32; 3],
first_layer: u32,
num_layers: u32,
mipmap: u32,
) -> Result<Self, CopyBufferImageError>
where
S: vk::ImageAccess + Send + Sync + 'static,
D: vk::TypedBufferAccess<Content = [Px]> + Send + Sync + 'static,
vk::Format: vk::AcceptsPixels<Px>,
{
self.map_cb(move |cb| {
cb.copy_image_to_buffer_dimensions(
source,
destination,
offset,
size,
first_layer,
num_layers,
mipmap,
)
})
}
pub fn draw<V, Gp, S, Pc>(
self,
pipeline: Gp,
dynamic: &DynamicState,
vertex_buffer: V,
sets: S,
constants: Pc,
) -> Result<Self, DrawError>
where
Gp: vk::GraphicsPipelineAbstract + vk::VertexSource<V> + Send + Sync + 'static + Clone,
S: vk::DescriptorSetsCollection,
{
self.map_cb(move |cb| cb.draw(pipeline, dynamic, vertex_buffer, sets, constants))
}
pub fn draw_indexed<V, Gp, S, Pc, Ib, I>(
self,
pipeline: Gp,
dynamic: &DynamicState,
vertex_buffer: V,
index_buffer: Ib,
sets: S,
constants: Pc,
) -> Result<Self, DrawIndexedError>
where
Gp: vk::GraphicsPipelineAbstract + vk::VertexSource<V> + Send + Sync + 'static + Clone,
S: vk::DescriptorSetsCollection,
Ib: vk::BufferAccess + vk::TypedBufferAccess<Content = [I]> + Send + Sync + 'static,
I: Index + 'static,
{
self.map_cb(move |cb| {
cb.draw_indexed(
pipeline,
dynamic,
vertex_buffer,
index_buffer,
sets,
constants,
)
})
}
pub fn fill_buffer<B>(self, buffer: B, data: u32) -> Result<Self, FillBufferError>
where
B: vk::BufferAccess + Send + Sync + 'static,
{
self.map_cb(move |cb| cb.fill_buffer(buffer, data))
}
pub fn update_buffer<B, D>(self, buffer: B, data: D) -> Result<Self, UpdateBufferError>
where
B: vk::TypedBufferAccess<Content = D> + Send + Sync + 'static,
D: Send + Sync + 'static,
{
self.map_cb(move |cb| cb.update_buffer(buffer, data))
}
}