mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Transition between command buffers
This commit is contained in:
parent
879cd64b30
commit
f3cfd2e09c
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1047,6 +1047,7 @@ dependencies = [
|
||||
"gfx-backend-vulkan 0.1.0 (git+https://github.com/gfx-rs/gfx)",
|
||||
"gfx-hal 0.1.0 (git+https://github.com/gfx-rs/gfx.git)",
|
||||
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rendy-memory 0.1.0 (git+https://github.com/rustgd/rendy?rev=ce7dd7f)",
|
||||
]
|
||||
|
||||
@ -16,6 +16,7 @@ remote = ["parking_lot"]
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
lazy_static = "1.1.0"
|
||||
log = "0.4"
|
||||
parking_lot = { version = "0.6", optional = true }
|
||||
gfx-hal = { git = "https://github.com/gfx-rs/gfx" } # required by gfx-memory
|
||||
gfx-backend-empty = { git = "https://github.com/gfx-rs/gfx" }
|
||||
|
||||
@ -10,7 +10,7 @@ use hal::{self, Device};
|
||||
use hal::command::RawCommandBuffer;
|
||||
|
||||
use {
|
||||
Color, Origin3d, Stored,
|
||||
B, Color, Origin3d, Stored, BufferUsageFlags, TextureUsageFlags,
|
||||
BufferId, CommandBufferId, ComputePassId, DeviceId, RenderPassId, TextureId, TextureViewId,
|
||||
};
|
||||
use conv;
|
||||
@ -18,6 +18,7 @@ use registry::{HUB, Items, Registry};
|
||||
use track::{BufferTracker, TextureTracker};
|
||||
|
||||
use std::iter;
|
||||
use std::ops::Range;
|
||||
use std::thread::ThreadId;
|
||||
|
||||
|
||||
@ -81,8 +82,49 @@ pub struct CommandBuffer<B: hal::Backend> {
|
||||
fence: B::Fence,
|
||||
recorded_thread_id: ThreadId,
|
||||
device_id: Stored<DeviceId>,
|
||||
buffer_tracker: BufferTracker,
|
||||
texture_tracker: TextureTracker,
|
||||
pub(crate) buffer_tracker: BufferTracker,
|
||||
pub(crate) texture_tracker: TextureTracker,
|
||||
}
|
||||
|
||||
impl CommandBuffer<B> {
|
||||
pub(crate) fn insert_barriers<I, J>(
|
||||
raw: &mut <B as hal::Backend>::CommandBuffer,
|
||||
buffer_iter: I,
|
||||
texture_iter: J,
|
||||
) where
|
||||
I: Iterator<Item = (BufferId, Range<BufferUsageFlags>)>,
|
||||
J: Iterator<Item = (TextureId, Range<TextureUsageFlags>)>,
|
||||
{
|
||||
let buffer_guard = HUB.buffers.lock();
|
||||
let texture_guard = HUB.textures.lock();
|
||||
|
||||
let buffer_barriers = buffer_iter.map(|(id, transit)| {
|
||||
let b = buffer_guard.get(id);
|
||||
trace!("transit {:?} {:?}", id, transit);
|
||||
hal::memory::Barrier::Buffer {
|
||||
states: conv::map_buffer_state(transit.start) ..
|
||||
conv::map_buffer_state(transit.end),
|
||||
target: &b.raw,
|
||||
}
|
||||
});
|
||||
let texture_barriers = texture_iter.map(|(id, transit)| {
|
||||
let t = texture_guard.get(id);
|
||||
trace!("transit {:?} {:?}", id, transit);
|
||||
let aspects = t.full_range.aspects;
|
||||
hal::memory::Barrier::Image {
|
||||
states: conv::map_texture_state(transit.start, aspects) ..
|
||||
conv::map_texture_state(transit.end, aspects),
|
||||
target: &t.raw,
|
||||
range: t.full_range.clone(), //TODO?
|
||||
}
|
||||
});
|
||||
|
||||
raw.pipeline_barrier(
|
||||
hal::pso::PipelineStage::TOP_OF_PIPE .. hal::pso::PipelineStage::BOTTOM_OF_PIPE,
|
||||
hal::memory::Dependencies::empty(),
|
||||
buffer_barriers.chain(texture_barriers),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -117,7 +159,7 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass(
|
||||
} else {
|
||||
extent = Some(view.extent);
|
||||
}
|
||||
let query = tracker.query(view.texture_id.0);
|
||||
let query = tracker.query(view.texture_id.0, TextureUsageFlags::empty());
|
||||
let (_, layout) = conv::map_texture_state(
|
||||
query.usage,
|
||||
hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL,
|
||||
@ -141,7 +183,7 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass(
|
||||
} else {
|
||||
extent = Some(view.extent);
|
||||
}
|
||||
let query = tracker.query(view.texture_id.0);
|
||||
let query = tracker.query(view.texture_id.0, TextureUsageFlags::empty());
|
||||
let (_, layout) = conv::map_texture_state(query.usage, hal::format::Aspects::COLOR);
|
||||
hal::pass::Attachment {
|
||||
format: Some(conv::map_texture_format(view.format)),
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use conv;
|
||||
use registry::{HUB, Items, Registry};
|
||||
use track::{BufferTracker, TextureTracker};
|
||||
use {
|
||||
Stored,
|
||||
CommandBuffer, Stored,
|
||||
CommandBufferId, RenderPassId,
|
||||
};
|
||||
|
||||
@ -44,36 +43,10 @@ pub extern "C" fn wgpu_render_pass_end_pass(
|
||||
let cmb = cmb_guard.get_mut(pass.cmb_id.0);
|
||||
|
||||
if let Some(ref mut last) = cmb.raw.last_mut() {
|
||||
let buffer_guard = HUB.buffers.lock();
|
||||
let texture_guard = HUB.textures.lock();
|
||||
|
||||
let buffer_barriers = cmb.buffer_tracker
|
||||
.consume(pass.buffer_tracker)
|
||||
.map(|(id, transit)| {
|
||||
let b = buffer_guard.get(id);
|
||||
hal::memory::Barrier::Buffer {
|
||||
states: conv::map_buffer_state(transit.start) ..
|
||||
conv::map_buffer_state(transit.end),
|
||||
target: &b.raw,
|
||||
}
|
||||
});
|
||||
let texture_barriers = cmb.texture_tracker
|
||||
.consume(pass.texture_tracker)
|
||||
.map(|(id, transit)| {
|
||||
let t = texture_guard.get(id);
|
||||
let aspects = t.full_range.aspects;
|
||||
hal::memory::Barrier::Image {
|
||||
states: conv::map_texture_state(transit.start, aspects) ..
|
||||
conv::map_texture_state(transit.end, aspects),
|
||||
target: &t.raw,
|
||||
range: t.full_range.clone(), //TODO?
|
||||
}
|
||||
});
|
||||
|
||||
last.pipeline_barrier(
|
||||
hal::pso::PipelineStage::TOP_OF_PIPE .. hal::pso::PipelineStage::BOTTOM_OF_PIPE,
|
||||
hal::memory::Dependencies::empty(),
|
||||
buffer_barriers.chain(texture_barriers),
|
||||
CommandBuffer::insert_barriers(
|
||||
last,
|
||||
cmb.buffer_tracker.consume(&pass.buffer_tracker),
|
||||
cmb.texture_tracker.consume(&pass.texture_tracker),
|
||||
);
|
||||
last.finish();
|
||||
}
|
||||
|
||||
@ -364,6 +364,7 @@ pub fn map_texture_state(
|
||||
|
||||
let is_color = aspects.contains(hal::format::Aspects::COLOR);
|
||||
let layout = match usage {
|
||||
W::WRITE_ALL => return (A::empty(), L::Undefined), // special value
|
||||
W::TRANSFER_SRC => L::TransferSrcOptimal,
|
||||
W::TRANSFER_DST => L::TransferDstOptimal,
|
||||
W::SAMPLED => L::ShaderReadOnlyOptimal,
|
||||
|
||||
@ -2,7 +2,7 @@ use {back, binding_model, command, conv, pipeline, resource};
|
||||
use registry::{HUB, Items, Registry};
|
||||
use track::{BufferTracker, TextureTracker};
|
||||
use {
|
||||
Stored,
|
||||
CommandBuffer, Stored, TextureUsageFlags,
|
||||
AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId,
|
||||
DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId,
|
||||
TextureId, TextureViewId,
|
||||
@ -130,7 +130,7 @@ pub extern "C" fn wgpu_device_create_texture(
|
||||
let query = device.texture_tracker
|
||||
.lock()
|
||||
.unwrap()
|
||||
.query(id);
|
||||
.query(id, TextureUsageFlags::WRITE_ALL);
|
||||
assert!(query.initialized);
|
||||
|
||||
id
|
||||
@ -341,16 +341,34 @@ pub extern "C" fn wgpu_queue_submit(
|
||||
) {
|
||||
let mut device_guard = HUB.devices.lock();
|
||||
let device = device_guard.get_mut(queue_id);
|
||||
let mut buffer_tracker = device.buffer_tracker.lock().unwrap();
|
||||
let mut texture_tracker = device.texture_tracker.lock().unwrap();
|
||||
|
||||
let mut command_buffer_guard = HUB.command_buffers.lock();
|
||||
let command_buffer_ids = unsafe {
|
||||
slice::from_raw_parts(command_buffer_ptr, command_buffer_count)
|
||||
};
|
||||
|
||||
//TODO: if multiple command buffers are submitted, we can re-use the last
|
||||
// native command buffer of the previous chain instead of always creating
|
||||
// a temporary one, since the chains are not finished.
|
||||
|
||||
// finish all the command buffers first
|
||||
for &cmb_id in command_buffer_ids {
|
||||
command_buffer_guard
|
||||
.get_mut(cmb_id)
|
||||
.raw
|
||||
let comb = command_buffer_guard.get_mut(cmb_id);
|
||||
let mut transit = device.com_allocator.extend(comb);
|
||||
transit.begin(
|
||||
hal::command::CommandBufferFlags::ONE_TIME_SUBMIT,
|
||||
hal::command::CommandBufferInheritanceInfo::default(),
|
||||
);
|
||||
CommandBuffer::insert_barriers(
|
||||
&mut transit,
|
||||
buffer_tracker.consume(&comb.buffer_tracker),
|
||||
texture_tracker.consume(&comb.texture_tracker),
|
||||
);
|
||||
transit.finish();
|
||||
comb.raw.insert(0, transit);
|
||||
comb.raw
|
||||
.last_mut()
|
||||
.unwrap()
|
||||
.finish();
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
extern crate bitflags;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[cfg(feature = "remote")]
|
||||
extern crate parking_lot;
|
||||
|
||||
|
||||
@ -29,29 +29,23 @@ bitflags! {
|
||||
|
||||
|
||||
pub trait GenericUsage {
|
||||
fn default() -> Self;
|
||||
fn is_exclusive(&self) -> bool;
|
||||
}
|
||||
impl GenericUsage for BufferUsageFlags {
|
||||
fn default() -> Self {
|
||||
BufferUsageFlags::empty()
|
||||
}
|
||||
fn is_exclusive(&self) -> bool {
|
||||
BufferUsageFlags::WRITE_ALL.intersects(*self)
|
||||
}
|
||||
}
|
||||
impl GenericUsage for TextureUsageFlags {
|
||||
fn default() -> Self {
|
||||
TextureUsageFlags::empty()
|
||||
}
|
||||
fn is_exclusive(&self) -> bool {
|
||||
TextureUsageFlags::WRITE_ALL.intersects(*self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//TODO: consider having `I` as an associated type of `U`?
|
||||
pub struct Tracker<I, U> {
|
||||
map: HashMap<Stored<I>, U>,
|
||||
map: HashMap<Stored<I>, Range<U>>,
|
||||
}
|
||||
pub type BufferTracker = Tracker<BufferId, BufferUsageFlags>;
|
||||
pub type TextureTracker = Tracker<TextureId, TextureUsageFlags>;
|
||||
@ -66,19 +60,18 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
pub fn query(&mut self, id: I) -> Query<U> {
|
||||
pub fn query(&mut self, id: I, default: U) -> Query<U> {
|
||||
match self.map.entry(Stored(id)) {
|
||||
Entry::Vacant(e) => {
|
||||
let usage = U::default();
|
||||
e.insert(usage);
|
||||
e.insert(default .. default);
|
||||
Query {
|
||||
usage,
|
||||
usage: default,
|
||||
initialized: true,
|
||||
}
|
||||
}
|
||||
Entry::Occupied(e) => {
|
||||
Query {
|
||||
usage: *e.get(),
|
||||
usage: e.get().end,
|
||||
initialized: false,
|
||||
}
|
||||
}
|
||||
@ -88,17 +81,19 @@ impl<
|
||||
pub fn transit(&mut self, id: I, usage: U, permit: TrackPermit) -> Result<Tracktion<U>, U> {
|
||||
match self.map.entry(Stored(id)) {
|
||||
Entry::Vacant(e) => {
|
||||
e.insert(usage);
|
||||
e.insert(usage .. usage);
|
||||
Ok(Tracktion::Init)
|
||||
}
|
||||
Entry::Occupied(mut e) => {
|
||||
let old = *e.get();
|
||||
let old = e.get().end;
|
||||
if usage == old {
|
||||
Ok(Tracktion::Keep)
|
||||
} else if permit.contains(TrackPermit::EXTEND) && !(old | usage).is_exclusive() {
|
||||
Ok(Tracktion::Extend { old: e.insert(old | usage) })
|
||||
e.get_mut().end = old | usage;
|
||||
Ok(Tracktion::Extend { old })
|
||||
} else if permit.contains(TrackPermit::REPLACE) {
|
||||
Ok(Tracktion::Replace { old: e.insert(usage) })
|
||||
e.get_mut().end = usage;
|
||||
Ok(Tracktion::Replace { old })
|
||||
} else {
|
||||
Err(old)
|
||||
}
|
||||
@ -106,13 +101,13 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn consume<'a>(&'a mut self, other: Self) -> impl 'a + Iterator<Item = (I, Range<U>)> {
|
||||
pub fn consume<'a>(&'a mut self, other: &'a Self) -> impl 'a + Iterator<Item = (I, Range<U>)> {
|
||||
other.map
|
||||
.into_iter()
|
||||
.flat_map(move |(id, new)| match self.transit(id.0.clone(), new, TrackPermit::REPLACE) {
|
||||
.iter()
|
||||
.flat_map(move |(id, new)| match self.transit(id.0.clone(), new.end, TrackPermit::REPLACE) {
|
||||
Ok(Tracktion::Init) |
|
||||
Ok(Tracktion::Keep) => None,
|
||||
Ok(Tracktion::Replace { old }) => Some((id.0, old .. new)),
|
||||
Ok(Tracktion::Replace { old }) => Some((id.0.clone(), old .. new.end)),
|
||||
Ok(Tracktion::Extend { .. }) |
|
||||
Err(_) => panic!("Unable to consume a resource transition!"),
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user