mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-10-30 22:11:50 +00:00
Moving the code to use the new tracker API
This commit is contained in:
parent
2446190a0b
commit
bc7b842f12
@ -105,7 +105,6 @@ pub struct BindGroupDescriptor {
|
||||
pub bindings_length: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BindGroup<B: hal::Backend> {
|
||||
pub(crate) raw: DescriptorSet<B>,
|
||||
pub(crate) device_id: Stored<DeviceId>,
|
||||
|
@ -24,7 +24,6 @@ impl<B: hal::Backend> CommandPool<B> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Inner<B: hal::Backend> {
|
||||
pools: HashMap<thread::ThreadId, CommandPool<B>>,
|
||||
pending: Vec<CommandBuffer<B>>,
|
||||
@ -42,7 +41,6 @@ impl<B: hal::Backend> Inner<B> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CommandAllocator<B: hal::Backend> {
|
||||
queue_family: hal::queue::QueueFamilyId,
|
||||
inner: Mutex<Inner<B>>,
|
||||
|
@ -17,7 +17,6 @@ use hal::{self, command::RawCommandBuffer};
|
||||
|
||||
use std::{iter, slice};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ComputePass<B: hal::Backend> {
|
||||
raw: B::CommandBuffer,
|
||||
cmb_id: Stored<CommandBufferId>,
|
||||
|
@ -21,7 +21,7 @@ use crate::{
|
||||
hub::{Storage, HUB},
|
||||
resource::TexturePlacement,
|
||||
swap_chain::{SwapChainLink, SwapImageEpoch},
|
||||
track::{DummyUsage, Stitch, TrackerSet},
|
||||
track::{Stitch, TrackerSet},
|
||||
BufferHandle,
|
||||
BufferId,
|
||||
Color,
|
||||
@ -88,7 +88,6 @@ pub struct RenderPassDescriptor {
|
||||
pub depth_stencil_attachment: *const RenderPassDepthStencilAttachmentDescriptor<TextureViewId>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CommandBuffer<B: hal::Backend> {
|
||||
pub(crate) raw: Vec<B::CommandBuffer>,
|
||||
is_recording: bool,
|
||||
@ -110,34 +109,31 @@ impl CommandBufferHandle {
|
||||
) {
|
||||
let buffer_barriers =
|
||||
base.buffers
|
||||
.consume_by_replace(&head.buffers, stitch)
|
||||
.map(|(id, transit)| {
|
||||
let b = &buffer_guard[id];
|
||||
trace!("transit buffer {:?} {:?}", id, transit);
|
||||
.merge_replace(&head.buffers, stitch)
|
||||
.unwrap()
|
||||
.map(|pending| {
|
||||
trace!("transit buffer {:?}", pending);
|
||||
hal::memory::Barrier::Buffer {
|
||||
states: conv::map_buffer_state(transit.start)
|
||||
.. conv::map_buffer_state(transit.end),
|
||||
target: &b.raw,
|
||||
states: pending.to_states(),
|
||||
target: &buffer_guard[pending.id].raw,
|
||||
range: None .. None,
|
||||
families: None,
|
||||
}
|
||||
});
|
||||
let texture_barriers = base
|
||||
.textures
|
||||
.consume_by_replace(&head.textures, stitch)
|
||||
.map(|(id, transit)| {
|
||||
let t = &texture_guard[id];
|
||||
trace!("transit texture {:?} {:?}", id, transit);
|
||||
let aspects = t.full_range.aspects;
|
||||
.merge_replace(&head.textures, stitch)
|
||||
.unwrap()
|
||||
.map(|pending| {
|
||||
trace!("transit texture {:?}", pending);
|
||||
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?
|
||||
states: pending.to_states(),
|
||||
target: &texture_guard[pending.id].raw,
|
||||
range: pending.selector,
|
||||
families: None,
|
||||
}
|
||||
});
|
||||
base.views.consume_by_extend(&head.views).unwrap();
|
||||
base.views.merge_extend(&head.views).unwrap();
|
||||
|
||||
let stages = all_buffer_stages() | all_image_stages();
|
||||
unsafe {
|
||||
@ -175,6 +171,7 @@ pub fn command_encoder_begin_render_pass(
|
||||
let mut cmb_guard = HUB.command_buffers.write();
|
||||
let cmb = &mut cmb_guard[command_encoder_id];
|
||||
let device = &device_guard[cmb.device_id.value];
|
||||
let texture_guard = HUB.textures.read();
|
||||
let view_guard = HUB.texture_views.read();
|
||||
|
||||
let mut current_comb = device.com_allocator.extend(cmb);
|
||||
@ -185,6 +182,7 @@ pub fn command_encoder_begin_render_pass(
|
||||
);
|
||||
}
|
||||
let mut extent = None;
|
||||
let mut barriers = Vec::new();
|
||||
|
||||
let color_attachments =
|
||||
unsafe { slice::from_raw_parts(desc.color_attachments, desc.color_attachments_length) };
|
||||
@ -195,38 +193,65 @@ pub fn command_encoder_begin_render_pass(
|
||||
let swap_chain_links = &mut cmb.swap_chain_links;
|
||||
|
||||
let depth_stencil = depth_stencil_attachment.map(|at| {
|
||||
let view = &view_guard[at.attachment];
|
||||
let view = trackers.views
|
||||
.use_extend(&*view_guard, at.attachment, (), ())
|
||||
.unwrap();
|
||||
if let Some(ex) = extent {
|
||||
assert_eq!(ex, view.extent);
|
||||
} else {
|
||||
extent = Some(view.extent);
|
||||
}
|
||||
trackers
|
||||
.views
|
||||
.query(at.attachment, &view.life_guard.ref_count, DummyUsage);
|
||||
let query = trackers.textures.query(
|
||||
let old_layout = match trackers.textures.query(
|
||||
view.texture_id.value,
|
||||
&view.texture_id.ref_count,
|
||||
TextureUsage::empty(),
|
||||
);
|
||||
let (_, layout) = conv::map_texture_state(
|
||||
query.usage,
|
||||
hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL,
|
||||
);
|
||||
view.range.clone(),
|
||||
) {
|
||||
Some(usage) => {
|
||||
conv::map_texture_state(
|
||||
usage,
|
||||
hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL,
|
||||
).1
|
||||
}
|
||||
None => {
|
||||
// Required sub-resources have inconsistent states, we need to
|
||||
// issue individual barriers instead of relying on the render pass.
|
||||
let (texture, pending) = trackers.textures
|
||||
.use_replace(
|
||||
&*texture_guard,
|
||||
view.texture_id.value,
|
||||
view.range.clone(),
|
||||
TextureUsage::OUTPUT_ATTACHMENT,
|
||||
)
|
||||
.unwrap();
|
||||
barriers.extend(pending.map(|pending| hal::memory::Barrier::Image {
|
||||
states: pending.to_states(),
|
||||
target: &texture.raw,
|
||||
families: None,
|
||||
range: pending.selector,
|
||||
}));
|
||||
hal::image::Layout::DepthStencilAttachmentOptimal
|
||||
}
|
||||
};
|
||||
hal::pass::Attachment {
|
||||
format: Some(conv::map_texture_format(view.format)),
|
||||
samples: view.samples,
|
||||
ops: conv::map_load_store_ops(at.depth_load_op, at.depth_store_op),
|
||||
stencil_ops: conv::map_load_store_ops(at.stencil_load_op, at.stencil_store_op),
|
||||
layouts: layout .. layout,
|
||||
layouts: old_layout .. hal::image::Layout::DepthStencilAttachmentOptimal,
|
||||
}
|
||||
});
|
||||
|
||||
let color_keys = color_attachments.iter().map(|at| {
|
||||
let view = &view_guard[at.attachment];
|
||||
let view = trackers.views
|
||||
.use_extend(&*view_guard, at.attachment, (), ())
|
||||
.unwrap();
|
||||
if let Some(ex) = extent {
|
||||
assert_eq!(ex, view.extent);
|
||||
} else {
|
||||
extent = Some(view.extent);
|
||||
}
|
||||
|
||||
if view.is_owned_by_swap_chain {
|
||||
let link = match HUB.textures.read()[view.texture_id.value].placement {
|
||||
let link = match texture_guard[view.texture_id.value].placement {
|
||||
TexturePlacement::SwapChain(ref link) => SwapChainLink {
|
||||
swap_chain_id: link.swap_chain_id.clone(),
|
||||
epoch: *link.epoch.lock(),
|
||||
@ -237,26 +262,39 @@ pub fn command_encoder_begin_render_pass(
|
||||
swap_chain_links.push(link);
|
||||
}
|
||||
|
||||
if let Some(ex) = extent {
|
||||
assert_eq!(ex, view.extent);
|
||||
} else {
|
||||
extent = Some(view.extent);
|
||||
}
|
||||
trackers
|
||||
.views
|
||||
.query(at.attachment, &view.life_guard.ref_count, DummyUsage);
|
||||
let query = trackers.textures.query(
|
||||
let old_layout = match trackers.textures.query(
|
||||
view.texture_id.value,
|
||||
&view.texture_id.ref_count,
|
||||
TextureUsage::empty(),
|
||||
);
|
||||
let (_, layout) = conv::map_texture_state(query.usage, hal::format::Aspects::COLOR);
|
||||
view.range.clone(),
|
||||
) {
|
||||
Some(usage) => {
|
||||
conv::map_texture_state(usage, hal::format::Aspects::COLOR).1
|
||||
}
|
||||
None => {
|
||||
// Required sub-resources have inconsistent states, we need to
|
||||
// issue individual barriers instead of relying on the render pass.
|
||||
let (texture, pending) = trackers.textures
|
||||
.use_replace(
|
||||
&*texture_guard,
|
||||
view.texture_id.value,
|
||||
view.range.clone(),
|
||||
TextureUsage::OUTPUT_ATTACHMENT,
|
||||
)
|
||||
.unwrap();
|
||||
barriers.extend(pending.map(|pending| hal::memory::Barrier::Image {
|
||||
states: pending.to_states(),
|
||||
target: &texture.raw,
|
||||
families: None,
|
||||
range: pending.selector,
|
||||
}));
|
||||
hal::image::Layout::ColorAttachmentOptimal
|
||||
}
|
||||
};
|
||||
hal::pass::Attachment {
|
||||
format: Some(conv::map_texture_format(view.format)),
|
||||
samples: view.samples,
|
||||
ops: conv::map_load_store_ops(at.load_op, at.store_op),
|
||||
stencil_ops: hal::pass::AttachmentOps::DONT_CARE,
|
||||
layouts: layout .. layout,
|
||||
layouts: old_layout .. hal::image::Layout::ColorAttachmentOptimal,
|
||||
}
|
||||
});
|
||||
|
||||
@ -266,6 +304,16 @@ pub fn command_encoder_begin_render_pass(
|
||||
}
|
||||
};
|
||||
|
||||
if !barriers.is_empty() {
|
||||
unsafe {
|
||||
current_comb.pipeline_barrier(
|
||||
all_image_stages() .. all_image_stages(),
|
||||
hal::memory::Dependencies::empty(),
|
||||
barriers,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let mut render_pass_cache = device.render_passes.lock();
|
||||
let render_pass = match render_pass_cache.entry(rp_key.clone()) {
|
||||
Entry::Occupied(e) => e.into_mut(),
|
||||
|
@ -109,7 +109,6 @@ impl VertexState {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RenderPass<B: hal::Backend> {
|
||||
raw: B::CommandBuffer,
|
||||
cmb_id: Stored<CommandBufferId>,
|
||||
@ -192,7 +191,7 @@ pub extern "C" fn wgpu_render_pass_end_pass(pass_id: RenderPassId) -> CommandBuf
|
||||
unsafe { last.finish() };
|
||||
}
|
||||
None => {
|
||||
cmb.trackers.consume_by_extend(&pass.trackers);
|
||||
cmb.trackers.merge_extend(&pass.trackers);
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,7 +231,7 @@ pub extern "C" fn wgpu_render_pass_set_bind_group(
|
||||
}
|
||||
}
|
||||
|
||||
pass.trackers.consume_by_extend(&bind_group.used);
|
||||
pass.trackers.merge_extend(&bind_group.used);
|
||||
|
||||
if let Some((pipeline_layout_id, follow_up)) =
|
||||
pass.binder
|
||||
@ -282,7 +281,7 @@ pub extern "C" fn wgpu_render_pass_set_index_buffer(
|
||||
let buffer = pass
|
||||
.trackers
|
||||
.buffers
|
||||
.get_with_extended_usage(&*buffer_guard, buffer_id, BufferUsage::INDEX)
|
||||
.use_extend(&*buffer_guard, buffer_id, (), BufferUsage::INDEX)
|
||||
.unwrap();
|
||||
|
||||
let range = offset .. buffer.size;
|
||||
@ -316,7 +315,7 @@ pub extern "C" fn wgpu_render_pass_set_vertex_buffers(
|
||||
for (vbs, (&id, &offset)) in pass.vertex_state.inputs.iter_mut().zip(buffers.iter().zip(offsets)) {
|
||||
let buffer = pass.trackers
|
||||
.buffers
|
||||
.get_with_extended_usage(&*buffer_guard, id, BufferUsage::VERTEX)
|
||||
.use_extend(&*buffer_guard, id, (), BufferUsage::VERTEX)
|
||||
.unwrap();
|
||||
vbs.total_size = buffer.size - offset;
|
||||
}
|
||||
@ -450,7 +449,7 @@ pub extern "C" fn wgpu_render_pass_set_pipeline(
|
||||
let buffer = pass
|
||||
.trackers
|
||||
.buffers
|
||||
.get_with_extended_usage(&*buffer_guard, buffer_id, BufferUsage::INDEX)
|
||||
.use_extend(&*buffer_guard, buffer_id, (), BufferUsage::INDEX)
|
||||
.unwrap();
|
||||
|
||||
let view = hal::buffer::IndexBufferView {
|
||||
|
@ -39,6 +39,27 @@ pub struct TextureCopyView {
|
||||
pub origin: Origin3d,
|
||||
}
|
||||
|
||||
impl TextureCopyView {
|
||||
fn to_selector(&self) -> hal::image::SubresourceRange {
|
||||
let level = self.mip_level as hal::image::Level;
|
||||
let layer = self.array_layer as hal::image::Layer;
|
||||
hal::image::SubresourceRange {
|
||||
aspects: hal::format::Aspects::all(), //TODO
|
||||
levels: level .. level + 1,
|
||||
layers: layer .. layer + 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn to_sub_layers(&self) -> hal::image::SubresourceLayers {
|
||||
let layer = self.array_layer as hal::image::Layer;
|
||||
hal::image::SubresourceLayers {
|
||||
aspects: hal::format::Aspects::all(), //TODO
|
||||
level: self.mip_level as hal::image::Level,
|
||||
layers: layer .. layer + 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_command_buffer_copy_buffer_to_buffer(
|
||||
command_buffer_id: CommandBufferId,
|
||||
@ -51,30 +72,33 @@ pub extern "C" fn wgpu_command_buffer_copy_buffer_to_buffer(
|
||||
let mut cmb_guard = HUB.command_buffers.write();
|
||||
let cmb = &mut cmb_guard[command_buffer_id];
|
||||
let buffer_guard = HUB.buffers.read();
|
||||
// we can't hold both src_pending and dst_pending in scope because they
|
||||
// borrow the buffer tracker mutably...
|
||||
let mut barriers = Vec::new();
|
||||
|
||||
let (src_buffer, src_usage) = cmb
|
||||
let (src_buffer, src_pending) = cmb
|
||||
.trackers
|
||||
.buffers
|
||||
.get_with_replaced_usage(&*buffer_guard, src, BufferUsage::TRANSFER_SRC)
|
||||
.use_replace(&*buffer_guard, src, (), BufferUsage::TRANSFER_SRC)
|
||||
.unwrap();
|
||||
let src_barrier = src_usage.map(|old| hal::memory::Barrier::Buffer {
|
||||
states: conv::map_buffer_state(old) .. hal::buffer::Access::TRANSFER_READ,
|
||||
barriers.extend(src_pending.map(|pending| hal::memory::Barrier::Buffer {
|
||||
states: pending.to_states(),
|
||||
target: &src_buffer.raw,
|
||||
families: None,
|
||||
range: None .. None,
|
||||
});
|
||||
}));
|
||||
|
||||
let (dst_buffer, dst_usage) = cmb
|
||||
let (dst_buffer, dst_pending) = cmb
|
||||
.trackers
|
||||
.buffers
|
||||
.get_with_replaced_usage(&*buffer_guard, dst, BufferUsage::TRANSFER_DST)
|
||||
.use_replace(&*buffer_guard, dst, (), BufferUsage::TRANSFER_DST)
|
||||
.unwrap();
|
||||
let dst_barrier = dst_usage.map(|old| hal::memory::Barrier::Buffer {
|
||||
states: conv::map_buffer_state(old) .. hal::buffer::Access::TRANSFER_WRITE,
|
||||
barriers.extend(dst_pending.map(|pending| hal::memory::Barrier::Buffer {
|
||||
states: pending.to_states(),
|
||||
target: &dst_buffer.raw,
|
||||
families: None,
|
||||
range: None .. None,
|
||||
});
|
||||
}));
|
||||
|
||||
let region = hal::command::BufferCopy {
|
||||
src: src_offset,
|
||||
@ -86,7 +110,7 @@ pub extern "C" fn wgpu_command_buffer_copy_buffer_to_buffer(
|
||||
cmb_raw.pipeline_barrier(
|
||||
all_buffer_stages() .. all_buffer_stages(),
|
||||
hal::memory::Dependencies::empty(),
|
||||
src_barrier.into_iter().chain(dst_barrier),
|
||||
barriers,
|
||||
);
|
||||
cmb_raw.copy_buffer(&src_buffer.raw, &dst_buffer.raw, iter::once(region));
|
||||
}
|
||||
@ -104,34 +128,33 @@ pub extern "C" fn wgpu_command_buffer_copy_buffer_to_texture(
|
||||
let buffer_guard = HUB.buffers.read();
|
||||
let texture_guard = HUB.textures.read();
|
||||
|
||||
let (src_buffer, src_usage) = cmb
|
||||
let (src_buffer, src_pending) = cmb
|
||||
.trackers
|
||||
.buffers
|
||||
.get_with_replaced_usage(&*buffer_guard, source.buffer, BufferUsage::TRANSFER_SRC)
|
||||
.use_replace(&*buffer_guard, source.buffer, (), BufferUsage::TRANSFER_SRC)
|
||||
.unwrap();
|
||||
let src_barrier = src_usage.map(|old| hal::memory::Barrier::Buffer {
|
||||
states: conv::map_buffer_state(old) .. hal::buffer::Access::TRANSFER_READ,
|
||||
let src_barriers = src_pending.map(|pending| hal::memory::Barrier::Buffer {
|
||||
states: pending.to_states(),
|
||||
target: &src_buffer.raw,
|
||||
families: None,
|
||||
range: None .. None,
|
||||
});
|
||||
|
||||
let (dst_texture, dst_usage) = cmb
|
||||
let (dst_texture, dst_pending) = cmb
|
||||
.trackers
|
||||
.textures
|
||||
.get_with_replaced_usage(
|
||||
.use_replace(
|
||||
&*texture_guard,
|
||||
destination.texture,
|
||||
destination.to_selector(),
|
||||
TextureUsage::TRANSFER_DST,
|
||||
)
|
||||
.unwrap();
|
||||
let aspects = dst_texture.full_range.aspects;
|
||||
let dst_texture_state = conv::map_texture_state(TextureUsage::TRANSFER_DST, aspects);
|
||||
let dst_barrier = dst_usage.map(|old| hal::memory::Barrier::Image {
|
||||
states: conv::map_texture_state(old, aspects) .. dst_texture_state,
|
||||
let dst_barriers = dst_pending.map(|pending| hal::memory::Barrier::Image {
|
||||
states: pending.to_states(),
|
||||
target: &dst_texture.raw,
|
||||
families: None,
|
||||
range: dst_texture.full_range.clone(),
|
||||
range: pending.selector,
|
||||
});
|
||||
|
||||
if let TexturePlacement::SwapChain(ref link) = dst_texture.placement {
|
||||
@ -152,11 +175,7 @@ pub extern "C" fn wgpu_command_buffer_copy_buffer_to_texture(
|
||||
buffer_offset: source.offset,
|
||||
buffer_width,
|
||||
buffer_height: source.image_height,
|
||||
image_layers: hal::image::SubresourceLayers {
|
||||
aspects, //TODO
|
||||
level: destination.mip_level as hal::image::Level,
|
||||
layers: destination.array_layer as u16 .. destination.array_layer as u16 + 1,
|
||||
},
|
||||
image_layers: destination.to_sub_layers(),
|
||||
image_offset: conv::map_origin(destination.origin),
|
||||
image_extent: conv::map_extent(copy_size),
|
||||
};
|
||||
@ -166,12 +185,12 @@ pub extern "C" fn wgpu_command_buffer_copy_buffer_to_texture(
|
||||
cmb_raw.pipeline_barrier(
|
||||
stages .. stages,
|
||||
hal::memory::Dependencies::empty(),
|
||||
src_barrier.into_iter().chain(dst_barrier),
|
||||
src_barriers.chain(dst_barriers),
|
||||
);
|
||||
cmb_raw.copy_buffer_to_image(
|
||||
&src_buffer.raw,
|
||||
&dst_texture.raw,
|
||||
dst_texture_state.1,
|
||||
hal::image::Layout::TransferDstOptimal,
|
||||
iter::once(region),
|
||||
);
|
||||
}
|
||||
@ -189,18 +208,21 @@ pub extern "C" fn wgpu_command_buffer_copy_texture_to_buffer(
|
||||
let buffer_guard = HUB.buffers.read();
|
||||
let texture_guard = HUB.textures.read();
|
||||
|
||||
let (src_texture, src_usage) = cmb
|
||||
let (src_texture, src_pending) = cmb
|
||||
.trackers
|
||||
.textures
|
||||
.get_with_replaced_usage(&*texture_guard, source.texture, TextureUsage::TRANSFER_SRC)
|
||||
.use_replace(
|
||||
&*texture_guard,
|
||||
source.texture,
|
||||
source.to_selector(),
|
||||
TextureUsage::TRANSFER_SRC,
|
||||
)
|
||||
.unwrap();
|
||||
let aspects = src_texture.full_range.aspects;
|
||||
let src_texture_state = conv::map_texture_state(TextureUsage::TRANSFER_SRC, aspects);
|
||||
let src_barrier = src_usage.map(|old| hal::memory::Barrier::Image {
|
||||
states: conv::map_texture_state(old, aspects) .. src_texture_state,
|
||||
let src_barriers = src_pending.map(|pending| hal::memory::Barrier::Image {
|
||||
states: pending.to_states(),
|
||||
target: &src_texture.raw,
|
||||
families: None,
|
||||
range: src_texture.full_range.clone(),
|
||||
range: pending.selector,
|
||||
});
|
||||
match src_texture.placement {
|
||||
TexturePlacement::SwapChain(_) => unimplemented!(),
|
||||
@ -208,17 +230,18 @@ pub extern "C" fn wgpu_command_buffer_copy_texture_to_buffer(
|
||||
TexturePlacement::Memory(_) => (),
|
||||
}
|
||||
|
||||
let (dst_buffer, dst_usage) = cmb
|
||||
let (dst_buffer, dst_barriers) = cmb
|
||||
.trackers
|
||||
.buffers
|
||||
.get_with_replaced_usage(
|
||||
.use_replace(
|
||||
&*buffer_guard,
|
||||
destination.buffer,
|
||||
(),
|
||||
BufferUsage::TRANSFER_DST,
|
||||
)
|
||||
.unwrap();
|
||||
let dst_barrier = dst_usage.map(|old| hal::memory::Barrier::Buffer {
|
||||
states: conv::map_buffer_state(old) .. hal::buffer::Access::TRANSFER_WRITE,
|
||||
let dst_barrier = dst_barriers.map(|pending| hal::memory::Barrier::Buffer {
|
||||
states: pending.to_states(),
|
||||
target: &dst_buffer.raw,
|
||||
families: None,
|
||||
range: None .. None,
|
||||
@ -234,11 +257,7 @@ pub extern "C" fn wgpu_command_buffer_copy_texture_to_buffer(
|
||||
buffer_offset: destination.offset,
|
||||
buffer_width,
|
||||
buffer_height: destination.image_height,
|
||||
image_layers: hal::image::SubresourceLayers {
|
||||
aspects, //TODO
|
||||
level: source.mip_level as hal::image::Level,
|
||||
layers: source.array_layer as u16 .. source.array_layer as u16 + 1,
|
||||
},
|
||||
image_layers: source.to_sub_layers(),
|
||||
image_offset: conv::map_origin(source.origin),
|
||||
image_extent: conv::map_extent(copy_size),
|
||||
};
|
||||
@ -248,11 +267,11 @@ pub extern "C" fn wgpu_command_buffer_copy_texture_to_buffer(
|
||||
cmb_raw.pipeline_barrier(
|
||||
stages .. stages,
|
||||
hal::memory::Dependencies::empty(),
|
||||
src_barrier.into_iter().chain(dst_barrier),
|
||||
src_barriers.chain(dst_barrier),
|
||||
);
|
||||
cmb_raw.copy_image_to_buffer(
|
||||
&src_texture.raw,
|
||||
src_texture_state.1,
|
||||
hal::image::Layout::TransferSrcOptimal,
|
||||
&dst_buffer.raw,
|
||||
iter::once(region),
|
||||
);
|
||||
@ -269,38 +288,43 @@ pub extern "C" fn wgpu_command_buffer_copy_texture_to_texture(
|
||||
let mut cmb_guard = HUB.command_buffers.write();
|
||||
let cmb = &mut cmb_guard[command_buffer_id];
|
||||
let texture_guard = HUB.textures.read();
|
||||
// we can't hold both src_pending and dst_pending in scope because they
|
||||
// borrow the buffer tracker mutably...
|
||||
let mut barriers = Vec::new();
|
||||
|
||||
let (src_texture, src_usage) = cmb
|
||||
let (src_texture, src_pending) = cmb
|
||||
.trackers
|
||||
.textures
|
||||
.get_with_replaced_usage(&*texture_guard, source.texture, TextureUsage::TRANSFER_SRC)
|
||||
.use_replace(
|
||||
&*texture_guard,
|
||||
source.texture,
|
||||
source.to_selector(),
|
||||
TextureUsage::TRANSFER_SRC,
|
||||
)
|
||||
.unwrap();
|
||||
let (dst_texture, dst_usage) = cmb
|
||||
barriers.extend(src_pending.map(|pending| hal::memory::Barrier::Image {
|
||||
states: pending.to_states(),
|
||||
target: &src_texture.raw,
|
||||
families: None,
|
||||
range: pending.selector,
|
||||
}));
|
||||
|
||||
let (dst_texture, dst_pending) = cmb
|
||||
.trackers
|
||||
.textures
|
||||
.get_with_replaced_usage(
|
||||
.use_replace(
|
||||
&*texture_guard,
|
||||
destination.texture,
|
||||
destination.to_selector(),
|
||||
TextureUsage::TRANSFER_DST,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let aspects = src_texture.full_range.aspects & dst_texture.full_range.aspects;
|
||||
let src_texture_state = conv::map_texture_state(TextureUsage::TRANSFER_SRC, aspects);
|
||||
let dst_texture_state = conv::map_texture_state(TextureUsage::TRANSFER_DST, aspects);
|
||||
|
||||
let src_barrier = src_usage.map(|old| hal::memory::Barrier::Image {
|
||||
states: conv::map_texture_state(old, aspects) .. src_texture_state,
|
||||
target: &src_texture.raw,
|
||||
families: None,
|
||||
range: src_texture.full_range.clone(),
|
||||
});
|
||||
let dst_barrier = dst_usage.map(|old| hal::memory::Barrier::Image {
|
||||
states: conv::map_texture_state(old, aspects) .. dst_texture_state,
|
||||
barriers.extend(dst_pending.map(|pending| hal::memory::Barrier::Image {
|
||||
states: pending.to_states(),
|
||||
target: &dst_texture.raw,
|
||||
families: None,
|
||||
range: dst_texture.full_range.clone(),
|
||||
});
|
||||
range: pending.selector,
|
||||
}));
|
||||
|
||||
if let TexturePlacement::SwapChain(ref link) = dst_texture.placement {
|
||||
cmb.swap_chain_links.alloc().init(SwapChainLink {
|
||||
@ -311,17 +335,9 @@ pub extern "C" fn wgpu_command_buffer_copy_texture_to_texture(
|
||||
}
|
||||
|
||||
let region = hal::command::ImageCopy {
|
||||
src_subresource: hal::image::SubresourceLayers {
|
||||
aspects,
|
||||
level: source.mip_level as hal::image::Level,
|
||||
layers: source.array_layer as u16 .. source.array_layer as u16 + 1,
|
||||
},
|
||||
src_subresource: source.to_sub_layers(),
|
||||
src_offset: conv::map_origin(source.origin),
|
||||
dst_subresource: hal::image::SubresourceLayers {
|
||||
aspects,
|
||||
level: destination.mip_level as hal::image::Level,
|
||||
layers: destination.array_layer as u16 .. destination.array_layer as u16 + 1,
|
||||
},
|
||||
dst_subresource: destination.to_sub_layers(),
|
||||
dst_offset: conv::map_origin(destination.origin),
|
||||
extent: conv::map_extent(copy_size),
|
||||
};
|
||||
@ -330,13 +346,13 @@ pub extern "C" fn wgpu_command_buffer_copy_texture_to_texture(
|
||||
cmb_raw.pipeline_barrier(
|
||||
all_image_stages() .. all_image_stages(),
|
||||
hal::memory::Dependencies::empty(),
|
||||
src_barrier.into_iter().chain(dst_barrier),
|
||||
barriers,
|
||||
);
|
||||
cmb_raw.copy_image(
|
||||
&src_texture.raw,
|
||||
src_texture_state.1,
|
||||
hal::image::Layout::TransferSrcOptimal,
|
||||
&dst_texture.raw,
|
||||
dst_texture_state.1,
|
||||
hal::image::Layout::TransferDstOptimal,
|
||||
iter::once(region),
|
||||
);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use crate::{
|
||||
pipeline,
|
||||
resource,
|
||||
swap_chain,
|
||||
track::{DummyUsage, Stitch, TrackPermit, TrackerSet, Tracktion},
|
||||
track::{Stitch, TrackerSet},
|
||||
AdapterId,
|
||||
BindGroupId,
|
||||
BufferAddress,
|
||||
@ -605,12 +605,12 @@ pub fn device_track_buffer(
|
||||
ref_count: RefCount,
|
||||
flags: resource::BufferUsage,
|
||||
) {
|
||||
let query = HUB.devices.read()[device_id]
|
||||
let ok = HUB.devices.read()[device_id]
|
||||
.trackers
|
||||
.lock()
|
||||
.buffers
|
||||
.query(buffer_id, &ref_count, flags);
|
||||
assert!(query.initialized);
|
||||
.init(buffer_id, &ref_count, (), flags);
|
||||
assert!(ok);
|
||||
}
|
||||
|
||||
#[cfg(feature = "local")]
|
||||
@ -737,17 +737,23 @@ pub fn device_create_texture(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn device_track_texture(device_id: DeviceId, texture_id: TextureId, ref_count: RefCount) {
|
||||
let query = HUB.devices.read()[device_id]
|
||||
pub fn device_track_texture(
|
||||
device_id: DeviceId,
|
||||
texture_id: TextureId,
|
||||
ref_count: RefCount,
|
||||
full_range: hal::image::SubresourceRange,
|
||||
) {
|
||||
let ok = HUB.devices.read()[device_id]
|
||||
.trackers
|
||||
.lock()
|
||||
.textures
|
||||
.query(
|
||||
.init(
|
||||
texture_id,
|
||||
&ref_count,
|
||||
full_range,
|
||||
resource::TextureUsage::UNINITIALIZED,
|
||||
);
|
||||
assert!(query.initialized);
|
||||
assert!(ok);
|
||||
}
|
||||
|
||||
#[cfg(feature = "local")]
|
||||
@ -758,8 +764,9 @@ pub extern "C" fn wgpu_device_create_texture(
|
||||
) -> TextureId {
|
||||
let texture = device_create_texture(device_id, desc);
|
||||
let ref_count = texture.life_guard.ref_count.clone();
|
||||
let range = texture.full_range;
|
||||
let id = HUB.textures.register_local(texture);
|
||||
device_track_texture(device_id, id, ref_count);
|
||||
device_track_texture(device_id, id, ref_count, range);
|
||||
id
|
||||
}
|
||||
|
||||
@ -781,7 +788,7 @@ pub fn texture_create_view(
|
||||
view_kind,
|
||||
conv::map_texture_format(format),
|
||||
hal::format::Swizzle::NO,
|
||||
range,
|
||||
range.clone(),
|
||||
)
|
||||
.unwrap()
|
||||
};
|
||||
@ -795,6 +802,7 @@ pub fn texture_create_view(
|
||||
format: texture.format,
|
||||
extent: texture.kind.extent(),
|
||||
samples: texture.kind.num_samples(),
|
||||
range,
|
||||
is_owned_by_swap_chain: false,
|
||||
life_guard: LifeGuard::new(),
|
||||
}
|
||||
@ -802,12 +810,12 @@ pub fn texture_create_view(
|
||||
|
||||
pub fn device_track_view(texture_id: TextureId, view_id: TextureViewId, ref_count: RefCount) {
|
||||
let device_id = HUB.textures.read()[texture_id].device_id.value;
|
||||
let query = HUB.devices.read()[device_id]
|
||||
let ok = HUB.devices.read()[device_id]
|
||||
.trackers
|
||||
.lock()
|
||||
.views
|
||||
.query(view_id, &ref_count, DummyUsage);
|
||||
assert!(query.initialized);
|
||||
.init(view_id, &ref_count, (), ());
|
||||
assert!(ok);
|
||||
}
|
||||
|
||||
#[cfg(feature = "local")]
|
||||
@ -1067,7 +1075,7 @@ pub fn device_create_bind_group(
|
||||
);
|
||||
let buffer = used
|
||||
.buffers
|
||||
.get_with_extended_usage(&*buffer_guard, bb.buffer, usage)
|
||||
.use_extend(&*buffer_guard, bb.buffer, (), usage)
|
||||
.unwrap();
|
||||
let range = Some(bb.offset) .. Some(bb.offset + bb.size);
|
||||
hal::pso::Descriptor::Buffer(&buffer.raw, range)
|
||||
@ -1089,14 +1097,15 @@ pub fn device_create_bind_group(
|
||||
),
|
||||
_ => panic!("Mismatched texture binding for {:?}", decl),
|
||||
};
|
||||
let view = &texture_view_guard[id];
|
||||
used.views.query(id, &view.life_guard.ref_count, DummyUsage);
|
||||
let view = used.views
|
||||
.use_extend(&*texture_view_guard, id, (), ())
|
||||
.unwrap();
|
||||
used.textures
|
||||
.transit(
|
||||
.change_extend(
|
||||
view.texture_id.value,
|
||||
&view.texture_id.ref_count,
|
||||
view.range.clone(),
|
||||
usage,
|
||||
TrackPermit::EXTEND,
|
||||
)
|
||||
.unwrap();
|
||||
hal::pso::Descriptor::Image(&view.raw, image_layout)
|
||||
@ -1129,15 +1138,15 @@ pub fn device_create_bind_group(
|
||||
|
||||
pub fn device_track_bind_group(
|
||||
device_id: DeviceId,
|
||||
buffer_id: BindGroupId,
|
||||
bind_group_id: BindGroupId,
|
||||
ref_count: RefCount,
|
||||
) {
|
||||
let query = HUB.devices.read()[device_id]
|
||||
let ok = HUB.devices.read()[device_id]
|
||||
.trackers
|
||||
.lock()
|
||||
.bind_groups
|
||||
.query(buffer_id, &ref_count, DummyUsage);
|
||||
assert!(query.initialized);
|
||||
.init(bind_group_id, &ref_count, (), ());
|
||||
assert!(ok);
|
||||
}
|
||||
|
||||
#[cfg(feature = "local")]
|
||||
@ -1902,19 +1911,12 @@ pub extern "C" fn wgpu_buffer_map_read_async(
|
||||
let device_guard = HUB.devices.read();
|
||||
let device = &device_guard[device_id];
|
||||
|
||||
let usage = resource::BufferUsage::MAP_READ;
|
||||
match device
|
||||
device
|
||||
.trackers
|
||||
.lock()
|
||||
.buffers
|
||||
.transit(buffer_id, &ref_count, usage, TrackPermit::REPLACE)
|
||||
{
|
||||
Ok(Tracktion::Keep) => {}
|
||||
Ok(Tracktion::Replace { .. }) => {
|
||||
//TODO: launch a memory barrier into `HOST_READ` access?
|
||||
}
|
||||
other => panic!("Invalid mapping transition {:?}", other),
|
||||
}
|
||||
.change_replace(buffer_id, &ref_count, (), resource::BufferUsage::MAP_READ)
|
||||
.unwrap();
|
||||
|
||||
device.pending.lock().map(buffer_id, ref_count);
|
||||
}
|
||||
@ -1945,19 +1947,12 @@ pub extern "C" fn wgpu_buffer_map_write_async(
|
||||
let device_guard = HUB.devices.read();
|
||||
let device = &device_guard[device_id];
|
||||
|
||||
let usage = resource::BufferUsage::MAP_WRITE;
|
||||
match device
|
||||
device
|
||||
.trackers
|
||||
.lock()
|
||||
.buffers
|
||||
.transit(buffer_id, &ref_count, usage, TrackPermit::REPLACE)
|
||||
{
|
||||
Ok(Tracktion::Keep) => {}
|
||||
Ok(Tracktion::Replace { .. }) => {
|
||||
//TODO: launch a memory barrier into `HOST_WRITE` access?
|
||||
}
|
||||
other => panic!("Invalid mapping transition {:?}", other),
|
||||
}
|
||||
.change_replace(buffer_id, &ref_count, (), resource::BufferUsage::MAP_WRITE)
|
||||
.unwrap();
|
||||
|
||||
device.pending.lock().map(buffer_id, ref_count);
|
||||
}
|
||||
|
@ -255,11 +255,18 @@ pub struct TextureView<B: hal::Backend> {
|
||||
pub(crate) format: TextureFormat,
|
||||
pub(crate) extent: hal::image::Extent,
|
||||
pub(crate) samples: hal::image::NumSamples,
|
||||
pub(crate) range: hal::image::SubresourceRange,
|
||||
pub(crate) is_owned_by_swap_chain: bool,
|
||||
#[cfg_attr(not(feature = "local"), allow(dead_code))]
|
||||
pub(crate) life_guard: LifeGuard,
|
||||
}
|
||||
|
||||
impl<B: hal::Backend> Borrow<RefCount> for TextureView<B> {
|
||||
fn borrow(&self) -> &RefCount {
|
||||
&self.life_guard.ref_count
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum AddressMode {
|
||||
|
@ -3,7 +3,6 @@ use crate::{
|
||||
device::all_image_stages,
|
||||
hub::HUB,
|
||||
resource,
|
||||
track::TrackPermit,
|
||||
DeviceId,
|
||||
Extent3d,
|
||||
Stored,
|
||||
@ -231,27 +230,24 @@ pub extern "C" fn wgpu_swap_chain_present(swap_chain_id: SwapChainId) {
|
||||
//TODO: support for swapchain being sampled or read by the shader?
|
||||
|
||||
trace!("transit {:?} to present", frame.texture_id.value);
|
||||
let barrier = device
|
||||
.trackers
|
||||
.lock()
|
||||
.textures
|
||||
.transit(
|
||||
let mut trackers = device.trackers.lock();
|
||||
let barriers = trackers.textures
|
||||
.change_replace(
|
||||
frame.texture_id.value,
|
||||
&texture.life_guard.ref_count,
|
||||
texture.full_range.clone(),
|
||||
resource::TextureUsage::UNINITIALIZED,
|
||||
TrackPermit::REPLACE,
|
||||
)
|
||||
.unwrap()
|
||||
.into_source()
|
||||
.map(|old| hal::memory::Barrier::Image {
|
||||
states: conv::map_texture_state(old, hal::format::Aspects::COLOR)
|
||||
.map(|pending| hal::memory::Barrier::Image {
|
||||
states: conv::map_texture_state(pending.usage.start, hal::format::Aspects::COLOR)
|
||||
.. (
|
||||
hal::image::Access::COLOR_ATTACHMENT_WRITE,
|
||||
hal::image::Layout::Present,
|
||||
),
|
||||
target: &texture.raw,
|
||||
families: None,
|
||||
range: texture.full_range.clone(),
|
||||
range: pending.selector,
|
||||
});
|
||||
|
||||
let err = unsafe {
|
||||
@ -259,7 +255,7 @@ pub extern "C" fn wgpu_swap_chain_present(swap_chain_id: SwapChainId) {
|
||||
frame.comb.pipeline_barrier(
|
||||
all_image_stages() .. hal::pso::PipelineStage::COLOR_ATTACHMENT_OUTPUT,
|
||||
hal::memory::Dependencies::empty(),
|
||||
barrier,
|
||||
barriers,
|
||||
);
|
||||
frame.comb.finish();
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::{
|
||||
hub::Storage,
|
||||
conv,
|
||||
device::MAX_MIP_LEVELS,
|
||||
hub::Storage,
|
||||
resource::{BufferUsage, TextureUsage},
|
||||
BufferId,
|
||||
Epoch,
|
||||
@ -359,7 +360,7 @@ pub type TextureViewTracker = Tracker<TextureViewId, Unit<DummyUsage>>;
|
||||
pub type BindGroupTracker = Tracker<BindGroupId, Unit<DummyUsage>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TrackerSet {
|
||||
pub struct TrackerSetOld {
|
||||
pub buffers: BufferTracker,
|
||||
pub textures: TextureTracker,
|
||||
pub views: TextureViewTracker,
|
||||
@ -367,9 +368,9 @@ pub struct TrackerSet {
|
||||
//TODO: samplers
|
||||
}
|
||||
|
||||
impl TrackerSet {
|
||||
impl TrackerSetOld {
|
||||
pub fn new() -> Self {
|
||||
TrackerSet {
|
||||
TrackerSetOld {
|
||||
buffers: BufferTracker::new(),
|
||||
textures: TextureTracker::new(),
|
||||
views: TextureViewTracker::new(),
|
||||
@ -427,13 +428,14 @@ struct Resource<S> {
|
||||
epoch: Epoch,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PendingTransition<S: ResourceState> {
|
||||
pub id: S::Id,
|
||||
pub selector: S::Selector,
|
||||
pub usage: Range<S::Usage>,
|
||||
}
|
||||
|
||||
struct ResourceTracker<S: ResourceState> {
|
||||
pub struct ResourceTracker<S: ResourceState> {
|
||||
/// An association of known resource indices with their tracked states.
|
||||
map: FastHashMap<Index, Resource<S>>,
|
||||
/// Temporary storage for collecting transitions.
|
||||
@ -620,8 +622,16 @@ impl<S: ResourceState> ResourceTracker<S> {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: store `hal::buffer::State` here to avoid extra conversions
|
||||
pub type BufferState = Unit<BufferUsage>;
|
||||
|
||||
impl PendingTransition<BufferState> {
|
||||
pub fn to_states(&self) -> Range<hal::buffer::State> {
|
||||
conv::map_buffer_state(self.usage.start) ..
|
||||
conv::map_buffer_state(self.usage.end)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for BufferState {
|
||||
fn default() -> Self {
|
||||
BufferState {
|
||||
@ -745,7 +755,7 @@ impl<I: Copy + PartialOrd, T: Copy + PartialEq> RangedStates<I, T> {
|
||||
&mut self.ranges[start_pos .. pos]
|
||||
}
|
||||
|
||||
fn coalesce(&mut self) {
|
||||
fn _coalesce(&mut self) {
|
||||
let mut num_removed = 0;
|
||||
let mut iter = self.ranges.iter_mut();
|
||||
let mut cur = match iter.next() {
|
||||
@ -836,18 +846,26 @@ impl<'a, I: Copy + Ord, T: Copy> Iterator for Merge<'a, I, T> {
|
||||
|
||||
type PlaneStates<T> = RangedStates<hal::image::Layer, T>;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
//TODO: store `hal::image::State` here to avoid extra conversions
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
struct DepthStencilState {
|
||||
depth: Unit<TextureUsage>,
|
||||
stencil: Unit<TextureUsage>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct TextureStates {
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct TextureStates {
|
||||
color_mips: ArrayVec<[PlaneStates<Unit<TextureUsage>>; MAX_MIP_LEVELS]>,
|
||||
depth_stencil: PlaneStates<DepthStencilState>,
|
||||
}
|
||||
|
||||
impl PendingTransition<TextureStates> {
|
||||
pub fn to_states(&self) -> Range<hal::image::State> {
|
||||
conv::map_texture_state(self.usage.start, self.selector.aspects) ..
|
||||
conv::map_texture_state(self.usage.end, self.selector.aspects)
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceState for TextureStates {
|
||||
type Id = TextureId;
|
||||
type Selector = hal::image::SubresourceRange;
|
||||
@ -1134,3 +1152,72 @@ impl ResourceState for TextureViewState {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct BindGroupState;
|
||||
|
||||
impl ResourceState for BindGroupState {
|
||||
type Id = BindGroupId;
|
||||
type Selector = ();
|
||||
type Usage = ();
|
||||
|
||||
fn query(
|
||||
&self,
|
||||
_selector: Self::Selector,
|
||||
) -> Option<Self::Usage> {
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn change(
|
||||
&mut self,
|
||||
_id: Self::Id,
|
||||
_selector: Self::Selector,
|
||||
_usage: Self::Usage,
|
||||
_output: Option<&mut Vec<PendingTransition<Self>>>,
|
||||
) -> Result<(), PendingTransition<Self>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn merge(
|
||||
&mut self,
|
||||
_id: Self::Id,
|
||||
_other: &Self,
|
||||
_stitch: Stitch,
|
||||
_output: Option<&mut Vec<PendingTransition<Self>>>,
|
||||
) -> Result<(), PendingTransition<Self>> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TrackerSet {
|
||||
pub buffers: ResourceTracker<BufferState>,
|
||||
pub textures: ResourceTracker<TextureStates>,
|
||||
pub views: ResourceTracker<TextureViewState>,
|
||||
pub bind_groups: ResourceTracker<BindGroupState>,
|
||||
//TODO: samplers
|
||||
}
|
||||
|
||||
impl TrackerSet {
|
||||
pub fn new() -> Self {
|
||||
TrackerSet {
|
||||
buffers: ResourceTracker::new(),
|
||||
textures: ResourceTracker::new(),
|
||||
views: ResourceTracker::new(),
|
||||
bind_groups: ResourceTracker::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.buffers.clear();
|
||||
self.textures.clear();
|
||||
self.views.clear();
|
||||
self.bind_groups.clear();
|
||||
}
|
||||
|
||||
pub fn merge_extend(&mut self, other: &Self) {
|
||||
self.buffers.merge_extend(&other.buffers).unwrap();
|
||||
self.textures.merge_extend(&other.textures).unwrap();
|
||||
self.views.merge_extend(&other.views).unwrap();
|
||||
self.bind_groups.merge_extend(&other.bind_groups).unwrap();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user