Basic resource tracking

This commit is contained in:
Dzmitry Malyshau 2018-10-19 10:34:19 -04:00
parent 5462690c4a
commit 0fca6930d9
6 changed files with 140 additions and 41 deletions

View File

@ -1,4 +1,5 @@
use registry::{HUB, Items, Registry}; use registry::{HUB, Items, Registry};
use track::{Tracker};
use { use {
Stored, Stored,
CommandBufferId, RenderPassId, CommandBufferId, RenderPassId,
@ -14,6 +15,7 @@ pub struct RenderPass<B: hal::Backend> {
raw: B::CommandBuffer, raw: B::CommandBuffer,
parent: B::CommandBuffer, parent: B::CommandBuffer,
cmb_id: Stored<CommandBufferId>, cmb_id: Stored<CommandBufferId>,
tracker: Tracker,
} }
impl<B: hal::Backend> RenderPass<B> { impl<B: hal::Backend> RenderPass<B> {
@ -26,6 +28,7 @@ impl<B: hal::Backend> RenderPass<B> {
raw, raw,
parent, parent,
cmb_id: Stored(cmb_id), cmb_id: Stored(cmb_id),
tracker: Tracker::default(),
} }
} }
} }

View File

@ -244,7 +244,9 @@ fn checked_u32_as_u16(value: u32) -> u16 {
value as 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 hal::image::Kind as H;
use resource::TextureDimension::*; use resource::TextureDimension::*;
let Extent3d { width, height, depth } = size; 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 { pub(crate) fn map_texture_usage_flags(
use hal::image::Usage as H; flags: resource::TextureUsageFlags, format: hal::format::Format
use resource::{ ) -> hal::image::Usage {
TextureUsageFlags_TRANSFER_SRC, TextureUsageFlags_TRANSFER_DST, TextureUsageFlags_SAMPLED, use hal::image::Usage as U;
TextureUsageFlags_STORAGE, TextureUsageFlags_OUTPUT_ATTACHMENT, use resource::TextureUsageFlags as W;
};
let mut value = H::empty(); let mut value = U::empty();
if 0 != flags & TextureUsageFlags_TRANSFER_SRC { if flags.contains(W::TRANSFER_SRC) {
value |= H::TRANSFER_SRC; value |= U::TRANSFER_SRC;
} }
if 0 != flags & TextureUsageFlags_TRANSFER_DST { if flags.contains(W::TRANSFER_DST) {
value |= H::TRANSFER_DST; value |= U::TRANSFER_DST;
} }
if 0 != flags & TextureUsageFlags_SAMPLED { if flags.contains(W::SAMPLED) {
value |= H::SAMPLED; value |= U::SAMPLED;
} }
if 0 != flags & TextureUsageFlags_STORAGE { if flags.contains(W::STORAGE) {
value |= H::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) { 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 { } else {
value |= H::COLOR_ATTACHMENT; value |= U::COLOR_ATTACHMENT;
} }
} }
// Note: TextureUsageFlags::Present does not need to be handled explicitly // Note: TextureUsageFlags::Present does not need to be handled explicitly

View File

@ -1,6 +1,8 @@
use {back, binding_model, command, conv, pipeline, resource}; use {back, binding_model, command, conv, pipeline, resource};
use registry::{HUB, Items, Registry}; use registry::{HUB, Items, Registry};
use track::{Tracker, UsePermit};
use { use {
Stored,
AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId, AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId,
DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, TextureId, DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, TextureId,
}; };
@ -18,6 +20,7 @@ pub struct Device<B: hal::Backend> {
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>,
tracker: Tracker,
mem_props: hal::MemoryProperties, mem_props: hal::MemoryProperties,
} }
@ -53,6 +56,7 @@ 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,
tracker: Tracker::default(),
mem_props, mem_props,
} }
} }
@ -101,11 +105,16 @@ pub extern "C" fn wgpu_device_create_texture(
.raw .raw
.bind_image_memory(&image_memory, 0, image_unbound) .bind_image_memory(&image_memory, 0, image_unbound)
.unwrap(); .unwrap();
HUB.textures
let id = HUB.textures
.lock() .lock()
.register(resource::Texture { .register(resource::Texture {
raw: bound_image, raw: bound_image,
}) });
device.tracker.use_texture(Stored(id), resource::TextureUsageFlags::empty(), UsePermit::empty())
.expect("Resource somehow is already registered");
id
} }
#[no_mangle] #[no_mangle]
@ -216,7 +225,7 @@ pub extern "C" fn wgpu_device_create_command_buffer(
_desc: &command::CommandBufferDescriptor, _desc: &command::CommandBufferDescriptor,
) -> CommandBufferId { ) -> CommandBufferId {
let mut device_guard = HUB.devices.lock(); 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); let mut cmd_buf = device.com_allocator.allocate(device_id, &device.raw);
cmd_buf.raw.last_mut().unwrap().begin( cmd_buf.raw.last_mut().unwrap().begin(

View File

@ -29,6 +29,7 @@ mod instance;
mod pipeline; mod pipeline;
mod registry; mod registry;
mod resource; mod resource;
mod track;
pub use self::binding_model::*; pub use self::binding_model::*;
pub use self::command::*; pub use self::command::*;
@ -40,7 +41,7 @@ pub use self::resource::*;
use back::Backend as B; use back::Backend as B;
use registry::Id; use registry::Id;
#[derive(Debug, PartialEq)] #[derive(Debug, Hash, PartialEq, Eq)]
struct Stored<T>(T); struct Stored<T>(T);
#[cfg(not(feature = "remote"))] #[cfg(not(feature = "remote"))]
unsafe impl<T> Sync for Stored<T> {} unsafe impl<T> Sync for Stored<T> {}

View File

@ -1,11 +1,11 @@
use {Extent3d};
use hal; use hal;
use Extent3d;
bitflags! { bitflags! {
#[repr(transparent)] #[repr(transparent)]
pub struct BufferUsageFlags: u32 { pub struct BufferUsageFlags: u32 {
const NONE = 0;
const MAP_READ = 1; const MAP_READ = 1;
const MAP_WRITE = 2; const MAP_WRITE = 2;
const TRANSFER_SRC = 4; const TRANSFER_SRC = 4;
@ -14,6 +14,8 @@ bitflags! {
const VERTEX = 32; const VERTEX = 32;
const UNIFORM = 64; const UNIFORM = 64;
const STORAGE = 128; const STORAGE = 128;
const NONE = 0;
const WRITE_ALL = 2 + 8 + 128;
} }
} }
@ -50,22 +52,19 @@ pub enum TextureFormat {
D32FloatS8Uint = 3, D32FloatS8Uint = 3,
} }
// TODO: bitflags bitflags! {
pub type TextureUsageFlags = u32; #[repr(transparent)]
#[allow(non_upper_case_globals)] pub struct TextureUsageFlags: u32 {
pub const TextureUsageFlags_NONE: u32 = 0; const TRANSFER_SRC = 1;
#[allow(non_upper_case_globals)] const TRANSFER_DST = 2;
pub const TextureUsageFlags_TRANSFER_SRC: u32 = 1; const SAMPLED = 4;
#[allow(non_upper_case_globals)] const STORAGE = 8;
pub const TextureUsageFlags_TRANSFER_DST: u32 = 2; const OUTPUT_ATTACHMENT = 16;
#[allow(non_upper_case_globals)] const PRESENT = 32;
pub const TextureUsageFlags_SAMPLED: u32 = 4; const NONE = 0;
#[allow(non_upper_case_globals)] const WRITE_ALL = 2 + 8 + 16;
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;
#[repr(C)] #[repr(C)]
pub struct TextureDescriptor { pub struct TextureDescriptor {

85
wgpu-native/src/track.rs Normal file
View File

@ -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<T> {
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<HashMap<Stored<BufferId>, Range<BufferUsageFlags>>>,
textures: Mutex<HashMap<Stored<TextureId>, Range<TextureUsageFlags>>>,
}
impl Tracker {
pub(crate) fn use_buffer(
&self, id: Stored<BufferId>, usage: BufferUsageFlags, permit: UsePermit,
) -> Result<UseAction<BufferUsageFlags>, 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<TextureId>, usage: TextureUsageFlags, permit: UsePermit,
) -> Result<UseAction<TextureUsageFlags>, 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)
}
}
}
}
}