Epoch tracking of indices

This commit is contained in:
Dzmitry Malyshau 2019-02-25 22:25:34 -05:00
parent ea18c8fa85
commit e16ceafb81
17 changed files with 219 additions and 130 deletions

2
Cargo.lock generated
View File

@ -1400,6 +1400,7 @@ dependencies = [
name = "wgpu-native"
version = "0.1.0"
dependencies = [
"arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx-backend-dx11 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx-backend-dx12 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1411,6 +1412,7 @@ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winit 0.18.1 (registry+https://github.com/rust-lang/crates.io-index)",
]

View File

@ -1,6 +1,7 @@
use log::info;
#[allow(dead_code)]
pub fn cast_slice<T>(data: &[T]) -> &[u8] {
use std::mem::size_of;
use std::slice::from_raw_parts;

View File

@ -1 +1,2 @@
newline_style = "Native"
spaces_around_ranges = true

View File

@ -153,7 +153,9 @@ typedef enum {
WGPUVertexFormat_IntR8G8B8A8 = 4,
} WGPUVertexFormat;
typedef uint32_t WGPUId;
typedef struct WGPUBufferMapAsyncStatus WGPUBufferMapAsyncStatus;
typedef struct WGPUId WGPUId;
typedef WGPUId WGPUDeviceId;
@ -169,6 +171,10 @@ typedef struct {
typedef WGPUId WGPUBufferId;
typedef void (*WGPUBufferMapReadCallback)(WGPUBufferMapAsyncStatus status, const uint8_t *data, uint8_t *userdata);
typedef void (*WGPUBufferMapWriteCallback)(WGPUBufferMapAsyncStatus status, uint8_t *data, uint8_t *userdata);
typedef WGPUId WGPUCommandBufferId;
typedef struct {
@ -553,11 +559,25 @@ WGPUDeviceId wgpu_adapter_create_device(WGPUAdapterId adapter_id, const WGPUDevi
void wgpu_buffer_destroy(WGPUBufferId buffer_id);
void wgpu_buffer_map_read_async(WGPUBufferId buffer_id,
uint32_t start,
uint32_t size,
WGPUBufferMapReadCallback callback,
uint8_t *userdata);
void wgpu_buffer_map_write_async(WGPUBufferId buffer_id,
uint32_t start,
uint32_t size,
WGPUBufferMapWriteCallback callback,
uint8_t *userdata);
void wgpu_buffer_set_sub_data(WGPUBufferId buffer_id,
uint32_t start,
uint32_t count,
const uint8_t *data);
void wgpu_buffer_unmap(WGPUBufferId buffer_id);
void wgpu_command_buffer_copy_buffer_to_buffer(WGPUCommandBufferId command_buffer_id,
WGPUBufferId src,
uint32_t src_offset,

View File

@ -22,6 +22,7 @@ remote = ["serde"]
metal-auto-capture = ["gfx-backend-metal/auto-capture"]
[dependencies]
arrayvec = "0.4"
bitflags = "1.0"
lazy_static = "1.1.0"
log = "0.4"
@ -34,4 +35,5 @@ gfx-backend-dx12 = { version = "0.1.0", optional = true }
gfx-backend-metal = { version = "0.1.0", optional = true }
#rendy-memory = { git = "https://github.com/rustgd/rendy", rev = "ce7dd7f", features = ["gfx-hal"] }
serde = { version = "1.0", features = ["serde_derive"], optional = true }
vec_map = "0.8"
winit = { version = "0.18", optional = true }

View File

@ -1,6 +1,6 @@
use crate::track::TrackerSet;
use crate::{
LifeGuard, WeaklyStored,
LifeGuard,
BindGroupLayoutId, BufferId, SamplerId, TextureViewId,
};
@ -50,7 +50,7 @@ pub struct PipelineLayoutDescriptor {
pub struct PipelineLayout<B: hal::Backend> {
pub(crate) raw: B::PipelineLayout,
pub(crate) bind_group_layout_ids: Vec<WeaklyStored<BindGroupLayoutId>>,
pub(crate) bind_group_layout_ids: Vec<BindGroupLayoutId>,
}
#[repr(C)]
@ -82,7 +82,7 @@ pub struct BindGroupDescriptor {
pub struct BindGroup<B: hal::Backend> {
pub(crate) raw: B::DescriptorSet,
pub(crate) layout_id: WeaklyStored<BindGroupLayoutId>,
pub(crate) layout_id: BindGroupLayoutId,
pub(crate) life_guard: LifeGuard,
pub(crate) used: TrackerSet,
}

View File

@ -1,17 +1,17 @@
use crate::{
BindGroupHandle, Stored, WeaklyStored,
BindGroupHandle, Stored,
BindGroupId, BindGroupLayoutId, PipelineLayoutId,
};
pub struct BindGroupPair {
layout_id: WeaklyStored<BindGroupLayoutId>,
layout_id: BindGroupLayoutId,
group_id: Stored<BindGroupId>,
}
#[derive(Default)]
pub struct BindGroupEntry {
expected_layout_id: Option<WeaklyStored<BindGroupLayoutId>>,
expected_layout_id: Option<BindGroupLayoutId>,
provided: Option<BindGroupPair>,
}
@ -38,12 +38,12 @@ impl BindGroupEntry {
pub fn expect_layout(
&mut self, bind_group_layout_id: BindGroupLayoutId,
) -> Option<BindGroupId> {
let some = Some(WeaklyStored(bind_group_layout_id));
let some = Some(bind_group_layout_id);
if self.expected_layout_id != some {
self.expected_layout_id = some;
match self.provided {
Some(BindGroupPair { ref layout_id, ref group_id })
if layout_id.0 == bind_group_layout_id => Some(group_id.value),
Some(BindGroupPair { layout_id, ref group_id })
if layout_id == bind_group_layout_id => Some(group_id.value),
Some(_) | None => None,
}
} else {
@ -54,7 +54,7 @@ impl BindGroupEntry {
#[derive(Default)]
pub struct Binder {
pub(crate) pipeline_layout_id: Option<WeaklyStored<PipelineLayoutId>>, //TODO: strongly `Stored`
pub(crate) pipeline_layout_id: Option<PipelineLayoutId>, //TODO: strongly `Stored`
pub(crate) entries: Vec<BindGroupEntry>,
}
@ -70,7 +70,7 @@ impl Binder {
) -> Option<PipelineLayoutId> {
self.ensure_length(index + 1);
if self.entries[index].provide(bind_group_id, bind_group) {
self.pipeline_layout_id.as_ref().map(|&WeaklyStored(id)| id)
self.pipeline_layout_id.as_ref().cloned()
} else {
None
}

View File

@ -112,18 +112,18 @@ pub extern "C" fn wgpu_compute_pass_set_pipeline(
}
let pipeline_layout_guard = HUB.pipeline_layouts.read();
let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id.0);
let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id);
let bing_group_guard = HUB.bind_groups.read();
pass.binder.pipeline_layout_id = Some(pipeline.layout_id.clone());
pass.binder.ensure_length(pipeline_layout.bind_group_layout_ids.len());
for (index, (entry, bgl_id)) in pass.binder.entries
for (index, (entry, &bgl_id)) in pass.binder.entries
.iter_mut()
.zip(&pipeline_layout.bind_group_layout_ids)
.enumerate()
{
if let Some(bg_id) = entry.expect_layout(bgl_id.0) {
if let Some(bg_id) = entry.expect_layout(bgl_id) {
let bind_group = bing_group_guard.get(bg_id);
unsafe {
pass.raw.bind_compute_descriptor_sets(

View File

@ -22,7 +22,7 @@ use crate::{
BufferId, CommandBufferId, CommandEncoderId, DeviceId,
TextureId, TextureViewId,
BufferUsageFlags, TextureUsageFlags, Color,
LifeGuard, Stored, WeaklyStored,
LifeGuard, Stored,
CommandBufferHandle,
};
#[cfg(feature = "local")]
@ -294,9 +294,9 @@ pub fn command_encoder_begin_render_pass(
let fb_key = FramebufferKey {
attachments: color_attachments
.iter()
.map(|at| WeaklyStored(at.attachment))
.map(|at| at.attachment)
.chain(
depth_stencil_attachment.map(|at| WeaklyStored(at.attachment)),
depth_stencil_attachment.map(|at| at.attachment),
)
.collect(),
};
@ -308,7 +308,7 @@ pub fn command_encoder_begin_render_pass(
.key()
.attachments
.iter()
.map(|&WeaklyStored(id)| &view_guard.get(id).raw);
.map(|&id| &view_guard.get(id).raw);
unsafe {
device
@ -374,7 +374,7 @@ pub extern "C" fn wgpu_command_encoder_begin_render_pass(
desc: RenderPassDescriptor,
) -> RenderPassId {
let pass = command_encoder_begin_render_pass(command_encoder_id, desc);
HUB.render_passes.register(pass)
HUB.render_passes.register_local(pass)
}
pub fn command_encoder_begin_compute_pass(
@ -398,5 +398,5 @@ pub extern "C" fn wgpu_command_encoder_begin_compute_pass(
command_encoder_id: CommandEncoderId,
) -> ComputePassId {
let pass = command_encoder_begin_compute_pass(command_encoder_id);
HUB.compute_passes.register(pass)
HUB.compute_passes.register_local(pass)
}

View File

@ -224,18 +224,18 @@ pub extern "C" fn wgpu_render_pass_set_pipeline(
}
let pipeline_layout_guard = HUB.pipeline_layouts.read();
let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id.0);
let pipeline_layout = pipeline_layout_guard.get(pipeline.layout_id);
let bing_group_guard = HUB.bind_groups.read();
pass.binder.pipeline_layout_id = Some(pipeline.layout_id.clone());
pass.binder.ensure_length(pipeline_layout.bind_group_layout_ids.len());
for (index, (entry, bgl_id)) in pass.binder.entries
for (index, (entry, &bgl_id)) in pass.binder.entries
.iter_mut()
.zip(&pipeline_layout.bind_group_layout_ids)
.enumerate()
{
if let Some(bg_id) = entry.expect_layout(bgl_id.0) {
if let Some(bg_id) = entry.expect_layout(bgl_id) {
let bind_group = bing_group_guard.get(bg_id);
unsafe {
pass.raw.bind_graphics_descriptor_sets(

View File

@ -2,7 +2,7 @@ use crate::{binding_model, command, conv, pipeline, resource, swap_chain};
use crate::hub::HUB;
use crate::track::{TrackerSet, TrackPermit};
use crate::{
LifeGuard, RefCount, Stored, SubmissionIndex, WeaklyStored,
LifeGuard, RefCount, Stored, SubmissionIndex,
BufferMapAsyncStatus, BufferMapOperation,
};
use crate::{
@ -15,6 +15,7 @@ use crate::{
ShaderModuleId, CommandEncoderId, RenderPipelineId, ComputePipelineId,
};
use arrayvec::ArrayVec;
use back;
use hal::backend::FastHashMap;
use hal::command::RawCommandBuffer;
@ -34,6 +35,8 @@ use std::collections::hash_map::Entry;
use std::sync::atomic::Ordering;
type AttachmentVec<T> = ArrayVec<[T; 5]>;
pub fn all_buffer_stages() -> hal::pso::PipelineStage {
use hal::pso::PipelineStage as Ps;
Ps::DRAW_INDIRECT |
@ -57,13 +60,13 @@ pub fn all_image_stages() -> hal::pso::PipelineStage {
#[derive(Hash, PartialEq)]
pub(crate) struct RenderPassKey {
pub attachments: Vec<hal::pass::Attachment>,
pub attachments: AttachmentVec<hal::pass::Attachment>,
}
impl Eq for RenderPassKey {}
#[derive(Hash, PartialEq)]
pub(crate) struct FramebufferKey {
pub attachments: Vec<WeaklyStored<TextureViewId>>,
pub attachments: AttachmentVec<TextureViewId>,
}
impl Eq for FramebufferKey {}
@ -222,7 +225,7 @@ impl DestroyedResources<back::Backend> {
let mut buffer_guard = HUB.buffers.write();
for buffer_id in self.ready_to_map.drain(..) {
let mut buffer = buffer_guard.get_mut(buffer_id);
let buffer = buffer_guard.get_mut(buffer_id);
let mut operation = None;
std::mem::swap(&mut operation, &mut buffer.pending_map_operation);
match operation {
@ -254,7 +257,7 @@ impl DestroyedResources<back::Backend> {
pub struct Device<B: hal::Backend> {
pub(crate) raw: B::Device,
adapter_id: WeaklyStored<AdapterId>,
adapter_id: AdapterId,
pub(crate) queue_group: hal::QueueGroup<B, hal::General>,
//mem_allocator: Heaps<B::Memory>,
pub(crate) com_allocator: command::CommandAllocator<B>,
@ -270,7 +273,7 @@ pub struct Device<B: hal::Backend> {
impl<B: hal::Backend> Device<B> {
pub(crate) fn new(
raw: B::Device,
adapter_id: WeaklyStored<AdapterId>,
adapter_id: AdapterId,
queue_group: hal::QueueGroup<B, hal::General>,
mem_props: hal::MemoryProperties,
) -> Self {
@ -431,7 +434,7 @@ pub extern "C" fn wgpu_device_create_buffer(
) -> BufferId {
let buffer = device_create_buffer(device_id, desc);
let ref_count = buffer.life_guard.ref_count.clone();
let id = HUB.buffers.register(buffer);
let id = HUB.buffers.register_local(buffer);
device_track_buffer(device_id, id, ref_count);
id
}
@ -543,7 +546,7 @@ 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 id = HUB.textures.register(texture);
let id = HUB.textures.register_local(texture);
device_track_texture(device_id, id, ref_count);
id
}
@ -617,7 +620,7 @@ pub extern "C" fn wgpu_texture_create_view(
let view = texture_create_view(texture_id, desc);
let texture_id = view.texture_id.value;
let ref_count = view.life_guard.ref_count.clone();
let id = HUB.texture_views.register(view);
let id = HUB.texture_views.register_local(view);
device_track_view(texture_id, id, ref_count);
id
}
@ -671,7 +674,7 @@ pub extern "C" fn wgpu_texture_create_default_view(texture_id: TextureId) -> Tex
let view = texture_create_default_view(texture_id);
let texture_id = view.texture_id.value;
let ref_count = view.life_guard.ref_count.clone();
let id = HUB.texture_views.register(view);
let id = HUB.texture_views.register_local(view);
device_track_view(texture_id, id, ref_count);
id
}
@ -757,7 +760,7 @@ pub extern "C" fn wgpu_device_create_sampler(
device_id: DeviceId, desc: &resource::SamplerDescriptor
) -> SamplerId {
let sampler = device_create_sampler(device_id, desc);
HUB.samplers.register(sampler)
HUB.samplers.register_local(sampler)
}
@ -799,7 +802,7 @@ pub extern "C" fn wgpu_device_create_bind_group_layout(
desc: &binding_model::BindGroupLayoutDescriptor,
) -> BindGroupLayoutId {
let layout = device_create_bind_group_layout(device_id, desc);
HUB.bind_group_layouts.register(layout)
HUB.bind_group_layouts.register_local(layout)
}
pub fn device_create_pipeline_layout(
@ -829,7 +832,6 @@ pub fn device_create_pipeline_layout(
bind_group_layout_ids: bind_group_layout_ids
.iter()
.cloned()
.map(WeaklyStored)
.collect(),
}
}
@ -841,7 +843,7 @@ pub extern "C" fn wgpu_device_create_pipeline_layout(
desc: &binding_model::PipelineLayoutDescriptor,
) -> PipelineLayoutId {
let layout = device_create_pipeline_layout(device_id, desc);
HUB.pipeline_layouts.register(layout)
HUB.pipeline_layouts.register_local(layout)
}
pub fn device_create_bind_group(
@ -916,7 +918,7 @@ pub fn device_create_bind_group(
binding_model::BindGroup {
raw: desc_set,
layout_id: WeaklyStored(desc.layout),
layout_id: desc.layout,
life_guard: LifeGuard::new(),
used,
}
@ -929,7 +931,7 @@ pub extern "C" fn wgpu_device_create_bind_group(
desc: &binding_model::BindGroupDescriptor,
) -> BindGroupId {
let bind_group = device_create_bind_group(device_id, desc);
HUB.bind_groups.register(bind_group)
HUB.bind_groups.register_local(bind_group)
}
@ -957,7 +959,7 @@ pub extern "C" fn wgpu_device_create_shader_module(
desc: &pipeline::ShaderModuleDescriptor,
) -> ShaderModuleId {
let module = device_create_shader_module(device_id, desc);
HUB.shader_modules.register(module)
HUB.shader_modules.register_local(module)
}
pub fn device_create_command_encoder(
@ -988,7 +990,7 @@ pub extern "C" fn wgpu_device_create_command_encoder(
desc: &command::CommandEncoderDescriptor,
) -> CommandEncoderId {
let cmb = device_create_command_encoder(device_id, desc);
HUB.command_buffers.register(cmb)
HUB.command_buffers.register_local(cmb)
}
#[no_mangle]
@ -1084,7 +1086,7 @@ pub extern "C" fn wgpu_queue_submit(
.flat_map(|link| {
//TODO: check the epoch
surface_guard
.get(link.swap_chain_id.0)
.get(link.swap_chain_id)
.swap_chain
.as_ref()
.map(|swap_chain| (
@ -1339,7 +1341,7 @@ pub fn device_create_render_pipeline(
pipeline::RenderPipeline {
raw: pipeline,
layout_id: WeaklyStored(desc.layout),
layout_id: desc.layout,
}
}
@ -1350,7 +1352,7 @@ pub extern "C" fn wgpu_device_create_render_pipeline(
desc: &pipeline::RenderPipelineDescriptor,
) -> RenderPipelineId {
let pipeline = device_create_render_pipeline(device_id, desc);
HUB.render_pipelines.register(pipeline)
HUB.render_pipelines.register_local(pipeline)
}
pub fn device_create_compute_pipeline(
@ -1397,7 +1399,7 @@ pub fn device_create_compute_pipeline(
pipeline::ComputePipeline {
raw: pipeline,
layout_id: WeaklyStored(desc.layout),
layout_id: desc.layout,
}
}
@ -1408,7 +1410,7 @@ pub extern "C" fn wgpu_device_create_compute_pipeline(
desc: &pipeline::ComputePipelineDescriptor,
) -> ComputePipelineId {
let pipeline = device_create_compute_pipeline(device_id, desc);
HUB.compute_pipelines.register(pipeline)
HUB.compute_pipelines.register_local(pipeline)
}
pub fn device_create_swap_chain(
@ -1425,7 +1427,7 @@ pub fn device_create_swap_chain(
let (caps, formats, _present_modes, _composite_alphas) = {
let adapter_guard = HUB.adapters.read();
let adapter = adapter_guard.get(device.adapter_id.0);
let adapter = adapter_guard.get(device.adapter_id);
assert!(surface.raw.supports_queue_family(&adapter.queue_families[0]));
surface.raw.compatibility(&adapter.physical_device)
};
@ -1556,13 +1558,13 @@ pub fn swap_chain_populate_textures(
.unwrap()
};
texture.swap_chain_link = Some(swap_chain::SwapChainLink {
swap_chain_id: WeaklyStored(swap_chain_id), //TODO: strongly
swap_chain_id, //TODO: strongly
epoch: Mutex::new(0),
image_index: i as hal::SwapImageIndex,
});
let texture_id = Stored {
ref_count: texture.life_guard.ref_count.clone(),
value: HUB.textures.register(texture),
value: HUB.textures.register_local(texture),
};
trackers.textures.query(
texture_id.value,
@ -1581,7 +1583,7 @@ pub fn swap_chain_populate_textures(
};
let view_id = Stored {
ref_count: view.life_guard.ref_count.clone(),
value: HUB.texture_views.register(view),
value: HUB.texture_views.register_local(view),
};
trackers.views.query(
view_id.value,

View File

@ -7,56 +7,89 @@ use crate::{
SurfaceHandle,
};
use hal::backend::FastHashMap;
use lazy_static::lazy_static;
use parking_lot::RwLock;
#[cfg(feature = "local")]
use parking_lot::Mutex;
use vec_map::VecMap;
use std::ops;
use std::sync::Arc;
//TODO: use Vec instead of HashMap
//TODO: track epochs of indices
pub type Id = u32;
pub(crate) type Index = u32;
pub(crate) type Epoch = u32;
#[derive(Clone, Copy, Debug, Hash, PartialEq)]
pub struct Id(Index, Epoch);
pub trait NewId {
fn new(index: Index, epoch: Epoch) -> Self;
fn index(&self) -> Index;
fn epoch(&self) -> Epoch;
}
impl NewId for Id {
fn new(index: Index, epoch: Epoch) -> Self {
Id(index, epoch)
}
fn index(&self) -> Index {
self.0
}
fn epoch(&self) -> Epoch {
self.1
}
}
/// A simple structure to manage identities of objects.
#[derive(Default)]
pub struct IdentityManager {
last_id: Id,
free: Vec<Id>,
free: Vec<Index>,
epochs: Vec<Epoch>,
}
impl IdentityManager {
pub fn alloc(&mut self) -> Id {
match self.free.pop() {
Some(id) => id,
Some(index) => {
Id(index, self.epochs[index as usize])
}
None => {
self.last_id += 1;
assert_ne!(self.last_id, 0);
self.last_id
let id = Id(self.epochs.len() as Index, 1);
self.epochs.push(id.1);
id
}
}
}
pub fn free(&mut self, id: Id) {
debug_assert!(id <= self.last_id && !self.free.contains(&id));
self.free.push(id);
pub fn free(&mut self, Id(index, epoch): Id) {
// avoid doing this check in release
if cfg!(debug_assertions) {
assert!(!self.free.contains(&index));
}
let pe = &mut self.epochs[index as usize];
assert_eq!(*pe, epoch);
*pe += 1;
self.free.push(index);
}
}
pub struct Storage<T> {
//TODO: consider concurrent hashmap?
map: FastHashMap<Id, T>,
map: VecMap<(T, Epoch)>,
}
impl<T> Storage<T> {
pub fn get(&self, id: Id) -> &T {
self.map.get(&id).unwrap()
let (ref value, epoch) = self.map[id.0 as usize];
assert_eq!(epoch, id.1);
value
}
pub fn get_mut(&mut self, id: Id) -> &mut T {
self.map.get_mut(&id).unwrap()
let (ref mut value, epoch) = self.map[id.0 as usize];
assert_eq!(epoch, id.1);
value
}
}
@ -72,7 +105,7 @@ impl<T> Default for Registry<T> {
#[cfg(feature = "local")]
identity: Mutex::new(IdentityManager::default()),
data: RwLock::new(Storage {
map: FastHashMap::default(),
map: VecMap::new(),
}),
}
}
@ -92,26 +125,26 @@ impl<T> ops::DerefMut for Registry<T> {
}
impl<T> Registry<T> {
#[cfg(feature = "local")]
pub fn register(&self, value: T) -> Id {
let id = self.identity.lock().alloc();
let old = self.data.write().map.insert(id, value);
pub fn register(&self, id: Id, value: T) {
let old = self.data.write().map.insert(id.0 as usize, (value, id.1));
assert!(old.is_none());
}
}
impl<T> Registry<T> {
#[cfg(feature = "local")]
pub fn register_local(&self, value: T) -> Id {
let id = self.identity.lock().alloc();
self.register(id, value);
id
}
pub fn unregister(&self, id: Id) -> T {
#[cfg(feature = "local")]
self.identity.lock().free(id);
self.data.write().map.remove(&id).unwrap()
}
}
#[cfg(feature = "remote")]
impl<T> Registry<T> {
pub fn register(&self, id: Id, value: T) {
let old = self.data.write().map.insert(id, value);
assert!(old.is_none());
let (value, epoch) = self.data.write().map.remove(id.0 as usize).unwrap();
assert_eq!(epoch, id.1);
value
}
}

View File

@ -1,6 +1,5 @@
use crate::hub::HUB;
use crate::{
WeaklyStored,
AdapterHandle, DeviceHandle, SurfaceHandle,
AdapterId, InstanceId,
};
@ -48,7 +47,7 @@ pub fn create_instance() -> ::back::Instance {
#[cfg(feature = "local")]
pub extern "C" fn wgpu_create_instance() -> InstanceId {
let inst = create_instance();
HUB.instances.register(inst)
HUB.instances.register_local(inst)
}
#[cfg(feature = "local")]
@ -62,7 +61,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_winit(
.get(instance_id)
.create_surface(window);
let surface = SurfaceHandle::new(raw);
HUB.surfaces.register(surface)
HUB.surfaces.register_local(surface)
}
#[allow(unused_variables)]
@ -90,7 +89,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_xlib(
window: u64,
) -> SurfaceId {
let surface = instance_create_surface_from_xlib(instance_id, display, window);
HUB.surfaces.register(surface)
HUB.surfaces.register_local(surface)
}
#[allow(unused_variables)]
@ -116,7 +115,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_macos_layer(
layer: *mut std::ffi::c_void,
) -> SurfaceId {
let surface = instance_create_surface_from_macos_layer(instance_id, layer);
HUB.surfaces.register(surface)
HUB.surfaces.register_local(surface)
}
#[allow(unused_variables)]
@ -152,7 +151,7 @@ pub extern "C" fn wgpu_instance_create_surface_from_windows_hwnd(
hwnd: *mut std::ffi::c_void,
) -> SurfaceId {
let surface = instance_create_surface_from_windows_hwnd(instance_id, hinstance, hwnd);
HUB.surfaces.register(surface)
HUB.surfaces.register_local(surface)
}
pub fn instance_get_adapter(
@ -184,7 +183,7 @@ pub extern "C" fn wgpu_instance_get_adapter(
desc: &AdapterDescriptor,
) -> AdapterId {
let adapter = instance_get_adapter(instance_id, desc);
HUB.adapters.register(adapter)
HUB.adapters.register_local(adapter)
}
pub fn adapter_create_device(
@ -195,7 +194,7 @@ pub fn adapter_create_device(
let adapter = adapter_guard.get_mut(adapter_id);
let (raw, queue_group) = adapter.open_with::<_, hal::General>(1, |_qf| true).unwrap();
let mem_props = adapter.physical_device.memory_properties();
DeviceHandle::new(raw, WeaklyStored(adapter_id), queue_group, mem_props)
DeviceHandle::new(raw, adapter_id, queue_group, mem_props)
}
#[cfg(feature = "local")]
@ -205,5 +204,5 @@ pub extern "C" fn wgpu_adapter_create_device(
desc: &DeviceDescriptor,
) -> DeviceId {
let device = adapter_create_device(adapter_id, desc);
HUB.devices.register(device)
HUB.devices.register_local(device)
}

View File

@ -100,9 +100,6 @@ struct Stored<T> {
ref_count: RefCount,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
struct WeaklyStored<T>(T);
#[repr(C)]
#[derive(Clone, Copy, Debug)]

View File

@ -1,6 +1,6 @@
use crate::resource;
use crate::{
ByteArray, PipelineLayoutId, ShaderModuleId, WeaklyStored,
ByteArray, PipelineLayoutId, ShaderModuleId,
};
use bitflags::bitflags;
@ -181,7 +181,7 @@ pub struct ComputePipelineDescriptor {
pub struct ComputePipeline<B: hal::Backend> {
pub(crate) raw: B::ComputePipeline,
pub(crate) layout_id: WeaklyStored<PipelineLayoutId>,
pub(crate) layout_id: PipelineLayoutId,
}
#[repr(C)]
@ -235,5 +235,5 @@ pub struct RenderPipelineDescriptor {
pub struct RenderPipeline<B: hal::Backend> {
pub(crate) raw: B::GraphicsPipeline,
pub(crate) layout_id: WeaklyStored<PipelineLayoutId>,
pub(crate) layout_id: PipelineLayoutId,
}

View File

@ -1,5 +1,5 @@
use crate::{
Extent3d, Stored, WeaklyStored,
Extent3d, Stored,
DeviceId, SwapChainId, TextureId, TextureViewId,
};
use crate::{conv, resource};
@ -17,7 +17,7 @@ use std::{iter, mem};
pub type SwapImageEpoch = u16;
pub(crate) struct SwapChainLink<E> {
pub swap_chain_id: WeaklyStored<SwapChainId>, //TODO: strongly
pub swap_chain_id: SwapChainId, //TODO: strongly
pub epoch: E,
pub image_index: hal::SwapImageIndex,
}

View File

@ -1,19 +1,19 @@
use crate::hub::{Id, Storage};
use crate::hub::{NewId, Id, Index, Epoch, Storage};
use crate::resource::{BufferUsageFlags, TextureUsageFlags};
use crate::{
RefCount, WeaklyStored,
RefCount,
BufferId, TextureId, TextureViewId,
};
use std::borrow::Borrow;
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;
use std::borrow::Borrow;
use std::collections::hash_map::Entry;
use std::marker::PhantomData;
use std::mem;
use std::ops::{BitOr, Range};
#[derive(Clone, Debug, PartialEq)]
#[allow(unused)]
@ -72,16 +72,19 @@ struct Track<U> {
ref_count: RefCount,
init: U,
last: U,
epoch: Epoch,
}
//TODO: consider having `I` as an associated type of `U`?
pub struct Tracker<I, U> {
map: FastHashMap<WeaklyStored<I>, Track<U>>,
map: FastHashMap<Index, Track<U>>,
_phantom: PhantomData<I>,
}
pub type BufferTracker = Tracker<BufferId, BufferUsageFlags>;
pub type TextureTracker = Tracker<TextureId, TextureUsageFlags>;
pub struct DummyTracker<I> {
map: FastHashMap<WeaklyStored<I>, RefCount>,
map: FastHashMap<Index, (RefCount, Epoch)>,
_phantom: PhantomData<I>,
}
pub type TextureViewTracker = DummyTracker<TextureViewId>;
@ -102,67 +105,88 @@ impl TrackerSet {
}
}
impl<I: Clone + Hash + Eq> DummyTracker<I> {
impl<I: NewId> DummyTracker<I> {
pub fn new() -> Self {
DummyTracker {
map: FastHashMap::default(),
_phantom: PhantomData,
}
}
/// Remove an id from the tracked map.
pub(crate) fn remove(&mut self, id: I) -> bool {
self.map.remove(&WeaklyStored(id)).is_some()
match self.map.remove(&id.index()) {
Some((_, epoch)) => {
assert_eq!(epoch, id.epoch());
true
}
None => false,
}
}
/// Get the last usage on a resource.
pub(crate) fn query(&mut self, id: I, ref_count: &RefCount) -> bool {
match self.map.entry(WeaklyStored(id)) {
match self.map.entry(id.index()) {
Entry::Vacant(e) => {
e.insert(ref_count.clone());
e.insert((ref_count.clone(), id.epoch()));
true
}
Entry::Occupied(_) => false,
Entry::Occupied(e) => {
assert_eq!(e.get().1, id.epoch());
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);
for (&index, &(ref ref_count, epoch)) in &other.map {
self.query(I::new(index, epoch), ref_count);
}
}
}
impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<I, U> {
impl<I: NewId, U: Copy + GenericUsage + BitOr<Output = U> + PartialEq> Tracker<I, U> {
pub fn new() -> Self {
Tracker {
map: FastHashMap::default(),
_phantom: PhantomData,
}
}
/// Remove an id from the tracked map.
pub(crate) fn remove(&mut self, id: I) -> bool {
self.map.remove(&WeaklyStored(id)).is_some()
match self.map.remove(&id.index()) {
Some(track) => {
assert_eq!(track.epoch, id.epoch());
true
}
None => false,
}
}
/// 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)) {
match self.map.entry(id.index()) {
Entry::Vacant(e) => {
e.insert(Track {
ref_count: ref_count.clone(),
init: default,
last: default,
epoch: id.epoch(),
});
Query {
usage: default,
initialized: true,
}
}
Entry::Occupied(e) => Query {
usage: e.get().last,
initialized: false,
},
Entry::Occupied(e) => {
assert_eq!(e.get().epoch, id.epoch());
Query {
usage: e.get().last,
initialized: false,
}
}
}
}
@ -174,16 +198,18 @@ impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialE
usage: U,
permit: TrackPermit,
) -> Result<Tracktion<U>, U> {
match self.map.entry(WeaklyStored(id)) {
match self.map.entry(id.index()) {
Entry::Vacant(e) => {
e.insert(Track {
ref_count: ref_count.clone(),
init: usage,
last: usage,
epoch: id.epoch(),
});
Ok(Tracktion::Init)
}
Entry::Occupied(mut e) => {
assert_eq!(e.get().epoch, id.epoch());
let old = e.get().last;
if usage == old {
Ok(Tracktion::Keep)
@ -201,37 +227,43 @@ impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialE
}
/// Consume another tacker, adding it's transitions to `self`.
/// Transitions the current usage to the new one.
pub fn consume_by_replace<'a>(&'a mut self, other: &'a Self) -> impl 'a + Iterator<Item = (I, Range<U>)> {
other.map.iter().flat_map(move |(id, new)| {
match self.map.entry(WeaklyStored(id.0.clone())) {
other.map.iter().flat_map(move |(&index, new)| {
match self.map.entry(index) {
Entry::Vacant(e) => {
e.insert(new.clone());
None
}
Entry::Occupied(mut e) => {
assert_eq!(e.get().epoch, new.epoch);
let old = mem::replace(&mut e.get_mut().last, new.last);
if old == new.init {
None
} else {
Some((id.0.clone(), old..new.last))
Some((I::new(index, new.epoch), old .. new.last))
}
}
}
})
}
/// Consume another tacker, adding it's transitions to `self`.
/// Extends the current usage without doing any transitions.
pub fn consume_by_extend<'a>(&'a mut self, other: &'a Self) -> Result<(), (I, Range<U>)> {
for (id, new) in other.map.iter() {
match self.map.entry(WeaklyStored(id.0.clone())) {
for (&index, new) in other.map.iter() {
match self.map.entry(index) {
Entry::Vacant(e) => {
e.insert(new.clone());
}
Entry::Occupied(mut e) => {
assert_eq!(e.get().epoch, new.epoch);
let old = e.get().last;
if old != new.last {
let extended = old | new.last;
if extended.is_exclusive() {
return Err((id.0.clone(), old..new.last));
let id = I::new(index, new.epoch);
return Err((id, old .. new.last));
}
e.get_mut().last = extended;
}
@ -243,7 +275,7 @@ impl<I: Clone + Hash + Eq, U: Copy + GenericUsage + BitOr<Output = U> + PartialE
/// Return an iterator over used resources keys.
pub fn used<'a>(&'a self) -> impl 'a + Iterator<Item = I> {
self.map.keys().map(|&WeaklyStored(ref id)| id.clone())
self.map.iter().map(|(&index, track)| I::new(index, track.epoch))
}
}