mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-23 15:24:25 +00:00
Implement ContextCheckLayer
This commit is contained in:
parent
a1b65b3845
commit
097682bf9d
@ -51,7 +51,7 @@ impl AutoCommandBufferBuilder<Arc<StandardCommandPool>> {
|
||||
let c = cb::AutoPipelineBarriersLayer::new(c);
|
||||
let c = cb::SubmitSyncBuilderLayer::new(c);
|
||||
let c = cb::StateCacheLayer::new(c);
|
||||
let c = cb::ContextCheckLayer::new(c);
|
||||
let c = cb::ContextCheckLayer::new(c, false, true);
|
||||
let c = cb::QueueTyCheckLayer::new(c, supports_graphics, supports_compute);
|
||||
let c = cb::DeviceCheckLayer::new(c);
|
||||
c
|
||||
|
@ -16,20 +16,45 @@ use device::Device;
|
||||
use device::DeviceOwned;
|
||||
|
||||
/// Layer around a command buffer builder that checks whether the commands can be executed in the
|
||||
/// given context.
|
||||
/// given context related to render passes.
|
||||
///
|
||||
/// What is checked exactly:
|
||||
///
|
||||
/// - When adding a command that can only be executed within a render pass or outside of a render
|
||||
/// pass, checks that we are within or outside of a render pass.
|
||||
/// - When leaving the render pass or going to the next subpass, makes sure that the number of
|
||||
/// subpasses of the current render pass is respected.
|
||||
/// - When binding a graphics pipeline or drawing, makes sure that the pipeline is valid for the
|
||||
/// current render pass.
|
||||
///
|
||||
/// "The given context" here means being inside/outside a render pass or a secondary command
|
||||
/// buffer.
|
||||
pub struct ContextCheckLayer<I> {
|
||||
// Inner command buffer builder.
|
||||
inner: I,
|
||||
// True if we are currently inside a render pass.
|
||||
inside_render_pass: bool,
|
||||
// True if entering/leaving a render pass or going to the next subpass is allowed.
|
||||
allow_render_pass_ops: bool,
|
||||
}
|
||||
|
||||
impl<I> ContextCheckLayer<I> {
|
||||
/// Builds a new `ContextCheckLayer`.
|
||||
///
|
||||
/// If `allow_render_pass_ops` is true, then entering/leaving a render pass or going to the
|
||||
/// next subpass is allowed by the layer.
|
||||
///
|
||||
/// If `inside_render_pass` is true, then the builder is currently inside a render pass.
|
||||
///
|
||||
/// Note that this layer will only protect you if you pass correct values in this constructor.
|
||||
/// It is not unsafe to pass wrong values, but if you do so then the layer will be inefficient
|
||||
/// as a safety tool.
|
||||
#[inline]
|
||||
pub fn new(inner: I) -> ContextCheckLayer<I> {
|
||||
pub fn new(inner: I, inside_render_pass: bool, allow_render_pass_ops: bool)
|
||||
-> ContextCheckLayer<I>
|
||||
{
|
||||
ContextCheckLayer {
|
||||
inner: inner,
|
||||
inside_render_pass: inside_render_pass,
|
||||
allow_render_pass_ops: allow_render_pass_ops,
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,9 +100,18 @@ unsafe impl<I> CommandBufferBuilder for ContextCheckLayer<I>
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: actually implement
|
||||
// TODO:
|
||||
// impl!((C), commands_raw::CmdExecuteCommands<C>);
|
||||
|
||||
macro_rules! pass_through {
|
||||
// FIXME: must also check that a pipeline's render pass matches the render pass
|
||||
|
||||
// FIXME:
|
||||
// > If the variable multisample rate feature is not supported, pipeline is a graphics pipeline,
|
||||
// > the current subpass has no attachments, and this is not the first call to this function with
|
||||
// > a graphics pipeline after transitioning to the current subpass, then the sample count
|
||||
// > specified by this pipeline must match that set in the previous pipeline
|
||||
|
||||
macro_rules! impl_always {
|
||||
(($($param:ident),*), $cmd:ty) => {
|
||||
unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for ContextCheckLayer<I>
|
||||
where I: AddCommand<$cmd, Out = O>
|
||||
@ -88,32 +122,130 @@ macro_rules! pass_through {
|
||||
fn add(self, command: $cmd) -> Self::Out {
|
||||
ContextCheckLayer {
|
||||
inner: self.inner.add(command),
|
||||
inside_render_pass: self.inside_render_pass,
|
||||
allow_render_pass_ops: self.allow_render_pass_ops,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pass_through!((Rp, F), commands_raw::CmdBeginRenderPass<Rp, F>);
|
||||
pass_through!((S, Pl), commands_raw::CmdBindDescriptorSets<S, Pl>);
|
||||
pass_through!((B), commands_raw::CmdBindIndexBuffer<B>);
|
||||
pass_through!((Pl), commands_raw::CmdBindPipeline<Pl>);
|
||||
pass_through!((V), commands_raw::CmdBindVertexBuffers<V>);
|
||||
pass_through!((S, D), commands_raw::CmdBlitImage<S, D>);
|
||||
pass_through!((), commands_raw::CmdClearAttachments);
|
||||
pass_through!((S, D), commands_raw::CmdCopyBuffer<S, D>);
|
||||
pass_through!((S, D), commands_raw::CmdCopyBufferToImage<S, D>);
|
||||
pass_through!((S, D), commands_raw::CmdCopyImage<S, D>);
|
||||
pass_through!((), commands_raw::CmdDispatchRaw);
|
||||
pass_through!((), commands_raw::CmdDrawIndexedRaw);
|
||||
pass_through!((B), commands_raw::CmdDrawIndirectRaw<B>);
|
||||
pass_through!((), commands_raw::CmdDrawRaw);
|
||||
pass_through!((), commands_raw::CmdEndRenderPass);
|
||||
pass_through!((C), commands_raw::CmdExecuteCommands<C>);
|
||||
pass_through!((B), commands_raw::CmdFillBuffer<B>);
|
||||
pass_through!((), commands_raw::CmdNextSubpass);
|
||||
pass_through!((Pc, Pl), commands_raw::CmdPushConstants<Pc, Pl>);
|
||||
pass_through!((S, D), commands_raw::CmdResolveImage<S, D>);
|
||||
pass_through!((), commands_raw::CmdSetEvent);
|
||||
pass_through!((), commands_raw::CmdSetState);
|
||||
pass_through!((B, D), commands_raw::CmdUpdateBuffer<B, D>);
|
||||
impl_always!((S, Pl), commands_raw::CmdBindDescriptorSets<S, Pl>);
|
||||
impl_always!((B), commands_raw::CmdBindIndexBuffer<B>);
|
||||
impl_always!((Pl), commands_raw::CmdBindPipeline<Pl>);
|
||||
impl_always!((V), commands_raw::CmdBindVertexBuffers<V>);
|
||||
impl_always!((Pc, Pl), commands_raw::CmdPushConstants<Pc, Pl>);
|
||||
|
||||
macro_rules! impl_inside_only {
|
||||
(($($param:ident),*), $cmd:ty) => {
|
||||
unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for ContextCheckLayer<I>
|
||||
where I: AddCommand<$cmd, Out = O>
|
||||
{
|
||||
type Out = ContextCheckLayer<O>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, command: $cmd) -> Self::Out {
|
||||
assert!(self.inside_render_pass); // TODO: proper error
|
||||
|
||||
ContextCheckLayer {
|
||||
inner: self.inner.add(command),
|
||||
inside_render_pass: self.inside_render_pass,
|
||||
allow_render_pass_ops: self.allow_render_pass_ops,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_inside_only!((), commands_raw::CmdClearAttachments);
|
||||
impl_inside_only!((), commands_raw::CmdDrawIndexedRaw);
|
||||
impl_inside_only!((B), commands_raw::CmdDrawIndirectRaw<B>);
|
||||
impl_inside_only!((), commands_raw::CmdDrawRaw);
|
||||
|
||||
macro_rules! impl_outside_only {
|
||||
(($($param:ident),*), $cmd:ty) => {
|
||||
unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for ContextCheckLayer<I>
|
||||
where I: AddCommand<$cmd, Out = O>
|
||||
{
|
||||
type Out = ContextCheckLayer<O>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, command: $cmd) -> Self::Out {
|
||||
assert!(!self.inside_render_pass); // TODO: proper error
|
||||
|
||||
ContextCheckLayer {
|
||||
inner: self.inner.add(command),
|
||||
inside_render_pass: self.inside_render_pass,
|
||||
allow_render_pass_ops: self.allow_render_pass_ops,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_outside_only!((S, D), commands_raw::CmdBlitImage<S, D>);
|
||||
impl_outside_only!((S, D), commands_raw::CmdCopyBuffer<S, D>);
|
||||
impl_outside_only!((S, D), commands_raw::CmdCopyBufferToImage<S, D>);
|
||||
impl_outside_only!((S, D), commands_raw::CmdCopyImage<S, D>);
|
||||
impl_outside_only!((), commands_raw::CmdDispatchRaw);
|
||||
impl_outside_only!((B), commands_raw::CmdFillBuffer<B>);
|
||||
impl_outside_only!((S, D), commands_raw::CmdResolveImage<S, D>);
|
||||
impl_outside_only!((), commands_raw::CmdSetEvent);
|
||||
impl_outside_only!((), commands_raw::CmdSetState);
|
||||
impl_outside_only!((B, D), commands_raw::CmdUpdateBuffer<B, D>);
|
||||
|
||||
unsafe impl<'a, I, O, Rp, F> AddCommand<commands_raw::CmdBeginRenderPass<Rp, F>> for ContextCheckLayer<I>
|
||||
where I: AddCommand<commands_raw::CmdBeginRenderPass<Rp, F>, Out = O>
|
||||
{
|
||||
type Out = ContextCheckLayer<O>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, command: commands_raw::CmdBeginRenderPass<Rp, F>) -> Self::Out {
|
||||
assert!(!self.inside_render_pass); // TODO: proper error
|
||||
assert!(self.allow_render_pass_ops); // TODO: proper error
|
||||
|
||||
ContextCheckLayer {
|
||||
inner: self.inner.add(command),
|
||||
inside_render_pass: true,
|
||||
allow_render_pass_ops: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, I, O> AddCommand<commands_raw::CmdNextSubpass> for ContextCheckLayer<I>
|
||||
where I: AddCommand<commands_raw::CmdNextSubpass, Out = O>
|
||||
{
|
||||
type Out = ContextCheckLayer<O>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, command: commands_raw::CmdNextSubpass) -> Self::Out {
|
||||
assert!(self.inside_render_pass); // TODO: proper error
|
||||
assert!(self.allow_render_pass_ops); // TODO: proper error
|
||||
// FIXME: check number of subpasses
|
||||
|
||||
ContextCheckLayer {
|
||||
inner: self.inner.add(command),
|
||||
inside_render_pass: true,
|
||||
allow_render_pass_ops: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<'a, I, O> AddCommand<commands_raw::CmdEndRenderPass> for ContextCheckLayer<I>
|
||||
where I: AddCommand<commands_raw::CmdEndRenderPass, Out = O>
|
||||
{
|
||||
type Out = ContextCheckLayer<O>;
|
||||
|
||||
#[inline]
|
||||
fn add(self, command: commands_raw::CmdEndRenderPass) -> Self::Out {
|
||||
assert!(self.inside_render_pass); // TODO: proper error
|
||||
assert!(self.allow_render_pass_ops); // TODO: proper error
|
||||
// FIXME: check number of subpasses
|
||||
|
||||
ContextCheckLayer {
|
||||
inner: self.inner.add(command),
|
||||
inside_render_pass: false,
|
||||
allow_render_pass_ops: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user