Merge pull request #669 from tomaka/ds-correct-sync

Correctly synchronize resources in descriptor sets
This commit is contained in:
tomaka 2017-07-21 20:00:04 +02:00 committed by GitHub
commit 3303cbe934
6 changed files with 759 additions and 170 deletions

View File

@ -10,6 +10,7 @@
use fnv::FnvHashMap;
use smallvec::SmallVec;
use std::any::Any;
use std::borrow::Cow;
use std::collections::hash_map::Entry;
use std::error;
use std::fmt;
@ -36,6 +37,7 @@ use command_buffer::sys::UnsafeCommandBufferBuilderColorImageClear;
use command_buffer::sys::UnsafeCommandBufferBuilderExecuteCommands;
use command_buffer::sys::UnsafeCommandBufferBuilderImageBlit;
use command_buffer::sys::UnsafeCommandBufferBuilderPipelineBarrier;
use descriptor::descriptor::DescriptorDescTy;
use descriptor::descriptor::ShaderStages;
use descriptor::descriptor_set::DescriptorSet;
use descriptor::pipeline_layout::PipelineLayoutAbstract;
@ -92,6 +94,9 @@ pub struct SyncCommandBufferBuilder<P> {
// Stores all the commands that were submitted or are going to be submitted to the inner
// builder. A copy of this `Arc` is stored in each `BuilderKey`.
commands: Arc<Mutex<Commands<P>>>,
// True if we're a secondary command buffer.
is_secondary: bool,
}
impl<P> fmt::Debug for SyncCommandBufferBuilder<P> {
@ -105,15 +110,22 @@ impl<P> fmt::Debug for SyncCommandBufferBuilder<P> {
#[derive(Debug, Clone)]
pub enum SyncCommandBufferBuilderError {
/// Unsolvable conflict.
// TODO: add details
Conflict,
Conflict {
command1_name: &'static str,
command1_param: Cow<'static, str>,
command1_offset: usize,
command2_name: &'static str,
command2_param: Cow<'static, str>,
command2_offset: usize,
},
}
impl error::Error for SyncCommandBufferBuilderError {
#[inline]
fn description(&self) -> &str {
match *self {
SyncCommandBufferBuilderError::Conflict => {
SyncCommandBufferBuilderError::Conflict { .. } => {
"unsolvable conflict"
},
}
@ -133,12 +145,19 @@ struct Commands<P> {
// `UnsafeCommandBufferBuilder`.
first_unflushed: usize,
// If we're currently inside a render pass, contains the index of the `CmdBeginRenderPass`
// command.
latest_render_pass_enter: Option<usize>,
// The actual list.
commands: Vec<Box<Command<P> + Send + Sync>>,
}
// A single command within the list of commands.
trait Command<P> {
// Returns a user-friendly name for the command for error reporting purposes.
fn name(&self) -> &'static str;
// Sends the command to the `UnsafeCommandBufferBuilder`. Calling this method twice on the same
// object may lead to a panic.
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>);
@ -154,6 +173,17 @@ trait Command<P> {
fn image(&self, num: usize) -> &ImageAccess {
panic!()
}
// Returns a user-friendly name for the `num`th buffer used by the command, for error
// reporting purposes.
fn buffer_name(&self, num: usize) -> Cow<'static, str> {
panic!()
}
// Returns a user-friendly name for the `num`th image used by the command, for error
// reporting purposes.
fn image_name(&self, num: usize) -> Cow<'static, str> {
panic!()
}
}
// Key that identifies a resource. Implements `PartialEq`, `Eq` and `Hash` so that two resources
@ -315,8 +345,13 @@ impl<P> SyncCommandBufferBuilder<P> {
R: RenderPassAbstract,
F: FramebufferAbstract
{
let (is_secondary, inside_render_pass) = match kind {
Kind::Primary => (false, false),
Kind::Secondary { ref render_pass, .. } => (true, render_pass.is_some()),
};
let cmd = UnsafeCommandBufferBuilder::new(pool, kind, flags)?;
Ok(SyncCommandBufferBuilder::from_unsafe_cmd(cmd))
Ok(SyncCommandBufferBuilder::from_unsafe_cmd(cmd, is_secondary, inside_render_pass))
}
/// Builds a `SyncCommandBufferBuilder` from an existing `UnsafeCommandBufferBuilder`.
@ -329,16 +364,24 @@ impl<P> SyncCommandBufferBuilder<P> {
/// you must take into account the fact that the `SyncCommandBufferBuilder` won't be aware of
/// any existing resource usage.
#[inline]
pub unsafe fn from_unsafe_cmd(cmd: UnsafeCommandBufferBuilder<P>)
-> SyncCommandBufferBuilder<P> {
pub unsafe fn from_unsafe_cmd(cmd: UnsafeCommandBufferBuilder<P>, is_secondary: bool,
inside_render_pass: bool) -> SyncCommandBufferBuilder<P> {
let latest_render_pass_enter = if inside_render_pass {
Some(0)
} else {
None
};
SyncCommandBufferBuilder {
inner: cmd,
resources: FnvHashMap::default(),
pending_barrier: UnsafeCommandBufferBuilderPipelineBarrier::new(),
commands: Arc::new(Mutex::new(Commands {
first_unflushed: 0,
latest_render_pass_enter,
commands: Vec::new(),
})),
is_secondary,
}
}
@ -373,10 +416,9 @@ impl<P> SyncCommandBufferBuilder<P> {
Entry::Occupied(entry) => {
let collision_command_id = entry.key().command_id;
debug_assert!(collision_command_id <= latest_command_id);
if collision_command_id == latest_command_id {
return Err(SyncCommandBufferBuilderError::Conflict);
}
let entry_key_resource_index = entry.key().resource_index;
let entry_key_resource_ty = entry.key().resource_ty;
let mut entry = entry.into_mut();
// Find out if we have a collision with the pending commands.
@ -394,11 +436,33 @@ impl<P> SyncCommandBufferBuilder<P> {
self.pending_barrier = UnsafeCommandBufferBuilderPipelineBarrier::new();
{
let mut commands_lock = self.commands.lock().unwrap();
let f = commands_lock.first_unflushed;
for command in &mut commands_lock.commands[f .. latest_command_id] {
let start = commands_lock.first_unflushed;
let end = if let Some(rp_enter) = commands_lock.latest_render_pass_enter {
rp_enter
} else {
latest_command_id
};
if collision_command_id >= end {
return Err(SyncCommandBufferBuilderError::Conflict {
command1_name: commands_lock.commands[collision_command_id].name(),
command1_param: match entry_key_resource_ty {
KeyTy::Buffer => commands_lock.commands[collision_command_id].buffer_name(entry_key_resource_index),
KeyTy::Image => commands_lock.commands[collision_command_id].image_name(entry_key_resource_index),
},
command1_offset: collision_command_id,
command2_name: commands_lock.commands[latest_command_id].name(),
command2_param: match resource_ty {
KeyTy::Buffer => commands_lock.commands[latest_command_id].buffer_name(resource_index),
KeyTy::Image => commands_lock.commands[latest_command_id].image_name(resource_index),
},
command2_offset: latest_command_id,
});
}
for command in &mut commands_lock.commands[start .. end] {
command.send(&mut self.inner);
}
commands_lock.first_unflushed = latest_command_id;
commands_lock.first_unflushed = end;
}
}
}
@ -448,7 +512,7 @@ impl<P> SyncCommandBufferBuilder<P> {
entry.access = access;
entry.exclusive_any = true;
entry.exclusive = exclusive;
if exclusive {
if exclusive || end_layout != ImageLayout::Undefined {
// Only modify the layout in case of a write, because buffer operations
// pass `Undefined` for the layout. While a buffer write *must* set the
// layout to `Undefined`, a buffer read must not touch it.
@ -466,7 +530,8 @@ impl<P> SyncCommandBufferBuilder<P> {
// Handle the case when the initial layout requirement of the image is different
// from the first layout usage.
if resource_ty == KeyTy::Image && start_layout != ImageLayout::Undefined &&
if !self.is_secondary && resource_ty == KeyTy::Image &&
start_layout != ImageLayout::Undefined &&
start_layout != ImageLayout::Preinitialized
{
let commands_lock = self.commands.lock().unwrap();
@ -515,6 +580,8 @@ impl<P> SyncCommandBufferBuilder<P> {
where P: CommandPoolBuilderAlloc
{
let mut commands_lock = self.commands.lock().unwrap();
debug_assert!(commands_lock.latest_render_pass_enter.is_none() ||
self.pending_barrier.is_empty());
// Flush the commands that haven't been flushed yet.
unsafe {
@ -526,37 +593,39 @@ impl<P> SyncCommandBufferBuilder<P> {
}
// Transition images to their desired final layout.
unsafe {
let mut barrier = UnsafeCommandBufferBuilderPipelineBarrier::new();
if !self.is_secondary {
unsafe {
let mut barrier = UnsafeCommandBufferBuilderPipelineBarrier::new();
for (key, mut state) in &mut self.resources {
if key.resource_ty != KeyTy::Image {
continue;
for (key, mut state) in &mut self.resources {
if key.resource_ty != KeyTy::Image {
continue;
}
let img = commands_lock.commands[key.command_id].image(key.resource_index);
if img.final_layout_requirement() == state.current_layout {
continue;
}
state.exclusive_any = true;
barrier.add_image_memory_barrier(img,
0 .. img.mipmap_levels(),
0 .. img.dimensions().array_layers(),
state.stages,
state.access,
PipelineStages {
bottom_of_pipe: true,
..PipelineStages::none()
}, // TODO:?
AccessFlagBits::none(),
true,
None, // TODO: access?
state.current_layout,
img.final_layout_requirement());
}
let img = commands_lock.commands[key.command_id].image(key.resource_index);
if img.final_layout_requirement() == state.current_layout {
continue;
}
state.exclusive_any = true;
barrier.add_image_memory_barrier(img,
0 .. img.mipmap_levels(),
0 .. img.dimensions().array_layers(),
state.stages,
state.access,
PipelineStages {
bottom_of_pipe: true,
..PipelineStages::none()
}, // TODO:?
AccessFlagBits::none(),
true,
None, // TODO: access?
state.current_layout,
img.final_layout_requirement());
self.inner.pipeline_barrier(&barrier);
}
self.inner.pipeline_barrier(&barrier);
}
// Fill the `commands` list.
@ -606,6 +675,10 @@ impl<P> SyncCommandBufferBuilder<P> {
where F: FramebufferAbstract + Send + Sync + 'static,
I: Iterator<Item = ClearValue>
{
fn name(&self) -> &'static str {
"vkCmdBeginRenderPass"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.begin_render_pass(&self.framebuffer,
self.subpass_contents,
@ -627,6 +700,10 @@ impl<P> SyncCommandBufferBuilder<P> {
fn image(&self, num: usize) -> &ImageAccess {
self.framebuffer.attached_image_view(num).unwrap().parent()
}
fn image_name(&self, num: usize) -> Cow<'static, str> {
format!("attachment {}", num).into()
}
}
let atch_desc = (0 .. framebuffer.num_attachments())
@ -658,6 +735,11 @@ impl<P> SyncCommandBufferBuilder<P> {
desc.initial_layout, desc.final_layout)?;
}
{
let mut cmd_lock = self.commands.lock().unwrap();
cmd_lock.latest_render_pass_enter = Some(cmd_lock.commands.len() - 1);
}
Ok(())
}
@ -675,6 +757,10 @@ impl<P> SyncCommandBufferBuilder<P> {
impl<P, B> Command<P> for Cmd<B>
where B: BufferAccess + Send + Sync + 'static
{
fn name(&self) -> &'static str {
"vkCmdBindIndexBuffer"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.bind_index_buffer(&self.buffer, self.index_ty);
}
@ -696,6 +782,11 @@ impl<P> SyncCommandBufferBuilder<P> {
assert_eq!(num, 0);
&self.buffer
}
fn buffer_name(&self, num: usize) -> Cow<'static, str> {
assert_eq!(num, 0);
"index buffer".into()
}
}
self.commands
@ -731,6 +822,10 @@ impl<P> SyncCommandBufferBuilder<P> {
impl<P, Gp> Command<P> for Cmd<Gp>
where Gp: GraphicsPipelineAbstract + Send + Sync + 'static
{
fn name(&self) -> &'static str {
"vkCmdBindPipeline"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.bind_pipeline_graphics(&self.pipeline);
}
@ -764,6 +859,10 @@ impl<P> SyncCommandBufferBuilder<P> {
impl<P, Gp> Command<P> for Cmd<Gp>
where Gp: ComputePipelineAbstract + Send + Sync + 'static
{
fn name(&self) -> &'static str {
"vkCmdBindPipeline"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.bind_pipeline_compute(&self.pipeline);
}
@ -833,6 +932,10 @@ impl<P> SyncCommandBufferBuilder<P> {
D: ImageAccess + Send + Sync + 'static,
R: Iterator<Item = UnsafeCommandBufferBuilderImageBlit>
{
fn name(&self) -> &'static str {
"vkCmdBlitImage"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.blit_image(self.source.as_ref().unwrap(), self.source_layout,
self.destination.as_ref().unwrap(), self.destination_layout,
@ -871,6 +974,16 @@ impl<P> SyncCommandBufferBuilder<P> {
panic!()
}
}
fn image_name(&self, num: usize) -> Cow<'static, str> {
if num == 0 {
"source".into()
} else if num == 1 {
"destination".into()
} else {
panic!()
}
}
}
self.commands.lock().unwrap().commands.push(Box::new(Cmd {
@ -931,6 +1044,10 @@ impl<P> SyncCommandBufferBuilder<P> {
where I: ImageAccess + Send + Sync + 'static,
R: Iterator<Item = UnsafeCommandBufferBuilderColorImageClear> + Send + Sync + 'static
{
fn name(&self) -> &'static str {
"vkCmdClearColorImage"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.clear_color_image(self.image.as_ref().unwrap(), self.layout, self.color,
self.regions.take().unwrap());
@ -955,6 +1072,11 @@ impl<P> SyncCommandBufferBuilder<P> {
assert_eq!(num, 0);
self.image.as_ref().unwrap()
}
fn image_name(&self, num: usize) -> Cow<'static, str> {
assert_eq!(num, 0);
"target".into()
}
}
self.commands.lock().unwrap().commands.push(Box::new(Cmd {
@ -1001,6 +1123,10 @@ impl<P> SyncCommandBufferBuilder<P> {
D: BufferAccess + Send + Sync + 'static,
R: Iterator<Item = (usize, usize, usize)>
{
fn name(&self) -> &'static str {
"vkCmdCopyBuffer"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.copy_buffer(self.source.as_ref().unwrap(),
self.destination.as_ref().unwrap(),
@ -1034,6 +1160,14 @@ impl<P> SyncCommandBufferBuilder<P> {
_ => panic!(),
}
}
fn buffer_name(&self, num: usize) -> Cow<'static, str> {
match num {
0 => "source".into(),
1 => "destination".into(),
_ => panic!(),
}
}
}
self.commands.lock().unwrap().commands.push(Box::new(Cmd {
@ -1094,6 +1228,10 @@ impl<P> SyncCommandBufferBuilder<P> {
D: ImageAccess + Send + Sync + 'static,
R: Iterator<Item = UnsafeCommandBufferBuilderBufferImageCopy>
{
fn name(&self) -> &'static str {
"vkCmdCopyBufferToImage"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.copy_buffer_to_image(self.source.as_ref().unwrap(),
self.destination.as_ref().unwrap(),
@ -1129,10 +1267,20 @@ impl<P> SyncCommandBufferBuilder<P> {
self.source.as_ref().unwrap()
}
fn buffer_name(&self, num: usize) -> Cow<'static, str> {
assert_eq!(num, 0);
"source".into()
}
fn image(&self, num: usize) -> &ImageAccess {
assert_eq!(num, 0);
self.destination.as_ref().unwrap()
}
fn image_name(&self, num: usize) -> Cow<'static, str> {
assert_eq!(num, 0);
"destination".into()
}
}
self.commands.lock().unwrap().commands.push(Box::new(Cmd {
@ -1194,6 +1342,10 @@ impl<P> SyncCommandBufferBuilder<P> {
D: BufferAccess + Send + Sync + 'static,
R: Iterator<Item = UnsafeCommandBufferBuilderBufferImageCopy>
{
fn name(&self) -> &'static str {
"vkCmdCopyImageToBuffer"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.copy_image_to_buffer(self.source.as_ref().unwrap(),
self.source_layout,
@ -1229,10 +1381,20 @@ impl<P> SyncCommandBufferBuilder<P> {
self.destination.as_ref().unwrap()
}
fn buffer_name(&self, num: usize) -> Cow<'static, str> {
assert_eq!(num, 0);
"destination".into()
}
fn image(&self, num: usize) -> &ImageAccess {
assert_eq!(num, 0);
self.source.as_ref().unwrap()
}
fn image_name(&self, num: usize) -> Cow<'static, str> {
assert_eq!(num, 0);
"source".into()
}
}
self.commands.lock().unwrap().commands.push(Box::new(Cmd {
@ -1278,6 +1440,10 @@ impl<P> SyncCommandBufferBuilder<P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdDispatch"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.dispatch(self.dimensions);
}
@ -1307,6 +1473,10 @@ impl<P> SyncCommandBufferBuilder<P> {
impl<P, B> Command<P> for Cmd<B>
where B: BufferAccess + Send + Sync + 'static
{
fn name(&self) -> &'static str {
"vkCmdDispatchIndirect"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.dispatch_indirect(&self.buffer);
}
@ -1328,6 +1498,11 @@ impl<P> SyncCommandBufferBuilder<P> {
assert_eq!(num, 0);
&self.buffer
}
fn buffer_name(&self, num: usize) -> Cow<'static, str> {
assert_eq!(num, 0);
"indirect buffer".into()
}
}
self.commands
@ -1363,6 +1538,10 @@ impl<P> SyncCommandBufferBuilder<P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdDraw"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.draw(self.vertex_count,
self.instance_count,
@ -1397,6 +1576,10 @@ impl<P> SyncCommandBufferBuilder<P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdDrawIndexed"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.draw_indexed(self.index_count,
self.instance_count,
@ -1434,6 +1617,10 @@ impl<P> SyncCommandBufferBuilder<P> {
impl<P, B> Command<P> for Cmd<B>
where B: BufferAccess + Send + Sync + 'static
{
fn name(&self) -> &'static str {
"vkCmdDrawIndirect"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.draw_indirect(&self.buffer, self.draw_count, self.stride);
}
@ -1455,6 +1642,11 @@ impl<P> SyncCommandBufferBuilder<P> {
assert_eq!(num, 0);
&self.buffer
}
fn buffer_name(&self, num: usize) -> Cow<'static, str> {
assert_eq!(num, 0);
"indirect buffer".into()
}
}
self.commands.lock().unwrap().commands.push(Box::new(Cmd {
@ -1493,6 +1685,10 @@ impl<P> SyncCommandBufferBuilder<P> {
impl<P, B> Command<P> for Cmd<B>
where B: BufferAccess + Send + Sync + 'static
{
fn name(&self) -> &'static str {
"vkCmdDrawIndexedIndirect"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.draw_indexed_indirect(&self.buffer, self.draw_count, self.stride);
}
@ -1514,6 +1710,11 @@ impl<P> SyncCommandBufferBuilder<P> {
assert_eq!(num, 0);
&self.buffer
}
fn buffer_name(&self, num: usize) -> Cow<'static, str> {
assert_eq!(num, 0);
"indirect buffer".into()
}
}
self.commands.lock().unwrap().commands.push(Box::new(Cmd {
@ -1543,6 +1744,10 @@ impl<P> SyncCommandBufferBuilder<P> {
struct Cmd;
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdEndRenderPass"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.end_render_pass();
}
@ -1552,7 +1757,10 @@ impl<P> SyncCommandBufferBuilder<P> {
}
}
self.commands.lock().unwrap().commands.push(Box::new(Cmd));
let mut cmd_lock = self.commands.lock().unwrap();
cmd_lock.commands.push(Box::new(Cmd));
debug_assert!(cmd_lock.latest_render_pass_enter.is_some());
cmd_lock.latest_render_pass_enter = None;
}
/// Starts the process of executing secondary command buffers. Returns an intermediate struct
@ -1579,6 +1787,10 @@ impl<P> SyncCommandBufferBuilder<P> {
impl<P, B> Command<P> for Cmd<B>
where B: BufferAccess + Send + Sync + 'static
{
fn name(&self) -> &'static str {
"vkCmdFillBuffer"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.fill_buffer(&self.buffer, self.data);
}
@ -1600,6 +1812,10 @@ impl<P> SyncCommandBufferBuilder<P> {
assert_eq!(num, 0);
&self.buffer
}
fn buffer_name(&self, num: usize) -> Cow<'static, str> {
"destination".into()
}
}
self.commands
@ -1631,6 +1847,10 @@ impl<P> SyncCommandBufferBuilder<P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdNextSubpass"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.next_subpass(self.subpass_contents);
}
@ -1665,6 +1885,10 @@ impl<P> SyncCommandBufferBuilder<P> {
impl<P, Pl> Command<P> for Cmd<Pl>
where Pl: PipelineLayoutAbstract + Send + Sync + 'static
{
fn name(&self) -> &'static str {
"vkCmdPushConstants"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.push_constants::<_, [u8]>(&self.pipeline_layout,
self.stages,
@ -1709,6 +1933,10 @@ impl<P> SyncCommandBufferBuilder<P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdResetEvent"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.reset_event(&self.event, self.stages);
}
@ -1736,6 +1964,10 @@ impl<P> SyncCommandBufferBuilder<P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdSetBlendConstants"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.set_blend_constants(self.constants);
}
@ -1762,6 +1994,10 @@ impl<P> SyncCommandBufferBuilder<P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdSetDepthBias"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.set_depth_bias(self.constant_factor, self.clamp, self.slope_factor);
}
@ -1787,6 +2023,10 @@ impl<P> SyncCommandBufferBuilder<P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdSetDepthBounds"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.set_depth_bounds(self.min, self.max);
}
@ -1812,6 +2052,10 @@ impl<P> SyncCommandBufferBuilder<P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdSetEvent"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.set_event(&self.event, self.stages);
}
@ -1839,6 +2083,10 @@ impl<P> SyncCommandBufferBuilder<P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdSetLineWidth"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.set_line_width(self.line_width);
}
@ -1872,6 +2120,10 @@ impl<P> SyncCommandBufferBuilder<P> {
impl<P, I> Command<P> for Cmd<I>
where I: Iterator<Item = Scissor>
{
fn name(&self) -> &'static str {
"vkCmdSetScissor"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.set_scissor(self.first_scissor, self.scissors.take().unwrap());
}
@ -1902,6 +2154,10 @@ impl<P> SyncCommandBufferBuilder<P> {
impl<P, I> Command<P> for Cmd<I>
where I: Iterator<Item = Viewport>
{
fn name(&self) -> &'static str {
"vkCmdSetViewport"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.set_viewport(self.first_viewport, self.viewports.take().unwrap());
}
@ -1932,6 +2188,10 @@ impl<P> SyncCommandBufferBuilder<P> {
where B: BufferAccess + Send + Sync + 'static,
D: Send + Sync + 'static
{
fn name(&self) -> &'static str {
"vkCmdUpdateBuffer"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.update_buffer(&self.buffer, &self.data);
}
@ -1953,6 +2213,10 @@ impl<P> SyncCommandBufferBuilder<P> {
assert_eq!(num, 0);
&self.buffer
}
fn buffer_name(&self, num: usize) -> Cow<'static, str> {
"destination".into()
}
}
self.commands
@ -2017,6 +2281,10 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> {
where Pl: PipelineLayoutAbstract,
I: Iterator<Item = u32>
{
fn name(&self) -> &'static str {
"vkCmdBindDescriptorSets"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.bind_descriptor_sets(self.graphics,
&self.pipeline_layout,
@ -2028,12 +2296,119 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> {
fn into_final_command(self: Box<Self>) -> Box<FinalCommand + Send + Sync> {
struct Fin(SmallVec<[Box<DescriptorSet + Send + Sync>; 12]>);
impl FinalCommand for Fin {
/* TODO: implement buffer() and image() */
fn buffer(&self, mut num: usize) -> &BufferAccess {
for set in self.0.iter() {
if let Some(buf) = set.buffer(num) {
return buf.0;
}
num -= set.num_buffers();
}
panic!()
}
fn image(&self, mut num: usize) -> &ImageAccess {
for set in self.0.iter() {
if let Some(img) = set.image(num) {
return img.0.parent();
}
num -= set.num_images();
}
panic!()
}
}
Box::new(Fin(self.inner))
}
fn buffer(&self, mut num: usize) -> &BufferAccess {
for set in self.inner.iter() {
if let Some(buf) = set.buffer(num) {
return buf.0;
}
num -= set.num_buffers();
}
panic!()
}
fn buffer_name(&self, mut num: usize) -> Cow<'static, str> {
for (set_num, set) in self.inner.iter().enumerate() {
if let Some(buf) = set.buffer(num) {
return format!("Buffer bound to descriptor {} of set {}", buf.1, set_num).into();
}
num -= set.num_buffers();
}
panic!()
}
fn image(&self, mut num: usize) -> &ImageAccess {
for set in self.inner.iter() {
if let Some(img) = set.image(num) {
return img.0.parent();
}
num -= set.num_images();
}
panic!()
}
fn image_name(&self, mut num: usize) -> Cow<'static, str> {
for (set_num, set) in self.inner.iter().enumerate() {
if let Some(img) = set.image(num) {
return format!("Image bound to descriptor {} of set {}", img.1, set_num).into();
}
num -= set.num_images();
}
panic!()
}
}
let all_buffers = {
let mut all_buffers = Vec::new();
for ds in self.inner.iter() {
for buf_num in 0 .. ds.num_buffers() {
let desc = ds.descriptor(ds.buffer(buf_num).unwrap().1 as usize).unwrap();
let write = !desc.readonly;
let (stages, access) = desc.pipeline_stages_and_access();
all_buffers.push((write, stages, access));
}
}
all_buffers
};
let all_images = {
let mut all_images = Vec::new();
for ds in self.inner.iter() {
for img_num in 0 .. ds.num_images() {
let (image_view, desc_num) = ds.image(img_num).unwrap();
let desc = ds.descriptor(desc_num as usize).unwrap();
let write = !desc.readonly;
let (stages, access) = desc.pipeline_stages_and_access();
let mut ignore_me_hack = false;
let layout = match desc.ty {
DescriptorDescTy::CombinedImageSampler(_) => {
image_view.descriptor_set_combined_image_sampler_layout()
},
DescriptorDescTy::Image(ref img) => {
if img.sampled {
image_view.descriptor_set_sampled_image_layout()
} else {
image_view.descriptor_set_storage_image_layout()
}
},
DescriptorDescTy::InputAttachment { .. } => {
// FIXME: This is tricky. Since we read from the input attachment
// and this input attachment is being written in an earlier pass,
// vulkano will think that it needs to put a pipeline barrier and will
// return a `Conflict` error. For now as a work-around we simply ignore
// input attachments.
ignore_me_hack = true;
image_view.descriptor_set_input_attachment_layout()
},
_ => panic!("Tried to bind an image to a non-image descriptor")
};
all_images.push((write, stages, access, layout, ignore_me_hack));
}
}
all_images
};
self.builder
.commands
.lock()
@ -2047,7 +2422,22 @@ impl<'b, P> SyncCommandBufferBuilderBindDescriptorSets<'b, P> {
dynamic_offsets: Some(dynamic_offsets),
}));
// FIXME: add resources
for (n, (write, stages, access)) in all_buffers.into_iter().enumerate() {
self.builder
.prev_cmd_resource(KeyTy::Buffer,
n, write, stages, access,
ImageLayout::Undefined,
ImageLayout::Undefined)?;
}
for (n, (write, stages, access, layout, ignore_me_hack)) in all_images.into_iter().enumerate() {
if ignore_me_hack { continue; }
self.builder
.prev_cmd_resource(KeyTy::Image,
n, write, stages, access,
layout,
layout)?;
}
Ok(())
}
@ -2079,6 +2469,10 @@ impl<'a, P> SyncCommandBufferBuilderBindVertexBuffer<'a, P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdBindVertexBuffers"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.bind_vertex_buffers(self.first_binding, self.inner.take().unwrap());
}
@ -2096,6 +2490,10 @@ impl<'a, P> SyncCommandBufferBuilderBindVertexBuffer<'a, P> {
fn buffer(&self, num: usize) -> &BufferAccess {
&self.buffers[num]
}
fn buffer_name(&self, num: usize) -> Cow<'static, str> {
format!("Buffer #{}", num).into()
}
}
let num_buffers = self.buffers.len();
@ -2158,6 +2556,10 @@ impl<'a, P> SyncCommandBufferBuilderExecuteCommands<'a, P> {
}
impl<P> Command<P> for Cmd {
fn name(&self) -> &'static str {
"vkCmdExecuteCommands"
}
unsafe fn send(&mut self, out: &mut UnsafeCommandBufferBuilder<P>) {
out.execute_commands(self.inner.take().unwrap());
}

View File

@ -43,6 +43,8 @@
use format::Format;
use image::Dimensions;
use sync::AccessFlagBits;
use sync::PipelineStages;
use std::cmp;
use std::ops::BitOr;
use vk;
@ -100,6 +102,56 @@ impl DescriptorDesc {
readonly: self.readonly && other.readonly,
})
}
/// Returns the pipeline stages and access flags corresponding to the usage of this descriptor.
///
/// # Panic
///
/// Panicks if the type if `Sampler`.
///
pub fn pipeline_stages_and_access(&self) -> (PipelineStages, AccessFlagBits) {
let stages: PipelineStages = self.stages.into();
let access = match self.ty {
DescriptorDescTy::Sampler => panic!(),
DescriptorDescTy::CombinedImageSampler(_) | DescriptorDescTy::Image(_) => {
AccessFlagBits {
shader_read: true,
shader_write: !self.readonly,
.. AccessFlagBits::none()
}
},
DescriptorDescTy::TexelBuffer { .. } => {
AccessFlagBits {
shader_read: true,
shader_write: !self.readonly,
.. AccessFlagBits::none()
}
},
DescriptorDescTy::InputAttachment { .. } => {
AccessFlagBits {
input_attachment_read: true,
.. AccessFlagBits::none()
}
},
DescriptorDescTy::Buffer(ref buf) => {
if buf.storage {
AccessFlagBits {
shader_read: true,
shader_write: !self.readonly,
.. AccessFlagBits::none()
}
} else {
AccessFlagBits {
uniform_read: true,
.. AccessFlagBits::none()
}
}
},
};
(stages, access)
}
}
/// Describes the content and layout of each array element of a descriptor.
@ -472,6 +524,21 @@ impl BitOr for ShaderStages {
}
}
impl From<ShaderStages> for PipelineStages {
#[inline]
fn from(stages: ShaderStages) -> PipelineStages {
PipelineStages {
vertex_shader: stages.vertex,
tessellation_control_shader: stages.tessellation_control,
tessellation_evaluation_shader: stages.tessellation_evaluation,
geometry_shader: stages.geometry,
fragment_shader: stages.fragment,
compute_shader: stages.compute,
.. PipelineStages::none()
}
}
}
#[doc(hidden)]
impl Into<vk::ShaderStageFlags> for ShaderStages {
#[inline]

View File

@ -7,12 +7,9 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
use buffer::BufferAccess;
use descriptor::descriptor::DescriptorDesc;
use descriptor::descriptor_set::DescriptorSet;
use descriptor::descriptor_set::DescriptorSetDesc;
use image::ImageAccess;
use std::iter;
/// A collection of descriptor set objects.
pub unsafe trait DescriptorSetsCollection {
@ -21,18 +18,14 @@ pub unsafe trait DescriptorSetsCollection {
/// Returns the number of descriptors in the set. Includes possibly empty descriptors.
///
/// Returns `None` if the set is out of range.
// TODO: remove ; user should just use `into_vec` instead
fn num_bindings_in_set(&self, set: usize) -> Option<usize>;
/// Returns the descriptor for the given binding of the given set.
///
/// Returns `None` if out of range.
// TODO: remove ; user should just use `into_vec` instead
fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc>;
/// Returns the list of buffers used by this descriptor set. Includes buffer views.
fn buffers_list<'a>(&'a self) -> Box<Iterator<Item = &'a BufferAccess> + 'a>;
/// Returns the list of images used by this descriptor set. Includes image views.
fn images_list<'a>(&'a self) -> Box<Iterator<Item = &'a ImageAccess> + 'a>;
}
unsafe impl DescriptorSetsCollection for () {
@ -50,16 +43,6 @@ unsafe impl DescriptorSetsCollection for () {
fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc> {
None
}
#[inline]
fn buffers_list<'a>(&'a self) -> Box<Iterator<Item = &'a BufferAccess> + 'a> {
Box::new(iter::empty())
}
#[inline]
fn images_list<'a>(&'a self) -> Box<Iterator<Item = &'a ImageAccess> + 'a> {
Box::new(iter::empty())
}
}
unsafe impl<T> DescriptorSetsCollection for T
@ -85,16 +68,6 @@ unsafe impl<T> DescriptorSetsCollection for T
_ => None,
}
}
#[inline]
fn buffers_list<'a>(&'a self) -> Box<Iterator<Item = &'a BufferAccess> + 'a> {
DescriptorSet::buffers_list(self)
}
#[inline]
fn images_list<'a>(&'a self) -> Box<Iterator<Item = &'a ImageAccess> + 'a> {
DescriptorSet::images_list(self)
}
}
macro_rules! impl_collection {
@ -158,32 +131,6 @@ macro_rules! impl_collection {
None
}
#[inline]
fn buffers_list<'a>(&'a self) -> Box<Iterator<Item = &'a BufferAccess> + 'a> {
#![allow(non_snake_case)]
let &(ref first, $(ref $others,)*) = self;
let mut output = Vec::new();
output.extend(first.buffers_list());
$(
output.extend($others.buffers_list());
)*
Box::new(output.into_iter())
}
#[inline]
fn images_list<'a>(&'a self) -> Box<Iterator<Item = &'a ImageAccess> + 'a> {
#![allow(non_snake_case)]
let &(ref first, $(ref $others,)*) = self;
let mut output = Vec::new();
output.extend(first.images_list());
$(
output.extend($others.images_list());
)*
Box::new(output.into_iter())
}
}
impl_collection!($($others),+);

View File

@ -38,7 +38,7 @@
use SafeDeref;
use buffer::BufferAccess;
use descriptor::descriptor::DescriptorDesc;
use image::ImageAccess;
use image::ImageViewAccess;
pub use self::collection::DescriptorSetsCollection;
pub use self::persistent::PersistentDescriptorSet;
@ -78,13 +78,23 @@ pub unsafe trait DescriptorSet: DescriptorSetDesc {
/// Returns the inner `UnsafeDescriptorSet`.
fn inner(&self) -> &UnsafeDescriptorSet;
/// Returns the list of buffers used by this descriptor set. Includes buffer views.
// TODO: meh for boxing
fn buffers_list<'a>(&'a self) -> Box<Iterator<Item = &'a BufferAccess> + 'a>;
/// Returns the number of buffers within this descriptor set.
fn num_buffers(&self) -> usize;
/// Returns the list of images used by this descriptor set. Includes image views.
// TODO: meh for boxing
fn images_list<'a>(&'a self) -> Box<Iterator<Item = &'a ImageAccess> + 'a>;
/// Returns the `index`th buffer of this descriptor set, or `None` if out of range. Also
/// returns the index of the descriptor that uses this buffer.
///
/// The valid range is between 0 and `num_buffers()`.
fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)>;
/// Returns the number of images within this descriptor set.
fn num_images(&self) -> usize;
/// Returns the `index`th image of this descriptor set, or `None` if out of range. Also returns
/// the index of the descriptor that uses this image.
///
/// The valid range is between 0 and `num_images()`.
fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)>;
}
unsafe impl<T> DescriptorSet for T
@ -97,13 +107,23 @@ unsafe impl<T> DescriptorSet for T
}
#[inline]
fn buffers_list<'a>(&'a self) -> Box<Iterator<Item = &'a BufferAccess> + 'a> {
(**self).buffers_list()
fn num_buffers(&self) -> usize {
(**self).num_buffers()
}
#[inline]
fn images_list<'a>(&'a self) -> Box<Iterator<Item = &'a ImageAccess> + 'a> {
(**self).images_list()
fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> {
(**self).buffer(index)
}
#[inline]
fn num_images(&self) -> usize {
(**self).num_images()
}
#[inline]
fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> {
(**self).image(index)
}
}

View File

@ -31,12 +31,8 @@ use descriptor::pipeline_layout::PipelineLayoutAbstract;
use device::Device;
use device::DeviceOwned;
use format::Format;
use image::ImageAccess;
use image::ImageLayout;
use image::ImageViewAccess;
use sampler::Sampler;
use sync::AccessFlagBits;
use sync::PipelineStages;
use OomError;
use VulkanObject;
@ -58,21 +54,23 @@ use VulkanObject;
///
/// # Example
// TODO:
pub struct PersistentDescriptorSet<R, P = StdDescriptorPoolAlloc> {
pub struct PersistentDescriptorSet<L, R, P = StdDescriptorPoolAlloc> {
inner: P,
resources: R,
pipeline_layout: L,
set_id: usize,
layout: Arc<UnsafeDescriptorSetLayout>
}
impl PersistentDescriptorSet<()> {
impl<L> PersistentDescriptorSet<L, ()> {
/// Starts the process of building a `PersistentDescriptorSet`. Returns a builder.
///
/// # Panic
///
/// - Panics if the set id is out of range.
///
pub fn start<Pl>(layout: Pl, set_id: usize) -> PersistentDescriptorSetBuilder<Pl, ()>
where Pl: PipelineLayoutAbstract
pub fn start(layout: L, set_id: usize) -> PersistentDescriptorSetBuilder<L, ()>
where L: PipelineLayoutAbstract
{
assert!(layout.num_sets() > set_id);
@ -88,33 +86,48 @@ impl PersistentDescriptorSet<()> {
}
}
unsafe impl<R, P> DescriptorSet for PersistentDescriptorSet<R, P> where P: DescriptorPoolAlloc {
unsafe impl<L, R, P> DescriptorSet for PersistentDescriptorSet<L, R, P>
where L: PipelineLayoutAbstract,
P: DescriptorPoolAlloc,
R: PersistentDescriptorSetResources
{
#[inline]
fn inner(&self) -> &UnsafeDescriptorSet {
self.inner.inner()
}
#[inline]
fn buffers_list<'a>(&'a self) -> Box<Iterator<Item = &'a BufferAccess> + 'a> {
unimplemented!()
fn num_buffers(&self) -> usize {
self.resources.num_buffers()
}
#[inline]
fn images_list<'a>(&'a self) -> Box<Iterator<Item = &'a ImageAccess> + 'a> {
unimplemented!()
fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> {
self.resources.buffer(index)
}
#[inline]
fn num_images(&self) -> usize {
self.resources.num_images()
}
#[inline]
fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> {
self.resources.image(index)
}
}
// TODO: is DescriptorSetDesc really necessary?
unsafe impl<R, P> DescriptorSetDesc for PersistentDescriptorSet<R, P> {
unsafe impl<L, R, P> DescriptorSetDesc for PersistentDescriptorSet<L, R, P>
where L: PipelineLayoutAbstract
{
#[inline]
fn num_bindings(&self) -> usize {
unimplemented!() // FIXME:
self.pipeline_layout.num_bindings_in_set(self.set_id).unwrap()
}
#[inline]
fn descriptor(&self, binding: usize) -> Option<DescriptorDesc> {
unimplemented!() // FIXME:
self.pipeline_layout.descriptor(self.set_id, binding)
}
}
@ -154,7 +167,7 @@ impl<L, R> PersistentDescriptorSetBuilder<L, R>
{
/// Builds a `PersistentDescriptorSet` from the builder.
#[inline]
pub fn build(self) -> Result<PersistentDescriptorSet<R, StdDescriptorPoolAlloc>, PersistentDescriptorSetBuildError> {
pub fn build(self) -> Result<PersistentDescriptorSet<L, R, StdDescriptorPoolAlloc>, PersistentDescriptorSetBuildError> {
let pool = Device::standard_descriptor_pool(self.layout.device());
self.build_with_pool(pool)
}
@ -166,7 +179,7 @@ impl<L, R> PersistentDescriptorSetBuilder<L, R>
/// Panics if the pool doesn't have the same device as the pipeline layout.
///
pub fn build_with_pool<P>(self, pool: P)
-> Result<PersistentDescriptorSet<R, P::Alloc>, PersistentDescriptorSetBuildError>
-> Result<PersistentDescriptorSet<L, R, P::Alloc>, PersistentDescriptorSetBuildError>
where P: DescriptorPool
{
assert_eq!(self.layout.device().internal_object(),
@ -196,6 +209,8 @@ impl<L, R> PersistentDescriptorSetBuilder<L, R>
Ok(PersistentDescriptorSet {
inner: set,
resources: self.resources,
pipeline_layout: self.layout,
set_id: self.set_id,
layout: set_layout,
})
}
@ -419,9 +434,7 @@ impl<L, R> PersistentDescriptorSetBuilderArray<L, R> where L: PipelineLayoutAbst
writes: self.builder.writes,
resources: (self.builder.resources, PersistentDescriptorSetBuf {
buffer: buffer,
write: !readonly,
stage: PipelineStages::none(), // FIXME:
access: AccessFlagBits::none(), // FIXME:
descriptor_num: self.builder.binding_id as u32,
})
},
desc: self.desc,
@ -487,9 +500,7 @@ impl<L, R> PersistentDescriptorSetBuilderArray<L, R> where L: PipelineLayoutAbst
writes: self.builder.writes,
resources: (self.builder.resources, PersistentDescriptorSetBufView {
view: view,
write: !readonly,
stage: PipelineStages::none(), // FIXME:
access: AccessFlagBits::none(), // FIXME:
descriptor_num: self.builder.binding_id as u32,
})
},
desc: self.desc,
@ -581,14 +592,7 @@ impl<L, R> PersistentDescriptorSetBuilderArray<L, R> where L: PipelineLayoutAbst
writes: self.builder.writes,
resources: (self.builder.resources, PersistentDescriptorSetImg {
image: image_view,
write: !readonly,
first_mipmap: 0, // FIXME:
num_mipmaps: 1, // FIXME:
first_layer: 0, // FIXME:
num_layers: 1, // FIXME:
layout: ImageLayout::General, // FIXME:
stage: PipelineStages::none(), // FIXME:
access: AccessFlagBits::none(), // FIXME:
descriptor_num: self.builder.binding_id as u32,
})
},
desc: self.desc,
@ -646,14 +650,7 @@ impl<L, R> PersistentDescriptorSetBuilderArray<L, R> where L: PipelineLayoutAbst
writes: self.builder.writes,
resources: ((self.builder.resources, PersistentDescriptorSetImg {
image: image_view,
write: !readonly,
first_mipmap: 0, // FIXME:
num_mipmaps: 1, // FIXME:
first_layer: 0, // FIXME:
num_layers: 1, // FIXME:
layout: ImageLayout::General, // FIXME:
stage: PipelineStages::none(), // FIXME:
access: AccessFlagBits::none(), // FIXME:
descriptor_num: self.builder.binding_id as u32,
}), PersistentDescriptorSetSampler {
sampler: sampler,
}),
@ -772,12 +769,70 @@ fn image_match_desc<I>(image_view: &I, desc: &DescriptorImageDesc)
Ok(())
}
pub unsafe trait PersistentDescriptorSetResources {
fn num_buffers(&self) -> usize;
fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)>;
fn num_images(&self) -> usize;
fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)>;
}
unsafe impl PersistentDescriptorSetResources for () {
#[inline]
fn num_buffers(&self) -> usize {
0
}
#[inline]
fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> {
None
}
#[inline]
fn num_images(&self) -> usize {
0
}
#[inline]
fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> {
None
}
}
/// Internal object related to the `PersistentDescriptorSet` system.
pub struct PersistentDescriptorSetBuf<B> {
buffer: B,
write: bool,
stage: PipelineStages,
access: AccessFlagBits,
descriptor_num: u32,
}
unsafe impl<R, B> PersistentDescriptorSetResources for (R, PersistentDescriptorSetBuf<B>)
where R: PersistentDescriptorSetResources,
B: BufferAccess,
{
#[inline]
fn num_buffers(&self) -> usize {
self.0.num_buffers() + 1
}
#[inline]
fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> {
if let Some(buf) = self.0.buffer(index) {
Some(buf)
} else if index == self.0.num_buffers() {
Some((&self.1.buffer, self.1.descriptor_num))
} else {
None
}
}
#[inline]
fn num_images(&self) -> usize {
self.0.num_images()
}
#[inline]
fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> {
self.0.image(index)
}
}
/// Internal object related to the `PersistentDescriptorSet` system.
@ -785,22 +840,75 @@ pub struct PersistentDescriptorSetBufView<V>
where V: BufferViewRef
{
view: V,
write: bool,
stage: PipelineStages,
access: AccessFlagBits,
descriptor_num: u32,
}
unsafe impl<R, V> PersistentDescriptorSetResources for (R, PersistentDescriptorSetBufView<V>)
where R: PersistentDescriptorSetResources,
V: BufferViewRef,
{
#[inline]
fn num_buffers(&self) -> usize {
self.0.num_buffers() + 1
}
#[inline]
fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> {
if let Some(buf) = self.0.buffer(index) {
Some(buf)
} else if index == self.0.num_buffers() {
Some((self.1.view.view().buffer(), self.1.descriptor_num))
} else {
None
}
}
#[inline]
fn num_images(&self) -> usize {
self.0.num_images()
}
#[inline]
fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> {
self.0.image(index)
}
}
/// Internal object related to the `PersistentDescriptorSet` system.
pub struct PersistentDescriptorSetImg<I> {
image: I,
write: bool,
first_mipmap: u32,
num_mipmaps: u32,
first_layer: u32,
num_layers: u32,
layout: ImageLayout,
stage: PipelineStages,
access: AccessFlagBits,
descriptor_num: u32,
}
unsafe impl<R, I> PersistentDescriptorSetResources for (R, PersistentDescriptorSetImg<I>)
where R: PersistentDescriptorSetResources,
I: ImageViewAccess,
{
#[inline]
fn num_buffers(&self) -> usize {
self.0.num_buffers()
}
#[inline]
fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> {
self.0.buffer(index)
}
#[inline]
fn num_images(&self) -> usize {
self.0.num_images() + 1
}
#[inline]
fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> {
if let Some(img) = self.0.image(index) {
Some(img)
} else if index == self.0.num_images() {
Some((&self.1.image, self.1.descriptor_num))
} else {
None
}
}
}
/// Internal object related to the `PersistentDescriptorSet` system.
@ -808,6 +916,30 @@ pub struct PersistentDescriptorSetSampler {
sampler: Arc<Sampler>,
}
unsafe impl<R> PersistentDescriptorSetResources for (R, PersistentDescriptorSetSampler)
where R: PersistentDescriptorSetResources
{
#[inline]
fn num_buffers(&self) -> usize {
self.0.num_buffers()
}
#[inline]
fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> {
self.0.buffer(index)
}
#[inline]
fn num_images(&self) -> usize {
self.0.num_images()
}
#[inline]
fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> {
self.0.image(index)
}
}
/// Error related to the persistent descriptor set.
#[derive(Debug, Clone)]
pub enum PersistentDescriptorSetError {

View File

@ -28,7 +28,6 @@ use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
use descriptor::pipeline_layout::PipelineLayoutAbstract;
use device::Device;
use device::DeviceOwned;
use image::ImageAccess;
use image::ImageLayout;
use image::ImageViewAccess;
use sampler::Sampler;
@ -78,13 +77,35 @@ unsafe impl<R, P> DescriptorSet for SimpleDescriptorSet<R, P>
}
#[inline]
fn buffers_list<'a>(&'a self) -> Box<Iterator<Item = &'a BufferAccess> + 'a> {
unimplemented!()
fn num_buffers(&self) -> usize {
// Note that since the simple descriptor set is deprecated, and since buffers and images
// within descriptor sets weren't supported before its deprecation, we just return a dummy
// value.
0
}
#[inline]
fn images_list<'a>(&'a self) -> Box<Iterator<Item = &'a ImageAccess> + 'a> {
unimplemented!()
fn buffer(&self, index: usize) -> Option<(&BufferAccess, u32)> {
// Note that since the simple descriptor set is deprecated, and since buffers and images
// within descriptor sets weren't supported before its deprecation, we just return a dummy
// value.
None
}
#[inline]
fn num_images(&self) -> usize {
// Note that since the simple descriptor set is deprecated, and since buffers and images
// within descriptor sets weren't supported before its deprecation, we just return a dummy
// value.
0
}
#[inline]
fn image(&self, index: usize) -> Option<(&ImageViewAccess, u32)> {
// Note that since the simple descriptor set is deprecated, and since buffers and images
// within descriptor sets weren't supported before its deprecation, we just return a dummy
// value.
None
}
}