mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Add reference counting to objects
This commit is contained in:
parent
c1eb437b25
commit
39186c9c7b
@ -1,5 +1,5 @@
|
|||||||
use super::CommandBuffer;
|
use super::CommandBuffer;
|
||||||
use {DeviceId, Stored};
|
use {DeviceId, LifeGuard, Stored};
|
||||||
use track::{Tracker};
|
use track::{Tracker};
|
||||||
|
|
||||||
use hal::command::RawCommandBuffer;
|
use hal::command::RawCommandBuffer;
|
||||||
@ -61,8 +61,8 @@ impl<B: hal::Backend> CommandAllocator<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate(
|
pub(crate) fn allocate(
|
||||||
&self, device_id: DeviceId, device: &B::Device
|
&self, device_id: Stored<DeviceId>, device: &B::Device
|
||||||
) -> CommandBuffer<B> {
|
) -> CommandBuffer<B> {
|
||||||
let thread_id = thread::current().id();
|
let thread_id = thread::current().id();
|
||||||
let mut inner = self.inner.lock().unwrap();
|
let mut inner = self.inner.lock().unwrap();
|
||||||
@ -90,7 +90,8 @@ impl<B: hal::Backend> CommandAllocator<B> {
|
|||||||
raw: vec![init],
|
raw: vec![init],
|
||||||
fence,
|
fence,
|
||||||
recorded_thread_id: thread_id,
|
recorded_thread_id: thread_id,
|
||||||
device_id: Stored(device_id),
|
device_id,
|
||||||
|
life_guard: LifeGuard::new(),
|
||||||
buffer_tracker: Tracker::new(),
|
buffer_tracker: Tracker::new(),
|
||||||
texture_tracker: Tracker::new(),
|
texture_tracker: Tracker::new(),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,10 +16,10 @@ pub struct ComputePass<B: hal::Backend> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<B: hal::Backend> ComputePass<B> {
|
impl<B: hal::Backend> ComputePass<B> {
|
||||||
pub fn new(raw: B::CommandBuffer, cmb_id: CommandBufferId) -> Self {
|
pub(crate) fn new(raw: B::CommandBuffer, cmb_id: Stored<CommandBufferId>) -> Self {
|
||||||
ComputePass {
|
ComputePass {
|
||||||
raw,
|
raw,
|
||||||
cmb_id: Stored(cmb_id),
|
cmb_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,10 +34,10 @@ pub extern "C" fn wgpu_compute_pass_end_pass(
|
|||||||
|
|
||||||
HUB.command_buffers
|
HUB.command_buffers
|
||||||
.lock()
|
.lock()
|
||||||
.get_mut(pass.cmb_id.0)
|
.get_mut(pass.cmb_id.value)
|
||||||
.raw
|
.raw
|
||||||
.push(pass.raw);
|
.push(pass.raw);
|
||||||
pass.cmb_id.0
|
pass.cmb_id.value
|
||||||
}
|
}
|
||||||
|
|
||||||
pub extern "C" fn wgpu_compute_pass_set_bind_group(
|
pub extern "C" fn wgpu_compute_pass_set_bind_group(
|
||||||
|
|||||||
@ -2,7 +2,7 @@ mod allocator;
|
|||||||
mod compute;
|
mod compute;
|
||||||
mod render;
|
mod render;
|
||||||
|
|
||||||
pub use self::allocator::CommandAllocator;
|
pub(crate) use self::allocator::CommandAllocator;
|
||||||
pub use self::compute::*;
|
pub use self::compute::*;
|
||||||
pub use self::render::*;
|
pub use self::render::*;
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ use hal::{self, Device};
|
|||||||
use hal::command::RawCommandBuffer;
|
use hal::command::RawCommandBuffer;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
B, Color, Origin3d, Stored, BufferUsageFlags, TextureUsageFlags,
|
B, Color, LifeGuard, Origin3d, Stored, BufferUsageFlags, TextureUsageFlags, WeaklyStored,
|
||||||
BufferId, CommandBufferId, ComputePassId, DeviceId, RenderPassId, TextureId, TextureViewId,
|
BufferId, CommandBufferId, ComputePassId, DeviceId, RenderPassId, TextureId, TextureViewId,
|
||||||
};
|
};
|
||||||
use conv;
|
use conv;
|
||||||
@ -83,6 +83,7 @@ pub struct CommandBuffer<B: hal::Backend> {
|
|||||||
fence: B::Fence,
|
fence: B::Fence,
|
||||||
recorded_thread_id: ThreadId,
|
recorded_thread_id: ThreadId,
|
||||||
device_id: Stored<DeviceId>,
|
device_id: Stored<DeviceId>,
|
||||||
|
life_guard: LifeGuard,
|
||||||
pub(crate) buffer_tracker: BufferTracker,
|
pub(crate) buffer_tracker: BufferTracker,
|
||||||
pub(crate) texture_tracker: TextureTracker,
|
pub(crate) texture_tracker: TextureTracker,
|
||||||
}
|
}
|
||||||
@ -139,7 +140,7 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass(
|
|||||||
let mut cmb_guard = HUB.command_buffers.lock();
|
let mut cmb_guard = HUB.command_buffers.lock();
|
||||||
let cmb = cmb_guard.get_mut(command_buffer_id);
|
let cmb = cmb_guard.get_mut(command_buffer_id);
|
||||||
let device_guard = HUB.devices.lock();
|
let device_guard = HUB.devices.lock();
|
||||||
let device = device_guard.get(cmb.device_id.0);
|
let device = device_guard.get(cmb.device_id.value);
|
||||||
let view_guard = HUB.texture_views.lock();
|
let view_guard = HUB.texture_views.lock();
|
||||||
|
|
||||||
let mut current_comb = device.com_allocator.extend(cmb);
|
let mut current_comb = device.com_allocator.extend(cmb);
|
||||||
@ -160,7 +161,7 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass(
|
|||||||
} else {
|
} else {
|
||||||
extent = Some(view.extent);
|
extent = Some(view.extent);
|
||||||
}
|
}
|
||||||
let query = tracker.query(view.texture_id.0, TextureUsageFlags::empty());
|
let query = tracker.query(&view.texture_id, TextureUsageFlags::empty());
|
||||||
let (_, layout) = conv::map_texture_state(
|
let (_, layout) = conv::map_texture_state(
|
||||||
query.usage,
|
query.usage,
|
||||||
hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL,
|
hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL,
|
||||||
@ -185,7 +186,7 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass(
|
|||||||
} else {
|
} else {
|
||||||
extent = Some(view.extent);
|
extent = Some(view.extent);
|
||||||
}
|
}
|
||||||
let query = tracker.query(view.texture_id.0, TextureUsageFlags::empty());
|
let query = tracker.query(&view.texture_id, TextureUsageFlags::empty());
|
||||||
let (_, layout) = conv::map_texture_state(query.usage, hal::format::Aspects::COLOR);
|
let (_, layout) = conv::map_texture_state(query.usage, hal::format::Aspects::COLOR);
|
||||||
hal::pass::Attachment {
|
hal::pass::Attachment {
|
||||||
format: Some(conv::map_texture_format(view.format)),
|
format: Some(conv::map_texture_format(view.format)),
|
||||||
@ -234,8 +235,8 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass(
|
|||||||
let fb_key = FramebufferKey {
|
let fb_key = FramebufferKey {
|
||||||
attachments: desc.color_attachments
|
attachments: desc.color_attachments
|
||||||
.iter()
|
.iter()
|
||||||
.map(|at| Stored(at.attachment))
|
.map(|at| WeaklyStored(at.attachment))
|
||||||
.chain(desc.depth_stencil_attachment.as_ref().map(|at| Stored(at.attachment)))
|
.chain(desc.depth_stencil_attachment.as_ref().map(|at| WeaklyStored(at.attachment)))
|
||||||
.collect(),
|
.collect(),
|
||||||
};
|
};
|
||||||
let framebuffer = match framebuffer_cache.entry(fb_key) {
|
let framebuffer = match framebuffer_cache.entry(fb_key) {
|
||||||
@ -246,7 +247,7 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass(
|
|||||||
.key()
|
.key()
|
||||||
.attachments
|
.attachments
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&Stored(id)| &view_guard.get(id).raw);
|
.map(|&WeaklyStored(id)| &view_guard.get(id).raw);
|
||||||
|
|
||||||
device.raw
|
device.raw
|
||||||
.create_framebuffer(&render_pass, attachments, extent.unwrap())
|
.create_framebuffer(&render_pass, attachments, extent.unwrap())
|
||||||
@ -289,7 +290,10 @@ pub extern "C" fn wgpu_command_buffer_begin_render_pass(
|
|||||||
.lock()
|
.lock()
|
||||||
.register(RenderPass::new(
|
.register(RenderPass::new(
|
||||||
current_comb,
|
current_comb,
|
||||||
command_buffer_id,
|
Stored {
|
||||||
|
value: command_buffer_id,
|
||||||
|
ref_count: cmb.life_guard.ref_count.clone(),
|
||||||
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,8 +305,12 @@ pub extern "C" fn wgpu_command_buffer_begin_compute_pass(
|
|||||||
let cmb = cmb_guard.get_mut(command_buffer_id);
|
let cmb = cmb_guard.get_mut(command_buffer_id);
|
||||||
|
|
||||||
let raw = cmb.raw.pop().unwrap();
|
let raw = cmb.raw.pop().unwrap();
|
||||||
|
let stored = Stored {
|
||||||
|
value: command_buffer_id,
|
||||||
|
ref_count: cmb.life_guard.ref_count.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
HUB.compute_passes
|
HUB.compute_passes
|
||||||
.lock()
|
.lock()
|
||||||
.register(ComputePass::new(raw, command_buffer_id))
|
.register(ComputePass::new(raw, stored))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,13 +17,13 @@ pub struct RenderPass<B: hal::Backend> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<B: hal::Backend> RenderPass<B> {
|
impl<B: hal::Backend> RenderPass<B> {
|
||||||
pub fn new(
|
pub(crate) fn new(
|
||||||
raw: B::CommandBuffer,
|
raw: B::CommandBuffer,
|
||||||
cmb_id: CommandBufferId,
|
cmb_id: Stored<CommandBufferId>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
RenderPass {
|
RenderPass {
|
||||||
raw,
|
raw,
|
||||||
cmb_id: Stored(cmb_id),
|
cmb_id,
|
||||||
buffer_tracker: BufferTracker::new(),
|
buffer_tracker: BufferTracker::new(),
|
||||||
texture_tracker: TextureTracker::new(),
|
texture_tracker: TextureTracker::new(),
|
||||||
}
|
}
|
||||||
@ -40,7 +40,7 @@ pub extern "C" fn wgpu_render_pass_end_pass(
|
|||||||
pass.raw.end_render_pass();
|
pass.raw.end_render_pass();
|
||||||
|
|
||||||
let mut cmb_guard = HUB.command_buffers.lock();
|
let mut cmb_guard = HUB.command_buffers.lock();
|
||||||
let cmb = cmb_guard.get_mut(pass.cmb_id.0);
|
let cmb = cmb_guard.get_mut(pass.cmb_id.value);
|
||||||
|
|
||||||
if let Some(ref mut last) = cmb.raw.last_mut() {
|
if let Some(ref mut last) = cmb.raw.last_mut() {
|
||||||
CommandBuffer::insert_barriers(
|
CommandBuffer::insert_barriers(
|
||||||
@ -52,5 +52,5 @@ pub extern "C" fn wgpu_render_pass_end_pass(
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmb.raw.push(pass.raw);
|
cmb.raw.push(pass.raw);
|
||||||
pass.cmb_id.0
|
pass.cmb_id.value
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,9 @@ use {back, binding_model, command, conv, pipeline, resource};
|
|||||||
use registry::{HUB, Items, Registry};
|
use registry::{HUB, Items, Registry};
|
||||||
use track::{BufferTracker, TextureTracker};
|
use track::{BufferTracker, TextureTracker};
|
||||||
use {
|
use {
|
||||||
CommandBuffer, Stored, TextureUsageFlags,
|
CommandBuffer, LifeGuard, RefCount, Stored, SubmissionIndex, WeaklyStored,
|
||||||
BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId,
|
TextureUsageFlags,
|
||||||
|
BindGroupLayoutId, BlendStateId, BufferId, CommandBufferId, DepthStencilStateId,
|
||||||
DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId,
|
DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId,
|
||||||
TextureId, TextureViewId,
|
TextureId, TextureViewId,
|
||||||
};
|
};
|
||||||
@ -16,6 +17,7 @@ use rendy_memory::{allocator, Config, Heaps};
|
|||||||
use std::{ffi, slice};
|
use std::{ffi, slice};
|
||||||
use std::collections::hash_map::{Entry, HashMap};
|
use std::collections::hash_map::{Entry, HashMap};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Hash, PartialEq)]
|
#[derive(Hash, PartialEq)]
|
||||||
@ -26,21 +28,67 @@ impl Eq for RenderPassKey {}
|
|||||||
|
|
||||||
#[derive(Hash, PartialEq)]
|
#[derive(Hash, PartialEq)]
|
||||||
pub(crate) struct FramebufferKey {
|
pub(crate) struct FramebufferKey {
|
||||||
pub attachments: Vec<Stored<TextureViewId>>,
|
pub attachments: Vec<WeaklyStored<TextureViewId>>,
|
||||||
}
|
}
|
||||||
impl Eq for FramebufferKey {}
|
impl Eq for FramebufferKey {}
|
||||||
|
|
||||||
|
enum Resource {
|
||||||
|
Buffer(BufferId),
|
||||||
|
Texture(TextureId),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ActiveFrame<B: hal::Backend> {
|
||||||
|
submission_index: SubmissionIndex,
|
||||||
|
fence: B::Fence,
|
||||||
|
resources: Vec<Resource>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DestroyedResources<B: hal::Backend> {
|
||||||
|
/// Resources that are destroyed by the user but still referenced by
|
||||||
|
/// other objects or command buffers.
|
||||||
|
referenced: Vec<(Resource, RefCount)>,
|
||||||
|
/// Resources that are not referenced any more but still used by GPU.
|
||||||
|
/// Grouped by frames associated with a fence and a submission index.
|
||||||
|
active: Vec<ActiveFrame<B>>,
|
||||||
|
/// Resources that are neither referenced or used, just pending
|
||||||
|
/// actual deletion.
|
||||||
|
free: Vec<Resource>,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<B: hal::Backend> Send for DestroyedResources<B> {}
|
||||||
|
unsafe impl<B: hal::Backend> Sync for DestroyedResources<B> {}
|
||||||
|
|
||||||
|
impl<B: hal::Backend> DestroyedResources<B> {
|
||||||
|
fn add(&mut self, resource: Resource, life_guard: &LifeGuard) {
|
||||||
|
if life_guard.ref_count.load() == 1 {
|
||||||
|
let sub_index = life_guard.submission_index.load(Ordering::Acquire);
|
||||||
|
match self.active.iter_mut().find(|af| af.submission_index == sub_index) {
|
||||||
|
Some(frame) => {
|
||||||
|
frame.resources.push(resource);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.free.push(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.referenced.push((resource, life_guard.ref_count.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Device<B: hal::Backend> {
|
pub struct Device<B: hal::Backend> {
|
||||||
pub(crate) raw: B::Device,
|
pub(crate) raw: B::Device,
|
||||||
queue_group: hal::QueueGroup<B, hal::General>,
|
queue_group: hal::QueueGroup<B, hal::General>,
|
||||||
mem_allocator: Heaps<B::Memory>,
|
mem_allocator: Heaps<B::Memory>,
|
||||||
pub(crate) com_allocator: command::CommandAllocator<B>,
|
pub(crate) com_allocator: command::CommandAllocator<B>,
|
||||||
|
life_guard: LifeGuard,
|
||||||
buffer_tracker: Mutex<BufferTracker>,
|
buffer_tracker: Mutex<BufferTracker>,
|
||||||
texture_tracker: Mutex<TextureTracker>,
|
texture_tracker: Mutex<TextureTracker>,
|
||||||
mem_props: hal::MemoryProperties,
|
mem_props: hal::MemoryProperties,
|
||||||
pub(crate) render_passes: Mutex<HashMap<RenderPassKey, B::RenderPass>>,
|
pub(crate) render_passes: Mutex<HashMap<RenderPassKey, B::RenderPass>>,
|
||||||
pub(crate) framebuffers: Mutex<HashMap<FramebufferKey, B::Framebuffer>>,
|
pub(crate) framebuffers: Mutex<HashMap<FramebufferKey, B::Framebuffer>>,
|
||||||
|
last_submission_index: SubmissionIndex,
|
||||||
|
destroyed: Mutex<DestroyedResources<B>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: hal::Backend> Device<B> {
|
impl<B: hal::Backend> Device<B> {
|
||||||
@ -75,11 +123,18 @@ impl<B: hal::Backend> Device<B> {
|
|||||||
mem_allocator,
|
mem_allocator,
|
||||||
com_allocator: command::CommandAllocator::new(queue_group.family()),
|
com_allocator: command::CommandAllocator::new(queue_group.family()),
|
||||||
queue_group,
|
queue_group,
|
||||||
|
life_guard: LifeGuard::new(),
|
||||||
buffer_tracker: Mutex::new(BufferTracker::new()),
|
buffer_tracker: Mutex::new(BufferTracker::new()),
|
||||||
texture_tracker: Mutex::new(TextureTracker::new()),
|
texture_tracker: Mutex::new(TextureTracker::new()),
|
||||||
mem_props,
|
mem_props,
|
||||||
render_passes: Mutex::new(HashMap::new()),
|
render_passes: Mutex::new(HashMap::new()),
|
||||||
framebuffers: Mutex::new(HashMap::new()),
|
framebuffers: Mutex::new(HashMap::new()),
|
||||||
|
last_submission_index: 0,
|
||||||
|
destroyed: Mutex::new(DestroyedResources {
|
||||||
|
referenced: Vec::new(),
|
||||||
|
active: Vec::new(),
|
||||||
|
free: Vec::new(),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,19 +191,28 @@ pub extern "C" fn wgpu_device_create_texture(
|
|||||||
layers: 0 .. 1, //TODO
|
layers: 0 .. 1, //TODO
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let life_guard = LifeGuard::new();
|
||||||
|
let ref_count = life_guard.ref_count.clone();
|
||||||
let id = HUB.textures
|
let id = HUB.textures
|
||||||
.lock()
|
.lock()
|
||||||
.register(resource::Texture {
|
.register(resource::Texture {
|
||||||
raw: bound_image,
|
raw: bound_image,
|
||||||
device_id: Stored(device_id),
|
device_id: Stored {
|
||||||
|
value: device_id,
|
||||||
|
ref_count: device.life_guard.ref_count.clone(),
|
||||||
|
},
|
||||||
kind,
|
kind,
|
||||||
format: desc.format,
|
format: desc.format,
|
||||||
full_range,
|
full_range,
|
||||||
|
life_guard,
|
||||||
});
|
});
|
||||||
let query = device.texture_tracker
|
let query = device.texture_tracker
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.query(id, TextureUsageFlags::WRITE_ALL);
|
.query(
|
||||||
|
&Stored { value: id, ref_count },
|
||||||
|
TextureUsageFlags::WRITE_ALL,
|
||||||
|
);
|
||||||
assert!(query.initialized);
|
assert!(query.initialized);
|
||||||
|
|
||||||
id
|
id
|
||||||
@ -164,7 +228,7 @@ pub extern "C" fn wgpu_texture_create_texture_view(
|
|||||||
|
|
||||||
let raw = HUB.devices
|
let raw = HUB.devices
|
||||||
.lock()
|
.lock()
|
||||||
.get(texture.device_id.0)
|
.get(texture.device_id.value)
|
||||||
.raw
|
.raw
|
||||||
.create_image_view(
|
.create_image_view(
|
||||||
&texture.raw,
|
&texture.raw,
|
||||||
@ -183,10 +247,14 @@ pub extern "C" fn wgpu_texture_create_texture_view(
|
|||||||
.lock()
|
.lock()
|
||||||
.register(resource::TextureView {
|
.register(resource::TextureView {
|
||||||
raw,
|
raw,
|
||||||
texture_id: Stored(texture_id),
|
texture_id: Stored {
|
||||||
|
value: texture_id,
|
||||||
|
ref_count: texture.life_guard.ref_count.clone(),
|
||||||
|
},
|
||||||
format: texture.format,
|
format: texture.format,
|
||||||
extent: texture.kind.extent(),
|
extent: texture.kind.extent(),
|
||||||
samples: texture.kind.num_samples(),
|
samples: texture.kind.num_samples(),
|
||||||
|
life_guard: LifeGuard::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +273,7 @@ pub extern "C" fn wgpu_texture_create_default_texture_view(
|
|||||||
|
|
||||||
let raw = HUB.devices
|
let raw = HUB.devices
|
||||||
.lock()
|
.lock()
|
||||||
.get(texture.device_id.0)
|
.get(texture.device_id.value)
|
||||||
.raw
|
.raw
|
||||||
.create_image_view(
|
.create_image_view(
|
||||||
&texture.raw,
|
&texture.raw,
|
||||||
@ -220,13 +288,38 @@ pub extern "C" fn wgpu_texture_create_default_texture_view(
|
|||||||
.lock()
|
.lock()
|
||||||
.register(resource::TextureView {
|
.register(resource::TextureView {
|
||||||
raw,
|
raw,
|
||||||
texture_id: Stored(texture_id),
|
texture_id: Stored {
|
||||||
|
value: texture_id,
|
||||||
|
ref_count: texture.life_guard.ref_count.clone(),
|
||||||
|
},
|
||||||
format: texture.format,
|
format: texture.format,
|
||||||
extent: texture.kind.extent(),
|
extent: texture.kind.extent(),
|
||||||
samples: texture.kind.num_samples(),
|
samples: texture.kind.num_samples(),
|
||||||
|
life_guard: LifeGuard::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn wgpu_texture_destroy(
|
||||||
|
texture_id: DeviceId,
|
||||||
|
) {
|
||||||
|
let texture_guard = HUB.textures.lock();
|
||||||
|
let texture = texture_guard.get(texture_id);
|
||||||
|
let device_guard = HUB.devices.lock();
|
||||||
|
device_guard
|
||||||
|
.get(texture.device_id.value)
|
||||||
|
.destroyed
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.add(Resource::Texture(texture_id), &texture.life_guard);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn wgpu_texture_view_destroy(
|
||||||
|
_texture_view_id: TextureViewId,
|
||||||
|
) {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn wgpu_device_create_bind_group_layout(
|
pub extern "C" fn wgpu_device_create_bind_group_layout(
|
||||||
@ -338,7 +431,11 @@ pub extern "C" fn wgpu_device_create_command_buffer(
|
|||||||
let device_guard = HUB.devices.lock();
|
let device_guard = HUB.devices.lock();
|
||||||
let device = device_guard.get(device_id);
|
let device = device_guard.get(device_id);
|
||||||
|
|
||||||
let mut cmd_buf = device.com_allocator.allocate(device_id, &device.raw);
|
let dev_stored = Stored {
|
||||||
|
value: device_id,
|
||||||
|
ref_count: device.life_guard.ref_count.clone(),
|
||||||
|
};
|
||||||
|
let mut cmd_buf = device.com_allocator.allocate(dev_stored, &device.raw);
|
||||||
cmd_buf.raw.last_mut().unwrap().begin(
|
cmd_buf.raw.last_mut().unwrap().begin(
|
||||||
hal::command::CommandBufferFlags::ONE_TIME_SUBMIT,
|
hal::command::CommandBufferFlags::ONE_TIME_SUBMIT,
|
||||||
hal::command::CommandBufferInheritanceInfo::default(),
|
hal::command::CommandBufferInheritanceInfo::default(),
|
||||||
|
|||||||
@ -43,12 +43,78 @@ pub use self::resource::*;
|
|||||||
use back::Backend as B;
|
use back::Backend as B;
|
||||||
use registry::Id;
|
use registry::Id;
|
||||||
|
|
||||||
#[derive(Debug, Hash, PartialEq, Eq)]
|
use std::ptr;
|
||||||
struct Stored<T>(T);
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
#[cfg(not(feature = "remote"))]
|
|
||||||
unsafe impl<T> Sync for Stored<T> {}
|
|
||||||
#[cfg(not(feature = "remote"))]
|
//#[cfg(not(feature = "remote"))]
|
||||||
|
//unsafe impl<T> Sync for Stored<T> {}
|
||||||
|
//#[cfg(not(feature = "remote"))]
|
||||||
|
//unsafe impl<T> Send for Stored<T> {}
|
||||||
|
|
||||||
|
type SubmissionIndex = usize;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct RefCount(ptr::NonNull<AtomicUsize>);
|
||||||
|
|
||||||
|
impl RefCount {
|
||||||
|
const MAX: usize = 1 << 24;
|
||||||
|
|
||||||
|
fn load(&self) -> usize {
|
||||||
|
unsafe { self.0.as_ref() }.load(Ordering::Acquire)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for RefCount {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
let old_size = unsafe { self.0.as_ref() }.fetch_add(1, Ordering::Relaxed);
|
||||||
|
assert!(old_size < Self::MAX);
|
||||||
|
RefCount(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for RefCount {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if unsafe { self.0.as_ref() }.fetch_sub(1, Ordering::Relaxed) == 1 {
|
||||||
|
let _ = unsafe { Box::from_raw(self.0.as_ptr()) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LifeGuard {
|
||||||
|
ref_count: RefCount,
|
||||||
|
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));
|
||||||
|
LifeGuard {
|
||||||
|
ref_count: RefCount(ptr::NonNull::new(Box::into_raw(bx)).unwrap()),
|
||||||
|
submission_index: AtomicUsize::new(0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Stored<T> {
|
||||||
|
value: T,
|
||||||
|
ref_count: RefCount,
|
||||||
|
}
|
||||||
|
|
||||||
unsafe impl<T> Send for Stored<T> {}
|
unsafe impl<T> Send for Stored<T> {}
|
||||||
|
unsafe impl<T> Sync for Stored<T> {}
|
||||||
|
|
||||||
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||||
|
struct WeaklyStored<T>(T);
|
||||||
|
|
||||||
|
unsafe impl<T> Send for WeaklyStored<T> {}
|
||||||
|
unsafe impl<T> Sync for WeaklyStored<T> {}
|
||||||
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use {
|
use {
|
||||||
Extent3d, Stored,
|
Extent3d, LifeGuard, Stored,
|
||||||
DeviceId, TextureId,
|
DeviceId, TextureId,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -32,6 +32,7 @@ pub(crate) struct Buffer<B: hal::Backend> {
|
|||||||
//pub raw: B::UnboundBuffer,
|
//pub raw: B::UnboundBuffer,
|
||||||
pub raw: B::Buffer,
|
pub raw: B::Buffer,
|
||||||
pub memory_properties: hal::memory::Properties,
|
pub memory_properties: hal::memory::Properties,
|
||||||
|
pub life_guard: LifeGuard,
|
||||||
// TODO: mapping, unmap()
|
// TODO: mapping, unmap()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,6 +83,7 @@ pub(crate) struct Texture<B: hal::Backend> {
|
|||||||
pub kind: hal::image::Kind,
|
pub kind: hal::image::Kind,
|
||||||
pub format: TextureFormat,
|
pub format: TextureFormat,
|
||||||
pub full_range: hal::image::SubresourceRange,
|
pub full_range: hal::image::SubresourceRange,
|
||||||
|
pub life_guard: LifeGuard,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -122,6 +124,7 @@ pub(crate) struct TextureView<B: hal::Backend> {
|
|||||||
pub format: TextureFormat,
|
pub format: TextureFormat,
|
||||||
pub extent: hal::image::Extent,
|
pub extent: hal::image::Extent,
|
||||||
pub samples: hal::image::NumSamples,
|
pub samples: hal::image::NumSamples,
|
||||||
|
pub life_guard: LifeGuard,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use {Stored, BufferId, TextureId};
|
use {RefCount, Stored, WeaklyStored, BufferId, TextureId};
|
||||||
use resource::{BufferUsageFlags, TextureUsageFlags};
|
use resource::{BufferUsageFlags, TextureUsageFlags};
|
||||||
|
|
||||||
use std::collections::hash_map::{Entry, HashMap};
|
use std::collections::hash_map::{Entry, HashMap};
|
||||||
@ -42,10 +42,18 @@ impl GenericUsage for TextureUsageFlags {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Track<U> {
|
||||||
|
ref_count: RefCount,
|
||||||
|
init: 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`?
|
//TODO: consider having `I` as an associated type of `U`?
|
||||||
pub struct Tracker<I, U> {
|
pub struct Tracker<I, U> {
|
||||||
map: HashMap<Stored<I>, Range<U>>,
|
map: HashMap<WeaklyStored<I>, Track<U>>,
|
||||||
}
|
}
|
||||||
pub type BufferTracker = Tracker<BufferId, BufferUsageFlags>;
|
pub type BufferTracker = Tracker<BufferId, BufferUsageFlags>;
|
||||||
pub type TextureTracker = Tracker<TextureId, TextureUsageFlags>;
|
pub type TextureTracker = Tracker<TextureId, TextureUsageFlags>;
|
||||||
@ -54,16 +62,22 @@ impl<
|
|||||||
I: Clone + Hash + Eq,
|
I: Clone + Hash + Eq,
|
||||||
U: Copy + GenericUsage + BitOr<Output = U> + PartialEq,
|
U: Copy + GenericUsage + BitOr<Output = U> + PartialEq,
|
||||||
> Tracker<I, U> {
|
> Tracker<I, U> {
|
||||||
pub fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
Tracker {
|
Tracker {
|
||||||
map: HashMap::new(),
|
map: HashMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn query(&mut self, id: I, default: U) -> Query<U> {
|
pub(crate) fn query(
|
||||||
match self.map.entry(Stored(id)) {
|
&mut self, stored: &Stored<I>, default: U
|
||||||
|
) -> Query<U> {
|
||||||
|
match self.map.entry(WeaklyStored(stored.value.clone())) {
|
||||||
Entry::Vacant(e) => {
|
Entry::Vacant(e) => {
|
||||||
e.insert(default .. default);
|
e.insert(Track {
|
||||||
|
ref_count: stored.ref_count.clone(),
|
||||||
|
init: default,
|
||||||
|
last: default,
|
||||||
|
});
|
||||||
Query {
|
Query {
|
||||||
usage: default,
|
usage: default,
|
||||||
initialized: true,
|
initialized: true,
|
||||||
@ -71,28 +85,34 @@ impl<
|
|||||||
}
|
}
|
||||||
Entry::Occupied(e) => {
|
Entry::Occupied(e) => {
|
||||||
Query {
|
Query {
|
||||||
usage: e.get().end,
|
usage: e.get().last,
|
||||||
initialized: false,
|
initialized: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transit(&mut self, id: I, usage: U, permit: TrackPermit) -> Result<Tracktion<U>, U> {
|
pub(crate) fn transit(
|
||||||
match self.map.entry(Stored(id)) {
|
&mut self, id: I, ref_count: &RefCount, usage: U, permit: TrackPermit
|
||||||
|
) -> Result<Tracktion<U>, U> {
|
||||||
|
match self.map.entry(WeaklyStored(id)) {
|
||||||
Entry::Vacant(e) => {
|
Entry::Vacant(e) => {
|
||||||
e.insert(usage .. usage);
|
e.insert(Track {
|
||||||
|
ref_count: ref_count.clone(),
|
||||||
|
init: usage,
|
||||||
|
last: usage,
|
||||||
|
});
|
||||||
Ok(Tracktion::Init)
|
Ok(Tracktion::Init)
|
||||||
}
|
}
|
||||||
Entry::Occupied(mut e) => {
|
Entry::Occupied(mut e) => {
|
||||||
let old = e.get().end;
|
let old = e.get().last;
|
||||||
if usage == old {
|
if usage == old {
|
||||||
Ok(Tracktion::Keep)
|
Ok(Tracktion::Keep)
|
||||||
} else if permit.contains(TrackPermit::EXTEND) && !(old | usage).is_exclusive() {
|
} else if permit.contains(TrackPermit::EXTEND) && !(old | usage).is_exclusive() {
|
||||||
e.get_mut().end = old | usage;
|
e.get_mut().last = old | usage;
|
||||||
Ok(Tracktion::Extend { old })
|
Ok(Tracktion::Extend { old })
|
||||||
} else if permit.contains(TrackPermit::REPLACE) {
|
} else if permit.contains(TrackPermit::REPLACE) {
|
||||||
e.get_mut().end = usage;
|
e.get_mut().last = usage;
|
||||||
Ok(Tracktion::Replace { old })
|
Ok(Tracktion::Replace { old })
|
||||||
} else {
|
} else {
|
||||||
Err(old)
|
Err(old)
|
||||||
@ -101,13 +121,15 @@ impl<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn consume<'a>(&'a mut self, other: &'a 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
|
other.map
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(move |(id, new)| match self.transit(id.0.clone(), new.end, TrackPermit::REPLACE) {
|
.flat_map(move |(id, new)| match self.transit(id.0.clone(), &new.ref_count, new.last, TrackPermit::REPLACE) {
|
||||||
Ok(Tracktion::Init) |
|
Ok(Tracktion::Init) |
|
||||||
Ok(Tracktion::Keep) => None,
|
Ok(Tracktion::Keep) => None,
|
||||||
Ok(Tracktion::Replace { old }) => Some((id.0.clone(), old .. new.end)),
|
Ok(Tracktion::Replace { old }) => Some((id.0.clone(), old .. new.last)),
|
||||||
Ok(Tracktion::Extend { .. }) |
|
Ok(Tracktion::Extend { .. }) |
|
||||||
Err(_) => panic!("Unable to consume a resource transition!"),
|
Err(_) => panic!("Unable to consume a resource transition!"),
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user