Check depth and stencil presence when creating a pipeline

This commit is contained in:
Pierre Krieger 2016-04-22 15:49:32 +02:00
parent 5982778cd2
commit 32076a1e0c
3 changed files with 175 additions and 0 deletions

View File

@ -129,6 +129,42 @@ unsafe impl RenderPassDesc for EmptySinglePassRenderPass {
None
}
}
#[inline]
fn has_depth(&self, subpass: u32) -> Option<bool> {
if subpass == 0 {
Some(false)
} else {
None
}
}
#[inline]
fn has_writable_depth(&self, subpass: u32) -> Option<bool> {
if subpass == 0 {
Some(false)
} else {
None
}
}
#[inline]
fn has_stencil(&self, subpass: u32) -> Option<bool> {
if subpass == 0 {
Some(false)
} else {
None
}
}
#[inline]
fn has_writable_stencil(&self, subpass: u32) -> Option<bool> {
if subpass == 0 {
Some(false)
} else {
None
}
}
}
unsafe impl RenderPassAttachmentsList<()> for EmptySinglePassRenderPass {

View File

@ -95,6 +95,86 @@ pub unsafe trait RenderPassDesc {
}
})
}
/// Returns true if a subpass has a depth attachment or a depth-stencil attachment.
#[inline]
fn has_depth(&self, subpass: u32) -> Option<bool> {
self.passes().skip(subpass as usize).next().map(|p| {
let atch_num = match p.depth_stencil {
Some((d, _)) => d,
None => return false
};
match self.attachments().skip(atch_num).next().unwrap().format.ty() {
FormatTy::Depth => true,
FormatTy::Stencil => false,
FormatTy::DepthStencil => true,
_ => unreachable!()
}
})
}
/// Returns true if a subpass has a depth attachment or a depth-stencil attachment whose
/// layout is not `DepthStencilReadOnlyOptimal`.
#[inline]
fn has_writable_depth(&self, subpass: u32) -> Option<bool> {
self.passes().skip(subpass as usize).next().map(|p| {
let atch_num = match p.depth_stencil {
Some((d, l)) => {
if l == ImageLayout::DepthStencilReadOnlyOptimal { return false; }
d
},
None => return false
};
match self.attachments().skip(atch_num).next().unwrap().format.ty() {
FormatTy::Depth => true,
FormatTy::Stencil => false,
FormatTy::DepthStencil => true,
_ => unreachable!()
}
})
}
/// Returns true if a subpass has a stencil attachment or a depth-stencil attachment.
#[inline]
fn has_stencil(&self, subpass: u32) -> Option<bool> {
self.passes().skip(subpass as usize).next().map(|p| {
let atch_num = match p.depth_stencil {
Some((d, _)) => d,
None => return false
};
match self.attachments().skip(atch_num).next().unwrap().format.ty() {
FormatTy::Depth => false,
FormatTy::Stencil => true,
FormatTy::DepthStencil => true,
_ => unreachable!()
}
})
}
/// Returns true if a subpass has a stencil attachment or a depth-stencil attachment whose
/// layout is not `DepthStencilReadOnlyOptimal`.
#[inline]
fn has_writable_stencil(&self, subpass: u32) -> Option<bool> {
self.passes().skip(subpass as usize).next().map(|p| {
let atch_num = match p.depth_stencil {
Some((d, l)) => {
if l == ImageLayout::DepthStencilReadOnlyOptimal { return false; }
d
},
None => return false
};
match self.attachments().skip(atch_num).next().unwrap().format.ty() {
FormatTy::Depth => false,
FormatTy::Stencil => true,
FormatTy::DepthStencil => true,
_ => unreachable!()
}
})
}
}
/// Extension trait for `RenderPass`. Defines which types are allowed as an attachments list.
@ -346,6 +426,32 @@ impl<'a, L: 'a> Subpass<'a, L> where L: RenderPass + RenderPassDesc {
self.render_pass.num_color_attachments(self.subpass_id).unwrap()
}
/// Returns true if the subpass has a depth attachment or a depth-stencil attachment.
#[inline]
pub fn has_depth(&self) -> bool {
self.render_pass.has_depth(self.subpass_id).unwrap()
}
/// Returns true if the subpass has a depth attachment or a depth-stencil attachment whose
/// layout is not `DepthStencilReadOnlyOptimal`.
#[inline]
pub fn has_writable_depth(&self) -> bool {
self.render_pass.has_writable_depth(self.subpass_id).unwrap()
}
/// Returns true if the subpass has a stencil attachment or a depth-stencil attachment.
#[inline]
pub fn has_stencil(&self) -> bool {
self.render_pass.has_stencil(self.subpass_id).unwrap()
}
/// Returns true if the subpass has a stencil attachment or a depth-stencil attachment whose
/// layout is not `DepthStencilReadOnlyOptimal`.
#[inline]
pub fn has_writable_stencil(&self) -> bool {
self.render_pass.has_writable_stencil(self.subpass_id).unwrap()
}
/// Returns true if the subpass has any color or depth/stencil attachment.
#[inline]
pub fn has_color_or_depth_stencil_attachment(&self) -> bool {

View File

@ -469,6 +469,25 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
_ => return Err(GraphicsPipelineCreationError::WrongStencilState)
};
if params.depth_stencil.depth_write && !params.render_pass.has_writable_depth() {
return Err(GraphicsPipelineCreationError::NoDepthAttachment);
}
if params.depth_stencil.depth_compare != Compare::Always &&
!params.render_pass.has_depth()
{
return Err(GraphicsPipelineCreationError::NoDepthAttachment);
}
if (!params.depth_stencil.stencil_front.always_keep() ||
!params.depth_stencil.stencil_back.always_keep()) &&
!params.render_pass.has_stencil()
{
return Err(GraphicsPipelineCreationError::NoStencilAttachment);
}
// FIXME: stencil writability
vk::PipelineDepthStencilStateCreateInfo {
sType: vk::STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
pNext: ptr::null(),
@ -828,6 +847,14 @@ pub enum GraphicsPipelineCreationError {
/// The `logic_op` feature must be enabled in order to use logic operations.
LogicOpFeatureNotEnabled,
/// The depth test requires a depth attachment but render pass has no depth attachment, or
/// depth writing is enabled and the depth attachment is read-only.
NoDepthAttachment,
/// The stencil test requires a stencil attachment but render pass has no stencil attachment, or
/// stencil writing is enabled and the stencil attachment is read-only.
NoStencilAttachment,
}
impl error::Error for GraphicsPipelineCreationError {
@ -911,6 +938,12 @@ impl error::Error for GraphicsPipelineCreationError {
GraphicsPipelineCreationError::LogicOpFeatureNotEnabled => {
"the `logic_op` feature must be enabled in order to use logic operations"
},
GraphicsPipelineCreationError::NoDepthAttachment => {
"the depth attachment of the render pass does not match the depth test"
},
GraphicsPipelineCreationError::NoStencilAttachment => {
"the stencil attachment of the render pass does not match the stencil test"
},
}
}