Refactored tracking, now includes the views

This commit is contained in:
Dzmitry Malyshau 2019-02-22 12:59:23 -05:00
parent 7386a05a0d
commit c21420399a
14 changed files with 242 additions and 116 deletions

View File

@ -18,6 +18,7 @@ crate-type = ["lib", "cdylib", "staticlib"]
[features]
default = []
local = ["winit", "gfx-backend-empty/winit"]
metal-auto-capture = ["gfx-backend-metal/auto-capture"]
[dependencies]
bitflags = "1.0"

View File

@ -1,4 +1,4 @@
use crate::track::{BufferTracker, TextureTracker};
use crate::track::TrackerSet;
use crate::{
LifeGuard, WeaklyStored,
BindGroupLayoutId, BufferId, SamplerId, TextureViewId,
@ -84,6 +84,5 @@ pub struct BindGroup<B: hal::Backend> {
pub(crate) raw: B::DescriptorSet,
pub(crate) layout_id: WeaklyStored<BindGroupLayoutId>,
pub(crate) life_guard: LifeGuard,
pub(crate) used_buffers: BufferTracker,
pub(crate) used_textures: TextureTracker,
pub(crate) used: TrackerSet,
}

View File

@ -1,5 +1,5 @@
use super::CommandBuffer;
use crate::track::Tracker;
use crate::track::TrackerSet;
use crate::{DeviceId, LifeGuard, Stored, SubmissionIndex};
use hal::command::RawCommandBuffer;
@ -86,8 +86,7 @@ impl<B: hal::Backend> CommandAllocator<B> {
recorded_thread_id: thread_id,
device_id,
life_guard: LifeGuard::new(),
buffer_tracker: Tracker::new(),
texture_tracker: Tracker::new(),
trackers: TrackerSet::new(),
swap_chain_links: Vec::new(),
}
}

View File

@ -1,6 +1,6 @@
use crate::command::bind::{Binder};
use crate::hub::HUB;
use crate::track::{BufferTracker, TextureTracker};
use crate::track::TrackerSet;
use crate::{
Stored, CommandBuffer,
BindGroupId, CommandBufferId, ComputePassId, ComputePipelineId,
@ -16,8 +16,7 @@ pub struct ComputePass<B: hal::Backend> {
raw: B::CommandBuffer,
cmb_id: Stored<CommandBufferId>,
binder: Binder,
buffer_tracker: BufferTracker,
texture_tracker: TextureTracker,
trackers: TrackerSet,
}
impl<B: hal::Backend> ComputePass<B> {
@ -26,8 +25,7 @@ impl<B: hal::Backend> ComputePass<B> {
raw,
cmb_id,
binder: Binder::default(),
buffer_tracker: BufferTracker::new(),
texture_tracker: TextureTracker::new(),
trackers: TrackerSet::new(),
}
}
}
@ -36,6 +34,8 @@ impl<B: hal::Backend> ComputePass<B> {
pub extern "C" fn wgpu_compute_pass_end_pass(pass_id: ComputePassId) -> CommandBufferId {
let pass = HUB.compute_passes.unregister(pass_id);
//TODO: transitions?
HUB.command_buffers
.write()
.get_mut(pass.cmb_id.value)
@ -69,13 +69,15 @@ pub extern "C" fn wgpu_compute_pass_set_bind_group(
//Note: currently, WebGPU compute passes have synchronization defined
// at a dispatch granularity, so we insert the necessary barriers here.
//TODO: have `TrackerSet::consume()` ?
CommandBuffer::insert_barriers(
&mut pass.raw,
pass.buffer_tracker.consume_by_replace(&bind_group.used_buffers),
pass.texture_tracker.consume_by_replace(&bind_group.used_textures),
pass.trackers.buffers.consume_by_replace(&bind_group.used.buffers),
pass.trackers.textures.consume_by_replace(&bind_group.used.textures),
&*HUB.buffers.read(),
&*HUB.textures.read(),
);
pass.trackers.views.consume(&bind_group.used.views);
if let Some(pipeline_layout_id) = pass.binder.provide_entry(index as usize, bind_group_id, bind_group) {
let pipeline_layout_guard = HUB.pipeline_layouts.read();

View File

@ -15,7 +15,7 @@ use crate::device::{
};
use crate::hub::{HUB, Storage};
use crate::swap_chain::{SwapChainLink, SwapImageEpoch};
use crate::track::{BufferTracker, TextureTracker};
use crate::track::TrackerSet;
use crate::conv;
use crate::{
BufferHandle, TextureHandle,
@ -85,8 +85,7 @@ pub struct CommandBuffer<B: hal::Backend> {
recorded_thread_id: ThreadId,
device_id: Stored<DeviceId>,
pub(crate) life_guard: LifeGuard,
pub(crate) buffer_tracker: BufferTracker,
pub(crate) texture_tracker: TextureTracker,
pub(crate) trackers: TrackerSet,
pub(crate) swap_chain_links: Vec<SwapChainLink<SwapImageEpoch>>,
}
@ -184,7 +183,7 @@ pub fn command_encoder_begin_render_pass(
};
let rp_key = {
let tracker = &mut cmb.texture_tracker;
let trackers = &mut cmb.trackers;
let swap_chain_links = &mut cmb.swap_chain_links;
let depth_stencil_key = depth_stencil_attachment.map(|at| {
@ -194,7 +193,12 @@ pub fn command_encoder_begin_render_pass(
} else {
extent = Some(view.extent);
}
let query = tracker.query(&view.texture_id, TextureUsageFlags::empty());
trackers.views.query(at.attachment, &view.life_guard.ref_count);
let query = trackers.textures.query(
view.texture_id.value,
&view.texture_id.ref_count,
TextureUsageFlags::empty(),
);
let (_, layout) = conv::map_texture_state(
query.usage,
hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL,
@ -232,7 +236,12 @@ pub fn command_encoder_begin_render_pass(
} else {
extent = Some(view.extent);
}
let query = tracker.query(&view.texture_id, TextureUsageFlags::empty());
trackers.views.query(at.attachment, &view.life_guard.ref_count);
let query = trackers.textures.query(
view.texture_id.value,
&view.texture_id.ref_count,
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)),

View File

@ -1,7 +1,7 @@
use crate::command::bind::Binder;
use crate::hub::HUB;
use crate::resource::BufferUsageFlags;
use crate::track::{BufferTracker, TextureTracker};
use crate::track::TrackerSet;
use crate::{
CommandBuffer, Stored,
BindGroupId, BufferId, CommandBufferId, RenderPassId, RenderPipelineId,
@ -16,8 +16,7 @@ pub struct RenderPass<B: hal::Backend> {
raw: B::CommandBuffer,
cmb_id: Stored<CommandBufferId>,
binder: Binder,
buffer_tracker: BufferTracker,
texture_tracker: TextureTracker,
trackers: TrackerSet,
}
impl<B: hal::Backend> RenderPass<B> {
@ -26,8 +25,7 @@ impl<B: hal::Backend> RenderPass<B> {
raw,
cmb_id,
binder: Binder::default(),
buffer_tracker: BufferTracker::new(),
texture_tracker: TextureTracker::new(),
trackers: TrackerSet::new(),
}
}
}
@ -42,16 +40,27 @@ pub extern "C" fn wgpu_render_pass_end_pass(pass_id: RenderPassId) -> CommandBuf
let mut cmb_guard = HUB.command_buffers.write();
let cmb = cmb_guard.get_mut(pass.cmb_id.value);
if let Some(ref mut last) = cmb.raw.last_mut() {
CommandBuffer::insert_barriers(
last,
cmb.buffer_tracker.consume_by_replace(&pass.buffer_tracker),
cmb.texture_tracker.consume_by_replace(&pass.texture_tracker),
&*HUB.buffers.read(),
&*HUB.textures.read(),
);
unsafe { last.finish() };
match cmb.raw.last_mut() {
Some(ref mut last) => {
CommandBuffer::insert_barriers(
last,
cmb.trackers.buffers.consume_by_replace(&pass.trackers.buffers),
cmb.trackers.textures.consume_by_replace(&pass.trackers.textures),
&*HUB.buffers.read(),
&*HUB.textures.read(),
);
unsafe { last.finish() };
}
None => {
cmb.trackers.buffers
.consume_by_extend(&pass.trackers.buffers)
.unwrap();
cmb.trackers.textures
.consume_by_extend(&pass.trackers.textures)
.unwrap();
}
}
cmb.trackers.views.consume(&pass.trackers.views);
cmb.raw.push(pass.raw);
pass.cmb_id.value
@ -65,7 +74,7 @@ pub extern "C" fn wgpu_render_pass_set_index_buffer(
let buffer_guard = HUB.buffers.read();
let pass = pass_guard.get_mut(pass_id);
let buffer = pass.buffer_tracker
let buffer = pass.trackers.buffers
.get_with_extended_usage(
&*buffer_guard,
buffer_id,
@ -102,7 +111,7 @@ pub extern "C" fn wgpu_render_pass_set_vertex_buffers(
let pass = pass_guard.get_mut(pass_id);
for &id in buffers {
pass.buffer_tracker
pass.trackers.buffers
.get_with_extended_usage(
&*buffer_guard,
id,
@ -174,12 +183,13 @@ pub extern "C" fn wgpu_render_pass_set_bind_group(
let bind_group_guard = HUB.bind_groups.read();
let bind_group = bind_group_guard.get(bind_group_id);
pass.buffer_tracker
.consume_by_extend(&bind_group.used_buffers)
pass.trackers.buffers
.consume_by_extend(&bind_group.used.buffers)
.unwrap();
pass.texture_tracker
.consume_by_extend(&bind_group.used_textures)
pass.trackers.textures
.consume_by_extend(&bind_group.used.textures)
.unwrap();
pass.trackers.views.consume(&bind_group.used.views);
if let Some(pipeline_layout_id) = pass.binder.provide_entry(index as usize, bind_group_id, bind_group) {
let pipeline_layout_guard = HUB.pipeline_layouts.read();

View File

@ -45,7 +45,7 @@ pub extern "C" fn wgpu_command_buffer_copy_buffer_to_buffer(
let cmb = cmb_guard.get_mut(command_buffer_id);
let buffer_guard = HUB.buffers.read();
let (src_buffer, src_usage) = cmb.buffer_tracker
let (src_buffer, src_usage) = cmb.trackers.buffers
.get_with_replaced_usage(
&*buffer_guard,
src,
@ -59,7 +59,7 @@ pub extern "C" fn wgpu_command_buffer_copy_buffer_to_buffer(
range: None .. None,
});
let (dst_buffer, dst_usage) = cmb.buffer_tracker
let (dst_buffer, dst_usage) = cmb.trackers.buffers
.get_with_replaced_usage(
&*buffer_guard,
dst,
@ -105,7 +105,7 @@ 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.buffer_tracker
let (src_buffer, src_usage) = cmb.trackers.buffers
.get_with_replaced_usage(
&*buffer_guard,
source.buffer,
@ -119,7 +119,7 @@ pub extern "C" fn wgpu_command_buffer_copy_buffer_to_texture(
range: None .. None,
});
let (dst_texture, dst_usage) = cmb.texture_tracker
let (dst_texture, dst_usage) = cmb.trackers.textures
.get_with_replaced_usage(
&*texture_guard,
destination.texture,
@ -188,7 +188,7 @@ 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.texture_tracker
let (src_texture, src_usage) = cmb.trackers.textures
.get_with_replaced_usage(
&*texture_guard,
source.texture,
@ -205,7 +205,7 @@ pub extern "C" fn wgpu_command_buffer_copy_texture_to_buffer(
});
assert!(src_texture.swap_chain_link.is_none()); //TODO
let (dst_buffer, dst_usage) = cmb.buffer_tracker
let (dst_buffer, dst_usage) = cmb.trackers.buffers
.get_with_replaced_usage(
&*buffer_guard,
destination.buffer,
@ -263,14 +263,14 @@ pub extern "C" fn wgpu_command_buffer_copy_texture_to_texture(
let cmb = cmb_guard.get_mut(command_buffer_id);
let texture_guard = HUB.textures.read();
let (src_texture, src_usage) = cmb.texture_tracker
let (src_texture, src_usage) = cmb.trackers.textures
.get_with_replaced_usage(
&*texture_guard,
source.texture,
TextureUsageFlags::TRANSFER_SRC,
)
.unwrap();
let (dst_texture, dst_usage) = cmb.texture_tracker
let (dst_texture, dst_usage) = cmb.trackers.textures
.get_with_replaced_usage(
&*texture_guard,
destination.texture,

View File

@ -1,6 +1,6 @@
use crate::{binding_model, command, conv, pipeline, resource, swap_chain};
use crate::hub::HUB;
use crate::track::{BufferTracker, TextureTracker, TrackPermit};
use crate::track::{TrackerSet, TrackPermit};
use crate::{
LifeGuard, RefCount, Stored, SubmissionIndex, WeaklyStored,
};
@ -64,6 +64,7 @@ pub(crate) struct FramebufferKey {
}
impl Eq for FramebufferKey {}
#[derive(Debug)]
enum ResourceId {
Buffer(BufferId),
Texture(TextureId),
@ -140,29 +141,32 @@ impl<B: hal::Backend> DestroyedResources<B> {
impl DestroyedResources<back::Backend> {
fn triage_referenced(
&mut self,
buffer_tracker: &mut BufferTracker,
texture_tracker: &mut TextureTracker,
trackers: &mut TrackerSet,
) {
for i in (0..self.referenced.len()).rev() {
// one in resource itself, and one here in this list
let num_refs = self.referenced[i].1.load();
if num_refs <= 2 {
assert_eq!(num_refs, 2);
// Before destruction, a resource is expected to have the following strong refs:
// 1. in resource itself
// 2. in the device tracker
// 3. in this list
if num_refs <= 3 {
let resource_id = self.referenced.swap_remove(i).0;
assert_eq!(num_refs, 3, "Resource {:?} misses some references", resource_id);
let (submit_index, resource) = match resource_id {
ResourceId::Buffer(id) => {
buffer_tracker.remove(id);
trackers.buffers.remove(id);
let buf = HUB.buffers.unregister(id);
let si = buf.life_guard.submission_index.load(Ordering::Acquire);
(si, Resource::Buffer(buf))
}
ResourceId::Texture(id) => {
texture_tracker.remove(id);
trackers.textures.remove(id);
let tex = HUB.textures.unregister(id);
let si = tex.life_guard.submission_index.load(Ordering::Acquire);
(si, Resource::Texture(tex))
}
ResourceId::TextureView(id) => {
trackers.views.remove(id);
let view = HUB.texture_views.unregister(id);
let si = view.life_guard.submission_index.load(Ordering::Acquire);
(si, Resource::TextureView(view))
@ -189,8 +193,7 @@ pub struct Device<B: hal::Backend> {
//mem_allocator: Heaps<B::Memory>,
pub(crate) com_allocator: command::CommandAllocator<B>,
life_guard: LifeGuard,
buffer_tracker: Mutex<BufferTracker>,
pub(crate) texture_tracker: Mutex<TextureTracker>,
pub(crate) trackers: Mutex<TrackerSet>,
mem_props: hal::MemoryProperties,
pub(crate) render_passes: Mutex<HashMap<RenderPassKey, B::RenderPass>>,
pub(crate) framebuffers: Mutex<HashMap<FramebufferKey, B::Framebuffer>>,
@ -264,8 +267,7 @@ impl<B: hal::Backend> Device<B> {
com_allocator: command::CommandAllocator::new(queue_group.family()),
queue_group,
life_guard,
buffer_tracker: Mutex::new(BufferTracker::new()),
texture_tracker: Mutex::new(TextureTracker::new()),
trackers: Mutex::new(TrackerSet::new()),
mem_props,
render_passes: Mutex::new(HashMap::new()),
framebuffers: Mutex::new(HashMap::new()),
@ -343,12 +345,10 @@ pub fn device_track_buffer(
let query = HUB.devices
.read()
.get(device_id)
.buffer_tracker
.trackers
.lock()
.query(
&Stored { value: buffer_id, ref_count },
resource::BufferUsageFlags::empty(),
);
.buffers
.query(buffer_id, &ref_count, resource::BufferUsageFlags::empty());
assert!(query.initialized);
}
@ -458,12 +458,10 @@ pub fn device_track_texture(
let query = HUB.devices
.read()
.get(device_id)
.texture_tracker
.trackers
.lock()
.query(
&Stored { value: texture_id, ref_count },
resource::TextureUsageFlags::UNINITIALIZED,
);
.textures
.query(texture_id, &ref_count, resource::TextureUsageFlags::UNINITIALIZED);
assert!(query.initialized);
}
@ -520,6 +518,26 @@ pub fn texture_create_view(
}
}
pub fn device_track_view(
texture_id: TextureId,
view_id: BufferId,
ref_count: RefCount,
) {
let device_id = HUB.textures
.read()
.get(texture_id)
.device_id
.value;
let initialized = HUB.devices
.read()
.get(device_id)
.trackers
.lock()
.views
.query(view_id, &ref_count);
assert!(initialized);
}
#[cfg(feature = "local")]
#[no_mangle]
pub extern "C" fn wgpu_texture_create_view(
@ -527,7 +545,11 @@ pub extern "C" fn wgpu_texture_create_view(
desc: &resource::TextureViewDescriptor,
) -> TextureViewId {
let view = texture_create_view(texture_id, desc);
HUB.texture_views.register(view)
let texture_id = view.texture_id.value;
let ref_count = view.life_guard.ref_count.clone();
let id = HUB.texture_views.register(view);
device_track_view(texture_id, id, ref_count);
id
}
pub fn texture_create_default_view(
@ -537,8 +559,10 @@ pub fn texture_create_default_view(
let texture = texture_guard.get(texture_id);
let view_kind = match texture.kind {
hal::image::Kind::D1(..) => hal::image::ViewKind::D1,
hal::image::Kind::D2(..) => hal::image::ViewKind::D2, //TODO: array
hal::image::Kind::D1(_, 1) => hal::image::ViewKind::D1,
hal::image::Kind::D1(..) => hal::image::ViewKind::D1Array,
hal::image::Kind::D2(_, _, 1, _) => hal::image::ViewKind::D2,
hal::image::Kind::D2(..) => hal::image::ViewKind::D2Array,
hal::image::Kind::D3(..) => hal::image::ViewKind::D3,
};
@ -575,7 +599,11 @@ pub fn texture_create_default_view(
#[no_mangle]
pub extern "C" fn wgpu_texture_create_default_view(texture_id: TextureId) -> TextureViewId {
let view = texture_create_default_view(texture_id);
HUB.texture_views.register(view)
let texture_id = view.texture_id.value;
let ref_count = view.life_guard.ref_count.clone();
let id = HUB.texture_views.register(view);
device_track_view(texture_id, id, ref_count);
id
}
#[no_mangle]
@ -679,7 +707,7 @@ pub fn device_create_bind_group_layout(
hal::pso::DescriptorSetLayoutBinding {
binding: binding.binding,
ty: conv::map_binding_type(binding.ty),
count: bindings.len(),
count: 1, //TODO: consolidate
stage_flags: conv::map_shader_stage_flags(binding.visibility),
immutable_samplers: false, // TODO
}
@ -771,12 +799,11 @@ pub fn device_create_bind_group(
//TODO: group writes into contiguous sections
let mut writes = Vec::new();
let mut used_buffers = BufferTracker::new();
let mut used_textures = TextureTracker::new();
let mut used = TrackerSet::new();
for b in bindings {
let descriptor = match b.resource {
binding_model::BindingResource::Buffer(ref bb) => {
let buffer = used_buffers
let buffer = used.buffers
.get_with_extended_usage(
&*buffer_guard,
bb.buffer,
@ -792,7 +819,8 @@ pub fn device_create_bind_group(
}
binding_model::BindingResource::TextureView(id) => {
let view = texture_view_guard.get(id);
used_textures
used.views.query(id, &view.life_guard.ref_count);
used.textures
.transit(
view.texture_id.value,
&view.texture_id.ref_count,
@ -820,8 +848,7 @@ pub fn device_create_bind_group(
raw: desc_set,
layout_id: WeaklyStored(desc.layout),
life_guard: LifeGuard::new(),
used_buffers,
used_textures,
used,
}
}
@ -916,8 +943,7 @@ pub extern "C" fn wgpu_queue_submit(
.life_guard
.submission_index
.fetch_add(1, Ordering::Relaxed);
let mut buffer_tracker = device.buffer_tracker.lock();
let mut texture_tracker = device.texture_tracker.lock();
let mut trackers = device.trackers.lock();
//TODO: if multiple command buffers are submitted, we can re-use the last
// native command buffer of the previous chain instead of always creating
@ -934,14 +960,14 @@ pub extern "C" fn wgpu_queue_submit(
// update submission IDs
comb.life_guard.submission_index
.store(old_submit_index, Ordering::Release);
for id in comb.buffer_tracker.used() {
for id in comb.trackers.buffers.used() {
buffer_guard
.get(id)
.life_guard
.submission_index
.store(old_submit_index, Ordering::Release);
}
for id in comb.texture_tracker.used() {
for id in comb.trackers.textures.used() {
texture_guard
.get(id)
.life_guard
@ -958,13 +984,15 @@ pub extern "C" fn wgpu_queue_submit(
);
}
//TODO: fix the consume
let TrackerSet { ref mut buffers, ref mut textures, ref mut views } = *trackers;
command::CommandBuffer::insert_barriers(
&mut transit,
buffer_tracker.consume_by_replace(&comb.buffer_tracker),
texture_tracker.consume_by_replace(&comb.texture_tracker),
buffers.consume_by_replace(&comb.trackers.buffers),
textures.consume_by_replace(&comb.trackers.textures),
&*buffer_guard,
&*texture_guard,
);
views.consume(&comb.trackers.views);
unsafe {
transit.finish();
}
@ -1014,7 +1042,7 @@ pub extern "C" fn wgpu_queue_submit(
let last_done = {
let mut destroyed = device.destroyed.lock();
destroyed.triage_referenced(&mut *buffer_tracker, &mut *texture_tracker);
destroyed.triage_referenced(&mut *trackers);
let last_done = destroyed.cleanup(&device.raw);
destroyed.active.push(ActiveSubmission {
@ -1435,6 +1463,7 @@ fn swap_chain_populate_textures(
.unwrap();
let device_guard = HUB.devices.read();
let device = device_guard.get(swap_chain.device_id.value);
let mut trackers = device.trackers.lock();
for (i, mut texture) in textures.into_iter().enumerate() {
let format = texture.format;
@ -1460,9 +1489,11 @@ fn swap_chain_populate_textures(
ref_count: texture.life_guard.ref_count.clone(),
value: HUB.textures.register(texture),
};
device.texture_tracker
.lock()
.query(&texture_id, resource::TextureUsageFlags::UNINITIALIZED);
trackers.textures.query(
texture_id.value,
&texture_id.ref_count,
resource::TextureUsageFlags::UNINITIALIZED,
);
let view = resource::TextureView {
raw: view_raw,
@ -1473,12 +1504,18 @@ fn swap_chain_populate_textures(
is_owned_by_swap_chain: true,
life_guard: LifeGuard::new(),
};
let view_id = Stored {
ref_count: view.life_guard.ref_count.clone(),
value: HUB.texture_views.register(view),
};
trackers.views.query(
view_id.value,
&view_id.ref_count,
);
swap_chain.frames.push(swap_chain::Frame {
texture_id,
view_id: Stored {
ref_count: view.life_guard.ref_count.clone(),
value: HUB.texture_views.register(view),
},
view_id,
fence: device.raw.create_fence(true).unwrap(),
sem_available: device.raw.create_semaphore().unwrap(),
sem_present: device.raw.create_semaphore().unwrap(),
@ -1507,6 +1544,8 @@ pub extern "C" fn wgpu_device_create_swap_chain(
ref_count: outdated_view.life_guard.ref_count.clone(),
value: HUB.texture_views.register(outdated_view),
};
device_track_view(texture_id.value, view_id.value, view_id.ref_count.clone());
swap_chain::OutdatedFrame {
texture_id,
view_id,
@ -1532,8 +1571,9 @@ pub extern "C" fn wgpu_buffer_set_sub_data(
//Note: this is just doing `update_buffer`, which is limited to 64KB
trace!("transit {:?} to transfer dst", buffer_id);
let barrier = device.buffer_tracker
let barrier = device.trackers
.lock()
.buffers
.transit(
buffer_id,
&buffer.life_guard.ref_count,
@ -1581,3 +1621,8 @@ pub extern "C" fn wgpu_buffer_set_sub_data(
device.com_allocator.after_submit(comb);
}
#[no_mangle]
pub extern "C" fn wgpu_device_destroy(device_id: BufferId) {
HUB.devices.unregister(device_id);
}

View File

@ -51,6 +51,10 @@ type SubmissionIndex = usize;
#[derive(Debug)]
pub struct RefCount(ptr::NonNull<AtomicUsize>);
unsafe impl Send for RefCount {}
unsafe impl Sync for RefCount {}
impl RefCount {
const MAX: usize = 1 << 24;
@ -80,10 +84,6 @@ struct LifeGuard {
submission_index: AtomicUsize,
}
//TODO: reconsider this
unsafe impl Send for LifeGuard {}
unsafe impl Sync for LifeGuard {}
impl LifeGuard {
fn new() -> Self {
let bx = Box::new(AtomicUsize::new(1));
@ -100,9 +100,6 @@ struct Stored<T> {
ref_count: RefCount,
}
unsafe impl<T> Send for Stored<T> {}
unsafe impl<T> Sync for Stored<T> {}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
struct WeaklyStored<T>(T);

View File

@ -138,12 +138,13 @@ pub struct TextureViewDescriptor {
pub struct TextureView<B: hal::Backend> {
pub(crate) raw: B::ImageView,
pub(crate) texture_id: Stored<TextureId>,
//TODO: store device_id for quick access?
pub(crate) format: TextureFormat,
pub(crate) extent: hal::image::Extent,
pub(crate) samples: hal::image::NumSamples,
pub(crate) is_owned_by_swap_chain: bool,
#[cfg_attr(not(feature = "local"), allow(dead_code))]
pub(crate) life_guard: LifeGuard, //TODO: use
pub(crate) life_guard: LifeGuard,
}
#[repr(C)]

View File

@ -179,8 +179,9 @@ pub extern "C" fn wgpu_swap_chain_present(
//TODO: support for swapchain being sampled or read by the shader?
trace!("transit {:?} to present", frame.texture_id.value);
let barrier = device.texture_tracker
let barrier = device.trackers
.lock()
.textures
.transit(
frame.texture_id.value,
&texture.life_guard.ref_count,

View File

@ -1,14 +1,18 @@
use crate::hub::{Id, Storage};
use crate::resource::{BufferUsageFlags, TextureUsageFlags};
use crate::{BufferId, RefCount, Stored, TextureId, WeaklyStored};
use crate::{
RefCount, WeaklyStored,
BufferId, TextureId, TextureViewId,
};
use std::borrow::Borrow;
use std::collections::hash_map::{Entry, HashMap};
use std::collections::hash_map::Entry;
use std::hash::Hash;
use std::mem;
use std::ops::{BitOr, Range};
use bitflags::bitflags;
use hal::backend::FastHashMap;
#[derive(Clone, Debug, PartialEq)]
@ -70,20 +74,38 @@ struct Track<U> {
last: U,
}
unsafe impl<U> Send for Track<U> {}
unsafe impl<U> Sync for Track<U> {}
//TODO: consider having `I` as an associated type of `U`?
pub struct Tracker<I, U> {
map: HashMap<WeaklyStored<I>, Track<U>>,
map: FastHashMap<WeaklyStored<I>, Track<U>>,
}
pub type BufferTracker = Tracker<BufferId, BufferUsageFlags>;
pub type TextureTracker = Tracker<TextureId, TextureUsageFlags>;
pub struct DummyTracker<I> {
map: FastHashMap<WeaklyStored<I>, RefCount>,
}
pub type TextureViewTracker = DummyTracker<TextureViewId>;
impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<I, U> {
pub struct TrackerSet {
pub buffers: BufferTracker,
pub textures: TextureTracker,
pub views: TextureViewTracker,
//TODO: samplers
}
impl TrackerSet {
pub fn new() -> Self {
Tracker {
map: HashMap::new(),
TrackerSet {
buffers: BufferTracker::new(),
textures: TextureTracker::new(),
views: TextureViewTracker::new(),
}
}
}
impl<I: Clone + Hash + Eq> DummyTracker<I> {
pub fn new() -> Self {
DummyTracker {
map: FastHashMap::default(),
}
}
@ -93,11 +115,42 @@ impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialE
}
/// Get the last usage on a resource.
pub(crate) fn query(&mut self, stored: &Stored<I>, default: U) -> Query<U> {
match self.map.entry(WeaklyStored(stored.value.clone())) {
pub(crate) fn query(&mut self, id: I, ref_count: &RefCount) -> bool {
match self.map.entry(WeaklyStored(id)) {
Entry::Vacant(e) => {
e.insert(ref_count.clone());
true
}
Entry::Occupied(_) => false,
}
}
/// Consume another tacker.
pub fn consume(&mut self, other: &Self) {
for (id, ref_count) in &other.map {
self.query(id.0.clone(), ref_count);
}
}
}
impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<I, U> {
pub fn new() -> Self {
Tracker {
map: FastHashMap::default(),
}
}
/// Remove an id from the tracked map.
pub(crate) fn remove(&mut self, id: I) -> bool {
self.map.remove(&WeaklyStored(id)).is_some()
}
/// Get the last usage on a resource.
pub(crate) fn query(&mut self, id: I, ref_count: &RefCount, default: U) -> Query<U> {
match self.map.entry(WeaklyStored(id)) {
Entry::Vacant(e) => {
e.insert(Track {
ref_count: stored.ref_count.clone(),
ref_count: ref_count.clone(),
init: default,
last: default,
});

View File

@ -16,6 +16,7 @@ license = "MPL-2.0"
[features]
default = []
metal-auto-capture = ["wgpu-native/metal-auto-capture"]
metal = ["wgpu-native/gfx-backend-metal"]
dx11 = ["wgpu-native/gfx-backend-dx11"]
dx12 = ["wgpu-native/gfx-backend-dx12"]

View File

@ -443,6 +443,14 @@ impl Device {
}
}
impl Drop for Device {
fn drop(&mut self) {
//TODO: make this work in general
#[cfg(feature = "metal-auto-capture")]
wgn::wgpu_device_destroy(self.id);
}
}
impl Buffer {
pub fn set_sub_data(&self, offset: u32, data: &[u8]) {
wgn::wgpu_buffer_set_sub_data(self.id, offset, data.len() as u32, data.as_ptr());