use std::sync::Arc;
use std::marker::PhantomData;
use smallvec::SmallVec;
use ::{VdResult, Device, PipelineLayoutHandle, PipelineHandle, RenderPassHandle,
Handle, GraphicsPipelineCreateInfo};
#[derive(Debug)]
struct Inner {
handle: PipelineHandle,
device: Device,
}
impl Drop for Inner {
fn drop(&mut self) {
unsafe {
self.device.destroy_pipeline(self.handle, None);
}
}
}
#[derive(Debug, Clone)]
pub struct GraphicsPipeline {
inner: Arc<Inner>,
}
impl GraphicsPipeline {
pub fn builder<'b>() -> GraphicsPipelineBuilder<'b> {
GraphicsPipelineBuilder::new()
}
#[deprecated(note = "use `Device::create_graphics_pipelines`")]
pub fn create<'b, Gpb>(device: &Device, builders: &[Gpb])
-> VdResult<SmallVec<[GraphicsPipeline; 8]>>
where Gpb: AsRef<::GraphicsPipelineCreateInfo<'b>> {
let mut create_infos = SmallVec::<[GraphicsPipelineCreateInfo; 8]>::new();
let mut pipelines = SmallVec::<[GraphicsPipeline; 8]>::new();
create_infos.reserve_exact(builders.len());
pipelines.reserve_exact(builders.len());
for builder in builders {
create_infos.push(builder.as_ref().clone());
}
let pipeline_handles = unsafe { device.create_graphics_pipelines(None, &create_infos, None)? };
for handle in pipeline_handles {
pipelines.push(
GraphicsPipeline {
inner: Arc::new(Inner {
handle,
device: device.clone(),
})
}
);
}
Ok(pipelines)
}
pub fn handle(&self) -> PipelineHandle {
self.inner.handle
}
pub fn device(&self) -> &Device {
&self.inner.device
}
}
unsafe impl<'g> Handle for &'g GraphicsPipeline {
type Target = PipelineHandle;
fn handle(&self) -> Self::Target {
self.inner.handle
}
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct GraphicsPipelineBuilder<'b> {
create_info: GraphicsPipelineCreateInfo<'b>,
_p: PhantomData<&'b ()>,
}
impl<'b> GraphicsPipelineBuilder<'b> {
pub fn new() -> GraphicsPipelineBuilder<'b> {
GraphicsPipelineBuilder {
create_info: GraphicsPipelineCreateInfo::default(),
_p: PhantomData,
}
}
pub fn flags<'s>(&'s mut self, flags: ::PipelineCreateFlags)
-> &'s mut GraphicsPipelineBuilder<'b> {
self.create_info.set_flags(flags);
self
}
pub fn stages<'s, 'p>(&'s mut self,
stages: &'p [::PipelineShaderStageCreateInfo])
-> &'s mut GraphicsPipelineBuilder<'b>
where 'p: 'b {
self.create_info.set_stages(stages);
self
}
pub fn vertex_input_state<'s, 'p>(&'s mut self,
vertex_input_state: &'p ::PipelineVertexInputStateCreateInfo)
-> &'s mut GraphicsPipelineBuilder<'b>
where 'p: 'b {
self.create_info.set_vertex_input_state(vertex_input_state);
self
}
pub fn input_assembly_state<'s, 'p>(&'s mut self, input_assembly_state:
&'p ::PipelineInputAssemblyStateCreateInfo)
-> &'s mut GraphicsPipelineBuilder<'b>
where 'p: 'b {
self.create_info.set_input_assembly_state(input_assembly_state);
self
}
pub fn tessellation_state<'s, 'p>(&'s mut self,
tessellation_state: &'p ::PipelineTessellationStateCreateInfo)
-> &'s mut GraphicsPipelineBuilder<'b>
where 'p: 'b {
self.create_info.set_tessellation_state(tessellation_state);
self
}
pub fn viewport_state<'s, 'p>(&'s mut self,
viewport_state: &'p ::PipelineViewportStateCreateInfo)
-> &'s mut GraphicsPipelineBuilder<'b>
where 'p: 'b {
self.create_info.set_viewport_state(viewport_state);
self
}
pub fn rasterization_state<'s, 'p>(&'s mut self,
rasterization_state: &'p ::PipelineRasterizationStateCreateInfo)
-> &'s mut GraphicsPipelineBuilder<'b>
where 'p: 'b {
self.create_info.set_rasterization_state(rasterization_state);
self
}
pub fn multisample_state<'s, 'p>(&'s mut self,
multisample_state: &'p ::PipelineMultisampleStateCreateInfo)
-> &'s mut GraphicsPipelineBuilder<'b>
where 'p: 'b {
self.create_info.set_multisample_state(multisample_state);
self
}
pub fn depth_stencil_state<'s, 'p>(&'s mut self,
depth_stencil_state: &'p ::PipelineDepthStencilStateCreateInfo)
-> &'s mut GraphicsPipelineBuilder<'b>
where 'p: 'b {
self.create_info.set_depth_stencil_state(depth_stencil_state);
self
}
pub fn color_blend_state<'s, 'p>(&'s mut self,
color_blend_state: &'p ::PipelineColorBlendStateCreateInfo)
-> &'s mut GraphicsPipelineBuilder<'b>
where 'p: 'b {
self.create_info.set_color_blend_state(color_blend_state);
self
}
pub fn dynamic_state<'s, 'p>(&'s mut self,
dynamic_state: &'p ::PipelineDynamicStateCreateInfo)
-> &'s mut GraphicsPipelineBuilder<'b>
where 'p: 'b {
self.create_info.set_dynamic_state(dynamic_state);
self
}
pub fn layout<'s, H>(&'s mut self, layout: H) -> &'s mut GraphicsPipelineBuilder<'b>
where H: Handle<Target=PipelineLayoutHandle> {
self.create_info.set_layout(layout);
self
}
pub fn render_pass<'s, H>(&'s mut self, render_pass: H)
-> &'s mut GraphicsPipelineBuilder<'b>
where H: Handle<Target=RenderPassHandle> {
self.create_info.set_render_pass(render_pass);
self
}
pub fn subpass<'s>(&'s mut self, subpass: u32)
-> &'s mut GraphicsPipelineBuilder<'b> {
self.create_info.set_subpass(subpass);
self
}
pub fn base_pipeline<'s, H>(&'s mut self, base_pipeline: H)
-> &'s mut GraphicsPipelineBuilder<'b>
where H: Handle<Target=PipelineHandle> {
self.create_info.set_base_pipeline_handle(base_pipeline);
self
}
pub fn base_pipeline_index<'s>(&'s mut self, base_pipeline_index: i32)
-> &'s mut GraphicsPipelineBuilder<'b> {
self.create_info.set_base_pipeline_index(base_pipeline_index);
self
}
pub fn build(&self, device: Device) -> VdResult<GraphicsPipeline> {
let handle = unsafe {
let create_infos = ::std::slice::from_raw_parts(&self.create_info, 1);
*device.create_graphics_pipelines(None, create_infos, None)?.get_unchecked(0)
};
Ok(GraphicsPipeline {
inner: Arc::new(Inner {
handle,
device,
})
})
}
}
impl<'b> AsRef<GraphicsPipelineBuilder<'b>> for GraphicsPipelineBuilder<'b> {
fn as_ref(&self) -> &GraphicsPipelineBuilder<'b> {
self
}
}
impl<'b> AsRef<::GraphicsPipelineCreateInfo<'b>> for GraphicsPipelineBuilder<'b> {
fn as_ref(&self) -> &::GraphicsPipelineCreateInfo<'b> {
&self.create_info
}
}