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 track::{Tracker};
use {
Stored,
CommandBufferId, RenderPassId,
@ -14,6 +15,7 @@ pub struct RenderPass<B: hal::Backend> {
raw: B::CommandBuffer,
parent: B::CommandBuffer,
cmb_id: Stored<CommandBufferId>,
tracker: Tracker,
}
impl<B: hal::Backend> RenderPass<B> {
@ -26,6 +28,7 @@ impl<B: hal::Backend> RenderPass<B> {
raw,
parent,
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
}
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

View File

@ -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<B: hal::Backend> {
queue_group: hal::QueueGroup<B, hal::General>,
mem_allocator: Heaps<B::Memory>,
pub(crate) com_allocator: command::CommandAllocator<B>,
tracker: Tracker,
mem_props: hal::MemoryProperties,
}
@ -53,6 +56,7 @@ impl<B: hal::Backend> Device<B> {
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(

View File

@ -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>(T);
#[cfg(not(feature = "remote"))]
unsafe impl<T> Sync for Stored<T> {}

View File

@ -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 {

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)
}
}
}
}
}