From 0fca6930d90beb24c1d650d764a8b5d8d0b3069e Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 19 Oct 2018 10:34:19 -0400 Subject: [PATCH] Basic resource tracking --- wgpu-native/src/command/render.rs | 3 ++ wgpu-native/src/conv.rs | 40 ++++++++------- wgpu-native/src/device.rs | 15 ++++-- wgpu-native/src/lib.rs | 3 +- wgpu-native/src/resource.rs | 35 +++++++------ wgpu-native/src/track.rs | 85 +++++++++++++++++++++++++++++++ 6 files changed, 140 insertions(+), 41 deletions(-) create mode 100644 wgpu-native/src/track.rs diff --git a/wgpu-native/src/command/render.rs b/wgpu-native/src/command/render.rs index 3e221d662..4c4dd1b45 100644 --- a/wgpu-native/src/command/render.rs +++ b/wgpu-native/src/command/render.rs @@ -1,4 +1,5 @@ use registry::{HUB, Items, Registry}; +use track::{Tracker}; use { Stored, CommandBufferId, RenderPassId, @@ -14,6 +15,7 @@ pub struct RenderPass { raw: B::CommandBuffer, parent: B::CommandBuffer, cmb_id: Stored, + tracker: Tracker, } impl RenderPass { @@ -26,6 +28,7 @@ impl RenderPass { raw, parent, cmb_id: Stored(cmb_id), + tracker: Tracker::default(), } } } diff --git a/wgpu-native/src/conv.rs b/wgpu-native/src/conv.rs index 4708c7464..204ae14d6 100644 --- a/wgpu-native/src/conv.rs +++ b/wgpu-native/src/conv.rs @@ -244,7 +244,9 @@ fn checked_u32_as_u16(value: u32) -> u16 { value as u16 } -pub(crate) fn map_texture_dimension_size(dimension: resource::TextureDimension, size: Extent3d) -> hal::image::Kind { +pub(crate) fn map_texture_dimension_size( + dimension: resource::TextureDimension, size: Extent3d +) -> hal::image::Kind { use hal::image::Kind as H; use resource::TextureDimension::*; let Extent3d { width, height, depth } = size; @@ -258,30 +260,30 @@ pub(crate) fn map_texture_dimension_size(dimension: resource::TextureDimension, } } -pub(crate) fn map_texture_usage_flags(flags: u32, format: hal::format::Format) -> hal::image::Usage { - use hal::image::Usage as H; - use resource::{ - TextureUsageFlags_TRANSFER_SRC, TextureUsageFlags_TRANSFER_DST, TextureUsageFlags_SAMPLED, - TextureUsageFlags_STORAGE, TextureUsageFlags_OUTPUT_ATTACHMENT, - }; - let mut value = H::empty(); - if 0 != flags & TextureUsageFlags_TRANSFER_SRC { - value |= H::TRANSFER_SRC; +pub(crate) fn map_texture_usage_flags( + flags: resource::TextureUsageFlags, format: hal::format::Format +) -> hal::image::Usage { + use hal::image::Usage as U; + use resource::TextureUsageFlags as W; + + let mut value = U::empty(); + if flags.contains(W::TRANSFER_SRC) { + value |= U::TRANSFER_SRC; } - if 0 != flags & TextureUsageFlags_TRANSFER_DST { - value |= H::TRANSFER_DST; + if flags.contains(W::TRANSFER_DST) { + value |= U::TRANSFER_DST; } - if 0 != flags & TextureUsageFlags_SAMPLED { - value |= H::SAMPLED; + if flags.contains(W::SAMPLED) { + value |= U::SAMPLED; } - if 0 != flags & TextureUsageFlags_STORAGE { - value |= H::STORAGE; + if flags.contains(W::STORAGE) { + value |= U::STORAGE; } - if 0 != flags & TextureUsageFlags_OUTPUT_ATTACHMENT { + if flags.contains(W::OUTPUT_ATTACHMENT) { if format.surface_desc().aspects.intersects(hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL) { - value |= H::DEPTH_STENCIL_ATTACHMENT; + value |= U::DEPTH_STENCIL_ATTACHMENT; } else { - value |= H::COLOR_ATTACHMENT; + value |= U::COLOR_ATTACHMENT; } } // Note: TextureUsageFlags::Present does not need to be handled explicitly diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index fd3716dc1..3a5245317 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -1,6 +1,8 @@ use {back, binding_model, command, conv, pipeline, resource}; use registry::{HUB, Items, Registry}; +use track::{Tracker, UsePermit}; use { + Stored, AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId, DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, TextureId, }; @@ -18,6 +20,7 @@ pub struct Device { queue_group: hal::QueueGroup, mem_allocator: Heaps, pub(crate) com_allocator: command::CommandAllocator, + tracker: Tracker, mem_props: hal::MemoryProperties, } @@ -53,6 +56,7 @@ impl Device { mem_allocator, com_allocator: command::CommandAllocator::new(queue_group.family()), queue_group, + tracker: Tracker::default(), mem_props, } } @@ -101,11 +105,16 @@ pub extern "C" fn wgpu_device_create_texture( .raw .bind_image_memory(&image_memory, 0, image_unbound) .unwrap(); - HUB.textures + + let id = HUB.textures .lock() .register(resource::Texture { raw: bound_image, - }) + }); + device.tracker.use_texture(Stored(id), resource::TextureUsageFlags::empty(), UsePermit::empty()) + .expect("Resource somehow is already registered"); + + id } #[no_mangle] @@ -216,7 +225,7 @@ pub extern "C" fn wgpu_device_create_command_buffer( _desc: &command::CommandBufferDescriptor, ) -> CommandBufferId { let mut device_guard = HUB.devices.lock(); - let device = device_guard.get_mut(device_id); + let device = device_guard.get(device_id); let mut cmd_buf = device.com_allocator.allocate(device_id, &device.raw); cmd_buf.raw.last_mut().unwrap().begin( diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index 9d3248aa5..5445b4989 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -29,6 +29,7 @@ mod instance; mod pipeline; mod registry; mod resource; +mod track; pub use self::binding_model::*; pub use self::command::*; @@ -40,7 +41,7 @@ pub use self::resource::*; use back::Backend as B; use registry::Id; -#[derive(Debug, PartialEq)] +#[derive(Debug, Hash, PartialEq, Eq)] struct Stored(T); #[cfg(not(feature = "remote"))] unsafe impl Sync for Stored {} diff --git a/wgpu-native/src/resource.rs b/wgpu-native/src/resource.rs index 884a1d3a3..6a6f40ee5 100644 --- a/wgpu-native/src/resource.rs +++ b/wgpu-native/src/resource.rs @@ -1,11 +1,11 @@ +use {Extent3d}; + use hal; -use Extent3d; bitflags! { #[repr(transparent)] pub struct BufferUsageFlags: u32 { - const NONE = 0; const MAP_READ = 1; const MAP_WRITE = 2; const TRANSFER_SRC = 4; @@ -14,6 +14,8 @@ bitflags! { const VERTEX = 32; const UNIFORM = 64; const STORAGE = 128; + const NONE = 0; + const WRITE_ALL = 2 + 8 + 128; } } @@ -50,22 +52,19 @@ pub enum TextureFormat { D32FloatS8Uint = 3, } -// TODO: bitflags -pub type TextureUsageFlags = u32; -#[allow(non_upper_case_globals)] -pub const TextureUsageFlags_NONE: u32 = 0; -#[allow(non_upper_case_globals)] -pub const TextureUsageFlags_TRANSFER_SRC: u32 = 1; -#[allow(non_upper_case_globals)] -pub const TextureUsageFlags_TRANSFER_DST: u32 = 2; -#[allow(non_upper_case_globals)] -pub const TextureUsageFlags_SAMPLED: u32 = 4; -#[allow(non_upper_case_globals)] -pub const TextureUsageFlags_STORAGE: u32 = 8; -#[allow(non_upper_case_globals)] -pub const TextureUsageFlags_OUTPUT_ATTACHMENT: u32 = 16; -#[allow(non_upper_case_globals)] -pub const TextureUsageFlags_PRESENT: u32 = 32; +bitflags! { + #[repr(transparent)] + pub struct TextureUsageFlags: u32 { + const TRANSFER_SRC = 1; + const TRANSFER_DST = 2; + const SAMPLED = 4; + const STORAGE = 8; + const OUTPUT_ATTACHMENT = 16; + const PRESENT = 32; + const NONE = 0; + const WRITE_ALL = 2 + 8 + 16; + } +} #[repr(C)] pub struct TextureDescriptor { diff --git a/wgpu-native/src/track.rs b/wgpu-native/src/track.rs new file mode 100644 index 000000000..7f72a1f2e --- /dev/null +++ b/wgpu-native/src/track.rs @@ -0,0 +1,85 @@ +use {Stored, BufferId, TextureId}; +use resource::{BufferUsageFlags, TextureUsageFlags}; + +use std::collections::hash_map::{Entry, HashMap}; +use std::ops::Range; +use std::sync::Mutex; + + +#[derive(Clone, Debug, PartialEq)] +pub enum UseAction { + Init, + Keep, + Extend { old: T }, + Replace { old: T }, +} + +bitflags! { + pub struct UsePermit: u32 { + const EXTEND = 1; + const REPLACE = 2; + } +} + + +#[derive(Default)] +pub struct Tracker { + buffers: Mutex, Range>>, + textures: Mutex, Range>>, +} + +impl Tracker { + pub(crate) fn use_buffer( + &self, id: Stored, usage: BufferUsageFlags, permit: UsePermit, + ) -> Result, BufferUsageFlags> { + match self.buffers.lock().unwrap().entry(id) { + Entry::Vacant(e) => { + e.insert(usage .. usage); + Ok(UseAction::Init) + } + Entry::Occupied(mut e) => { + let old = e.get().end; + if usage == old { + Ok(UseAction::Keep) + } else if permit.contains(UsePermit::EXTEND) && + !BufferUsageFlags::WRITE_ALL.intersects(old | usage) + { + e.get_mut().end |= usage; + Ok(UseAction::Extend { old }) + } else if permit.contains(UsePermit::REPLACE) { + e.get_mut().end = usage; + Ok(UseAction::Replace { old }) + } else { + Err(old) + } + } + } + } + + pub(crate) fn use_texture( + &self, id: Stored, usage: TextureUsageFlags, permit: UsePermit, + ) -> Result, TextureUsageFlags> { + match self.textures.lock().unwrap().entry(id) { + Entry::Vacant(e) => { + e.insert(usage .. usage); + Ok(UseAction::Init) + } + Entry::Occupied(mut e) => { + let old = e.get().end; + if usage == old { + Ok(UseAction::Keep) + } else if permit.contains(UsePermit::EXTEND) && + !TextureUsageFlags::WRITE_ALL.intersects(old | usage) + { + e.get_mut().end |= usage; + Ok(UseAction::Extend { old }) + } else if permit.contains(UsePermit::REPLACE) { + e.get_mut().end = usage; + Ok(UseAction::Replace { old }) + } else { + Err(old) + } + } + } + } +}