mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-18 18:12:32 +00:00
Add documentation to the update buffer and empty modules
This commit is contained in:
parent
3ca46f2348
commit
0e887544e8
@ -85,22 +85,26 @@ unsafe impl<P> StdCommandsList for PrimaryCbBuilder<P> where P: CommandPool {
|
||||
None
|
||||
}
|
||||
|
||||
unsafe fn raw_build<I, F>(self, additional_elements: F, transitions: I,
|
||||
final_transitions: PipelineBarrierBuilder) -> Self::Output
|
||||
unsafe fn raw_build<I, F>(self, additional_elements: F, barriers: I,
|
||||
final_barrier: PipelineBarrierBuilder) -> Self::Output
|
||||
where F: FnOnce(&mut UnsafeCommandBufferBuilder<Self::Pool>),
|
||||
I: Iterator<Item = (usize, PipelineBarrierBuilder)>
|
||||
{
|
||||
let mut pipeline_barrier = PipelineBarrierBuilder::new();
|
||||
for (_, transition) in transitions {
|
||||
pipeline_barrier.merge(transition);
|
||||
}
|
||||
|
||||
let kind = Kind::Primary::<EmptySinglePassRenderPass, EmptySinglePassRenderPass>;
|
||||
let mut cb = UnsafeCommandBufferBuilder::new(self.pool, kind,
|
||||
self.flags).unwrap(); // TODO: handle
|
||||
self.flags).unwrap(); // TODO: handle error
|
||||
|
||||
// Since we're at the start of the command buffer, there's no need wonder when to add the
|
||||
// barriers. We have no choice but to add them immediately.
|
||||
let mut pipeline_barrier = PipelineBarrierBuilder::new();
|
||||
for (_, barrier) in barriers {
|
||||
pipeline_barrier.merge(barrier);
|
||||
}
|
||||
cb.pipeline_barrier(pipeline_barrier);
|
||||
|
||||
// Then add the rest.
|
||||
additional_elements(&mut cb);
|
||||
cb.pipeline_barrier(final_transitions);
|
||||
cb.pipeline_barrier(final_barrier);
|
||||
|
||||
PrimaryCb {
|
||||
cb: cb.build().unwrap(), // TODO: handle error
|
||||
@ -129,7 +133,9 @@ unsafe impl<P> CommandBuffer for PrimaryCb<P> where P: CommandPool {
|
||||
Self::SemaphoresSignalIterator>
|
||||
where F: FnMut() -> Arc<Fence>
|
||||
{
|
||||
// TODO: must handle SimultaneousUse and Once flags
|
||||
// TODO: Must handle non-SimultaneousUse and Once flags ; for now the `SimultaneousUse`
|
||||
// flag is mandatory, so there's no safety issue. However it will need to be handled
|
||||
// before allowing other flags to be used.
|
||||
|
||||
SubmitInfo {
|
||||
semaphores_wait: iter::empty(),
|
||||
|
@ -93,14 +93,14 @@ pub unsafe trait StdCommandsList {
|
||||
/// This function accepts additional arguments that will customize the output:
|
||||
///
|
||||
/// - `additional_elements` is a closure that must be called on the command buffer builder
|
||||
/// after it has finished building and before `final_transitions` are added.
|
||||
/// - `transitions` is a list of pipeline barriers accompanied by a command number. The
|
||||
/// after it has finished building and before `final_barrier` are added.
|
||||
/// - `barriers` is a list of pipeline barriers accompanied by a command number. The
|
||||
/// pipeline barrier must happen after the given command number. Usually you want all the
|
||||
/// the command numbers to be inferior to `num_commands`.
|
||||
/// - `final_transitions` is a pipeline barrier that must be added at the end of the
|
||||
/// - `final_barrier` is a pipeline barrier that must be added at the end of the
|
||||
/// command buffer builder.
|
||||
unsafe fn raw_build<I, F>(self, additional_elements: F, transitions: I,
|
||||
final_transitions: PipelineBarrierBuilder) -> Self::Output
|
||||
unsafe fn raw_build<I, F>(self, additional_elements: F, barriers: I,
|
||||
final_barrier: PipelineBarrierBuilder) -> Self::Output
|
||||
where F: FnOnce(&mut UnsafeCommandBufferBuilder<Self::Pool>),
|
||||
I: Iterator<Item = (usize, PipelineBarrierBuilder)>;
|
||||
}
|
||||
|
@ -32,12 +32,20 @@ use sync::Fence;
|
||||
use sync::PipelineStages;
|
||||
use sync::Semaphore;
|
||||
|
||||
pub struct UpdateCommand<'a, L, B, D: ?Sized> where B: TrackedBuffer, L: StdCommandsList, D: 'static {
|
||||
/// Wraps around a commands list and adds an update buffer command at the end of it.
|
||||
pub struct UpdateCommand<'a, L, B, D: ?Sized>
|
||||
where B: TrackedBuffer, L: StdCommandsList, D: 'static
|
||||
{
|
||||
// Parent commands list.
|
||||
previous: L,
|
||||
// The buffer to update.
|
||||
buffer: B,
|
||||
// Current state of the buffer to update, or `None` if it has been extracted.
|
||||
buffer_state: Option<B::CommandListState>,
|
||||
// The data to write to the buffer.
|
||||
data: &'a D,
|
||||
transition: Option<PipelineBarrierRequest>,
|
||||
// Pipeline barrier to perform before this command.
|
||||
barrier: Option<PipelineBarrierRequest>,
|
||||
}
|
||||
|
||||
impl<'a, L, B, D: ?Sized> UpdateCommand<'a, L, B, D>
|
||||
@ -45,26 +53,23 @@ impl<'a, L, B, D: ?Sized> UpdateCommand<'a, L, B, D>
|
||||
L: StdCommandsList + OutsideRenderPass,
|
||||
D: Copy + 'static,
|
||||
{
|
||||
/// See the documentation of the `update_buffer` method.
|
||||
pub fn new(mut previous: L, buffer: B, data: &'a D) -> UpdateCommand<'a, L, B, D> {
|
||||
let stage = PipelineStages {
|
||||
transfer: true,
|
||||
.. PipelineStages::none()
|
||||
};
|
||||
// Determining the new state of the buffer, and the optional pipeline barrier to add
|
||||
// before our command in the final output.
|
||||
let (state, barrier) = unsafe {
|
||||
let stage = PipelineStages { transfer: true, .. PipelineStages::none() };
|
||||
let access = AccessFlagBits { transfer_write: true, .. AccessFlagBits::none() };
|
||||
|
||||
let access = AccessFlagBits {
|
||||
transfer_write: true,
|
||||
.. AccessFlagBits::none()
|
||||
};
|
||||
|
||||
let (state, transition) = unsafe {
|
||||
previous.extract_current_buffer_state(&buffer)
|
||||
.unwrap_or(buffer.initial_state())
|
||||
.transition(previous.num_commands() + 1, buffer.inner(),
|
||||
0, buffer.size(), true, stage, access)
|
||||
};
|
||||
|
||||
if let Some(ref transition) = transition {
|
||||
assert!(transition.after_command_num <= previous.num_commands());
|
||||
// Minor safety check.
|
||||
if let Some(ref barrier) = barrier {
|
||||
assert!(barrier.after_command_num <= previous.num_commands());
|
||||
}
|
||||
|
||||
UpdateCommand {
|
||||
@ -72,7 +77,7 @@ impl<'a, L, B, D: ?Sized> UpdateCommand<'a, L, B, D>
|
||||
buffer: buffer,
|
||||
buffer_state: Some(state),
|
||||
data: data,
|
||||
transition: transition,
|
||||
barrier: barrier,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,54 +128,58 @@ unsafe impl<'a, L, B, D: ?Sized> StdCommandsList for UpdateCommand<'a, L, B, D>
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn raw_build<I, F>(mut self, additional_elements: F, transitions: I,
|
||||
mut final_transitions: PipelineBarrierBuilder) -> Self::Output
|
||||
unsafe fn raw_build<I, F>(mut self, additional_elements: F, barriers: I,
|
||||
mut final_barrier: PipelineBarrierBuilder) -> Self::Output
|
||||
where F: FnOnce(&mut UnsafeCommandBufferBuilder<L::Pool>),
|
||||
I: Iterator<Item = (usize, PipelineBarrierBuilder)>
|
||||
{
|
||||
// Computing the finished state, or `None` if we don't have to manage it.
|
||||
let finished_state = match self.buffer_state.take().map(|s| s.finish()) {
|
||||
Some((s, t)) => {
|
||||
if let Some(t) = t {
|
||||
final_transitions.add_buffer_barrier_request(self.buffer.inner(), t);
|
||||
final_barrier.add_buffer_barrier_request(self.buffer.inner(), t);
|
||||
}
|
||||
Some(s)
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
// We split the transitions in two: those to apply after the actual command, and those to
|
||||
// transfer to the parent so that they are applied before the actual command.
|
||||
// We split the barriers in two: those to apply after our command, and those to
|
||||
// transfer to the parent so that they are applied before our command.
|
||||
|
||||
let my_command_num = self.num_commands();
|
||||
|
||||
// The transitions to apply immediately after our command.
|
||||
let mut transitions_to_apply = PipelineBarrierBuilder::new();
|
||||
let mut transitions = transitions.filter_map(|(after_command_num, transition)| {
|
||||
|
||||
// The barriers to transfer to the parent.
|
||||
let mut barriers = barriers.filter_map(|(after_command_num, barrier)| {
|
||||
if after_command_num >= my_command_num || !transitions_to_apply.is_empty() {
|
||||
transitions_to_apply.merge(transition);
|
||||
transitions_to_apply.merge(barrier);
|
||||
None
|
||||
} else {
|
||||
Some((after_command_num, transition))
|
||||
Some((after_command_num, barrier))
|
||||
}
|
||||
}).collect::<SmallVec<[_; 8]>>();
|
||||
|
||||
let my_transition = if let Some(my_transition) = self.transition.take() {
|
||||
// The local barrier requested by this command, or `None` if no barrier requested.
|
||||
let my_barrier = if let Some(my_barrier) = self.barrier.take() {
|
||||
let mut t = PipelineBarrierBuilder::new();
|
||||
let c_num = my_transition.after_command_num;
|
||||
t.add_buffer_barrier_request(self.buffer.inner(), my_transition);
|
||||
let c_num = my_barrier.after_command_num;
|
||||
t.add_buffer_barrier_request(self.buffer.inner(), my_barrier);
|
||||
Some((c_num, t))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let transitions = my_transition.into_iter().chain(transitions.into_iter());
|
||||
|
||||
// Passing to the parent.
|
||||
let my_buffer = self.buffer;
|
||||
let my_data = self.data;
|
||||
let parent = self.previous.raw_build(|cb| {
|
||||
cb.update_buffer(my_buffer.inner(), 0, my_buffer.size(), my_data);
|
||||
cb.pipeline_barrier(transitions_to_apply);
|
||||
additional_elements(cb);
|
||||
}, transitions, final_transitions);
|
||||
}, my_barrier.into_iter().chain(barriers.into_iter()), final_barrier);
|
||||
|
||||
UpdateCommandCb {
|
||||
previous: parent,
|
||||
@ -180,9 +189,14 @@ unsafe impl<'a, L, B, D: ?Sized> StdCommandsList for UpdateCommand<'a, L, B, D>
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps around a command buffer and adds an update buffer command at the end of it.
|
||||
pub struct UpdateCommandCb<L, B> where B: TrackedBuffer, L: StdCommandsList {
|
||||
// The previous commands.
|
||||
previous: L::Output,
|
||||
// The buffer to update.
|
||||
buffer: B,
|
||||
// The state of the buffer to update, or `None` if we don't manage it. Will be used to
|
||||
// determine which semaphores or barriers to add when submitting.
|
||||
buffer_state: Option<B::FinishedState>,
|
||||
}
|
||||
|
||||
@ -203,9 +217,11 @@ unsafe impl<L, B> CommandBuffer for UpdateCommandCb<L, B>
|
||||
Self::SemaphoresSignalIterator>
|
||||
where F: FnMut() -> Arc<Fence>
|
||||
{
|
||||
// We query the parent.
|
||||
let parent = self.previous.on_submit(queue, &mut fence);
|
||||
|
||||
let mut my_output = SubmitInfo {
|
||||
// Then build our own output that modifies the parent's.
|
||||
let mut out = SubmitInfo {
|
||||
semaphores_wait: iter::empty(), // FIXME:
|
||||
semaphores_signal: iter::empty(), // FIXME:
|
||||
pre_pipeline_barrier: parent.pre_pipeline_barrier,
|
||||
@ -216,15 +232,15 @@ unsafe impl<L, B> CommandBuffer for UpdateCommandCb<L, B>
|
||||
let submit_infos = buffer_state.on_submit(&self.buffer, queue, fence);
|
||||
|
||||
if let Some(pre) = submit_infos.pre_barrier {
|
||||
my_output.pre_pipeline_barrier.add_buffer_barrier_request(self.buffer.inner(), pre);
|
||||
out.pre_pipeline_barrier.add_buffer_barrier_request(self.buffer.inner(), pre);
|
||||
}
|
||||
|
||||
if let Some(post) = submit_infos.post_barrier {
|
||||
my_output.post_pipeline_barrier.add_buffer_barrier_request(self.buffer.inner(), post);
|
||||
out.post_pipeline_barrier.add_buffer_barrier_request(self.buffer.inner(), post);
|
||||
}
|
||||
}
|
||||
|
||||
my_output
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user