Merge pull request #420 from tomaka/queue-ty

Implement QueueTyCheckLayer correctly
This commit is contained in:
tomaka 2017-04-17 12:41:14 +02:00 committed by GitHub
commit a1b65b3845
10 changed files with 249 additions and 30 deletions

View File

@ -40,6 +40,9 @@ impl AutoCommandBufferBuilder<Arc<StandardCommandPool>> {
pub fn new(device: Arc<Device>, queue_family: QueueFamily)
-> Result<AutoCommandBufferBuilder<Arc<StandardCommandPool>>, OomError>
{
let supports_graphics = queue_family.supports_graphics();
let supports_compute = queue_family.supports_compute();
let pool = Device::standard_command_pool(&device, queue_family);
let cmd = unsafe {
@ -49,7 +52,7 @@ impl AutoCommandBufferBuilder<Arc<StandardCommandPool>> {
let c = cb::SubmitSyncBuilderLayer::new(c);
let c = cb::StateCacheLayer::new(c);
let c = cb::ContextCheckLayer::new(c);
let c = cb::QueueTyCheckLayer::new(c);
let c = cb::QueueTyCheckLayer::new(c, supports_graphics, supports_compute);
let c = cb::DeviceCheckLayer::new(c);
c
};
@ -119,6 +122,15 @@ unsafe impl<P> CommandBufferBuilder for AutoCommandBufferBuilder<P>
where Cb<P>: CommandBufferBuilder,
P: CommandPool
{
#[inline]
fn supports_graphics(&self) -> bool {
self.inner.supports_graphics()
}
#[inline]
fn supports_compute(&self) -> bool {
self.inner.supports_compute()
}
}
macro_rules! pass_through {

View File

@ -198,6 +198,12 @@ pub unsafe trait CommandBufferBuilder: DeviceOwned {
{
CommandBufferBuild::build(self)
}
/// Returns true if the pool of the builder supports graphics operations.
fn supports_graphics(&self) -> bool;
/// Returns true if the pool of the builder supports compute operations.
fn supports_compute(&self) -> bool;
}
pub unsafe trait CommandBufferBuilderBuffered {

View File

@ -95,7 +95,16 @@ unsafe impl<I, O, E> CommandBufferBuild for AbstractStorageLayer<I>
}
}
unsafe impl<I> CommandBufferBuilder for AbstractStorageLayer<I> where I: DeviceOwned {
unsafe impl<I> CommandBufferBuilder for AbstractStorageLayer<I> where I: CommandBufferBuilder {
#[inline]
fn supports_graphics(&self) -> bool {
self.inner.supports_graphics()
}
#[inline]
fn supports_compute(&self) -> bool {
self.inner.supports_compute()
}
}
macro_rules! pass_through {

View File

@ -65,6 +65,15 @@ unsafe impl<I> DeviceOwned for AutoPipelineBarriersLayer<I>
unsafe impl<I> CommandBufferBuilder for AutoPipelineBarriersLayer<I>
where I: CommandBufferBuilder
{
#[inline]
fn supports_graphics(&self) -> bool {
self.inner.supports_graphics()
}
#[inline]
fn supports_compute(&self) -> bool {
self.inner.supports_compute()
}
}
macro_rules! pass_through {

View File

@ -64,6 +64,15 @@ unsafe impl<I> DeviceOwned for ContextCheckLayer<I>
unsafe impl<I> CommandBufferBuilder for ContextCheckLayer<I>
where I: CommandBufferBuilder
{
#[inline]
fn supports_graphics(&self) -> bool {
self.inner.supports_graphics()
}
#[inline]
fn supports_compute(&self) -> bool {
self.inner.supports_compute()
}
}
// TODO: actually implement

View File

@ -50,6 +50,15 @@ unsafe impl<I> DeviceOwned for DeviceCheckLayer<I>
unsafe impl<I> CommandBufferBuilder for DeviceCheckLayer<I>
where I: CommandBufferBuilder
{
#[inline]
fn supports_graphics(&self) -> bool {
self.inner.supports_graphics()
}
#[inline]
fn supports_compute(&self) -> bool {
self.inner.supports_compute()
}
}
unsafe impl<I, O, E> CommandBufferBuild for DeviceCheckLayer<I>

View File

@ -22,14 +22,22 @@ use device::DeviceOwned;
/// that support graphical or compute operations. This is what this layer verifies.
pub struct QueueTyCheckLayer<I> {
inner: I,
supports_graphics: bool,
supports_compute: bool,
}
impl<I> QueueTyCheckLayer<I> {
/// Builds a new `QueueTyCheckLayer`.
///
/// Note that this layer will only protect you if you pass correct values for
/// `supports_graphics` and `supports_compute`. 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) -> QueueTyCheckLayer<I> {
pub fn new(inner: I, supports_graphics: bool, supports_compute: bool) -> QueueTyCheckLayer<I> {
QueueTyCheckLayer {
inner: inner,
supports_graphics: supports_graphics,
supports_compute: supports_compute,
}
}
@ -38,6 +46,22 @@ impl<I> QueueTyCheckLayer<I> {
pub fn into_inner(self) -> I {
self.inner
}
/// Returns true if graphical operations can be added to this layer.
///
/// This returns the same value as what was passed to the constructor.
#[inline]
pub fn supports_graphics(&self) -> bool {
self.supports_graphics
}
/// Returns true if compute operations can be added to this layer.
///
/// This returns the same value as what was passed to the constructor.
#[inline]
pub fn supports_compute(&self) -> bool {
self.supports_compute
}
}
unsafe impl<I> DeviceOwned for QueueTyCheckLayer<I>
@ -49,9 +73,16 @@ unsafe impl<I> DeviceOwned for QueueTyCheckLayer<I>
}
}
unsafe impl<I> CommandBufferBuilder for QueueTyCheckLayer<I>
where I: CommandBufferBuilder
{
unsafe impl<I> CommandBufferBuilder for QueueTyCheckLayer<I> where I: DeviceOwned {
#[inline]
fn supports_graphics(&self) -> bool {
self.supports_graphics
}
#[inline]
fn supports_compute(&self) -> bool {
self.supports_compute
}
}
unsafe impl<I, O, E> CommandBufferBuild for QueueTyCheckLayer<I>
@ -68,7 +99,10 @@ unsafe impl<I, O, E> CommandBufferBuild for QueueTyCheckLayer<I>
// TODO: actually implement
macro_rules! pass_through {
// TODO: implement CmdExecuteCommands
//q_ty_impl!((C), commands_raw::CmdExecuteCommands<C>);
macro_rules! q_ty_impl_always {
(($($param:ident),*), $cmd:ty) => {
unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for QueueTyCheckLayer<I>
where I: AddCommand<$cmd, Out = O>
@ -79,32 +113,136 @@ macro_rules! pass_through {
fn add(self, command: $cmd) -> Self::Out {
QueueTyCheckLayer {
inner: self.inner.add(command),
supports_graphics: self.supports_graphics,
supports_compute: self.supports_compute,
}
}
}
}
}
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>);
q_ty_impl_always!((S, D), commands_raw::CmdCopyBuffer<S, D>);
q_ty_impl_always!((S, D), commands_raw::CmdCopyBufferToImage<S, D>);
q_ty_impl_always!((S, D), commands_raw::CmdCopyImage<S, D>);
q_ty_impl_always!((B), commands_raw::CmdFillBuffer<B>);
q_ty_impl_always!((B, D), commands_raw::CmdUpdateBuffer<B, D>);
macro_rules! q_ty_impl_graphics {
(($($param:ident),*), $cmd:ty) => {
unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for QueueTyCheckLayer<I>
where I: AddCommand<$cmd, Out = O>
{
type Out = QueueTyCheckLayer<O>;
#[inline]
fn add(self, command: $cmd) -> Self::Out {
assert!(self.supports_graphics()); // TODO: proper error
QueueTyCheckLayer {
inner: self.inner.add(command),
supports_graphics: self.supports_graphics,
supports_compute: self.supports_compute,
}
}
}
}
}
q_ty_impl_graphics!((Rp, F), commands_raw::CmdBeginRenderPass<Rp, F>);
q_ty_impl_graphics!((B), commands_raw::CmdBindIndexBuffer<B>);
q_ty_impl_graphics!((V), commands_raw::CmdBindVertexBuffers<V>);
q_ty_impl_graphics!((S, D), commands_raw::CmdBlitImage<S, D>);
q_ty_impl_graphics!((), commands_raw::CmdClearAttachments);
q_ty_impl_graphics!((), commands_raw::CmdDrawIndexedRaw);
q_ty_impl_graphics!((B), commands_raw::CmdDrawIndirectRaw<B>);
q_ty_impl_graphics!((), commands_raw::CmdDrawRaw);
q_ty_impl_graphics!((), commands_raw::CmdEndRenderPass);
q_ty_impl_graphics!((), commands_raw::CmdNextSubpass);
q_ty_impl_graphics!((S, D), commands_raw::CmdResolveImage<S, D>);
macro_rules! q_ty_impl_compute {
(($($param:ident),*), $cmd:ty) => {
unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for QueueTyCheckLayer<I>
where I: AddCommand<$cmd, Out = O>
{
type Out = QueueTyCheckLayer<O>;
#[inline]
fn add(self, command: $cmd) -> Self::Out {
assert!(self.supports_compute()); // TODO: proper error
QueueTyCheckLayer {
inner: self.inner.add(command),
supports_graphics: self.supports_graphics,
supports_compute: self.supports_compute,
}
}
}
}
}
q_ty_impl_compute!((), commands_raw::CmdDispatchRaw);
macro_rules! q_ty_impl_graphics_or_compute {
(($($param:ident),*), $cmd:ty) => {
unsafe impl<'a, I, O $(, $param)*> AddCommand<$cmd> for QueueTyCheckLayer<I>
where I: AddCommand<$cmd, Out = O>
{
type Out = QueueTyCheckLayer<O>;
#[inline]
fn add(self, command: $cmd) -> Self::Out {
assert!(self.supports_graphics() || self.supports_compute()); // TODO: proper error
QueueTyCheckLayer {
inner: self.inner.add(command),
supports_graphics: self.supports_graphics,
supports_compute: self.supports_compute,
}
}
}
}
}
q_ty_impl_graphics_or_compute!((Pc, Pl), commands_raw::CmdPushConstants<Pc, Pl>);
q_ty_impl_graphics_or_compute!((), commands_raw::CmdSetEvent);
q_ty_impl_graphics_or_compute!((), commands_raw::CmdSetState);
unsafe impl<I, O, Pl> AddCommand<commands_raw::CmdBindPipeline<Pl>> for QueueTyCheckLayer<I>
where I: AddCommand<commands_raw::CmdBindPipeline<Pl>, Out = O>
{
type Out = QueueTyCheckLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdBindPipeline<Pl>) -> Self::Out {
if command.is_graphics() {
assert!(self.supports_graphics()); // TODO: proper error
} else {
assert!(self.supports_compute()); // TODO: proper error
}
QueueTyCheckLayer {
inner: self.inner.add(command),
supports_graphics: self.supports_graphics,
supports_compute: self.supports_compute,
}
}
}
unsafe impl<I, O, S, Pl> AddCommand<commands_raw::CmdBindDescriptorSets<S, Pl>> for QueueTyCheckLayer<I>
where I: AddCommand<commands_raw::CmdBindDescriptorSets<S, Pl>, Out = O>
{
type Out = QueueTyCheckLayer<O>;
#[inline]
fn add(self, command: commands_raw::CmdBindDescriptorSets<S, Pl>) -> Self::Out {
if command.is_graphics() {
assert!(self.supports_graphics()); // TODO: proper error
} else {
assert!(self.supports_compute()); // TODO: proper error
}
QueueTyCheckLayer {
inner: self.inner.add(command),
supports_graphics: self.supports_graphics,
supports_compute: self.supports_compute,
}
}
}

View File

@ -78,6 +78,15 @@ unsafe impl<I> DeviceOwned for StateCacheLayer<I>
unsafe impl<I> CommandBufferBuilder for StateCacheLayer<I>
where I: CommandBufferBuilder
{
#[inline]
fn supports_graphics(&self) -> bool {
self.inner.supports_graphics()
}
#[inline]
fn supports_compute(&self) -> bool {
self.inner.supports_compute()
}
}
unsafe impl<Pl, I, O> AddCommand<commands_raw::CmdBindPipeline<Pl>> for StateCacheLayer<I>

View File

@ -106,6 +106,15 @@ unsafe impl<I> DeviceOwned for SubmitSyncBuilderLayer<I>
unsafe impl<I> CommandBufferBuilder for SubmitSyncBuilderLayer<I>
where I: CommandBufferBuilder
{
#[inline]
fn supports_graphics(&self) -> bool {
self.inner.supports_graphics()
}
#[inline]
fn supports_compute(&self) -> bool {
self.inner.supports_compute()
}
}
// FIXME: implement manually

View File

@ -95,6 +95,15 @@ impl<S, P> CmdBindDescriptorSets<S, P>
}
}
impl<S, P> CmdBindDescriptorSets<S, P> {
/// True if we bind to the graphics pipeline. False if the compute pipeline.
// TODO: should be an enum?
#[inline]
pub fn is_graphics(&self) -> bool {
self.pipeline_ty == vk::PIPELINE_BIND_POINT_GRAPHICS
}
}
unsafe impl<S, Pl> DeviceOwned for CmdBindDescriptorSets<S, Pl>
where Pl: DeviceOwned
{