From b27650bfcded3608d4695b4727710c338240e8cc Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 19 Oct 2018 12:07:07 -0400 Subject: [PATCH] Buffer transitions for a render pass --- wgpu-native/src/command/allocator.rs | 3 ++ wgpu-native/src/command/mod.rs | 4 ++ wgpu-native/src/command/render.rs | 44 ++++++++++++++----- wgpu-native/src/conv.rs | 48 +++++++++++++++++---- wgpu-native/src/device.rs | 21 ++++++---- wgpu-native/src/lib.rs | 1 + wgpu-native/src/registry/mod.rs | 3 +- wgpu-native/src/resource.rs | 10 ++--- wgpu-native/src/track.rs | 63 +++++++++++++--------------- 9 files changed, 130 insertions(+), 67 deletions(-) diff --git a/wgpu-native/src/command/allocator.rs b/wgpu-native/src/command/allocator.rs index 899c0ad002..d37b4e5e4e 100644 --- a/wgpu-native/src/command/allocator.rs +++ b/wgpu-native/src/command/allocator.rs @@ -1,5 +1,6 @@ use super::CommandBuffer; use {DeviceId, Stored}; +use track::{Tracker}; use hal::command::RawCommandBuffer; use hal::pool::RawCommandPool; @@ -90,6 +91,8 @@ impl CommandAllocator { fence, recorded_thread_id: thread_id, device_id: Stored(device_id), + buffer_tracker: Tracker::new(), + texture_tracker: Tracker::new(), } } diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index d4dd5658be..14bdbcf897 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -13,9 +13,11 @@ use { BufferId, CommandBufferId, ComputePassId, DeviceId, RenderPassId, TextureId, TextureViewId, }; use registry::{HUB, Items, Registry}; +use track::{BufferTracker, TextureTracker}; use std::thread::ThreadId; + #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum LoadOp { @@ -76,6 +78,8 @@ pub struct CommandBuffer { fence: B::Fence, recorded_thread_id: ThreadId, device_id: Stored, + buffer_tracker: BufferTracker, + texture_tracker: TextureTracker, } #[repr(C)] diff --git a/wgpu-native/src/command/render.rs b/wgpu-native/src/command/render.rs index 2c5892738d..3ee3f7d1db 100644 --- a/wgpu-native/src/command/render.rs +++ b/wgpu-native/src/command/render.rs @@ -1,5 +1,6 @@ +use conv; use registry::{HUB, Items, Registry}; -use track::{Tracker}; +use track::{BufferTracker, TextureTracker, Tracktion, TrackPermit}; use { Stored, CommandBufferId, RenderPassId, @@ -8,13 +9,12 @@ use { use hal; use hal::command::RawCommandBuffer; -use std::iter; - pub struct RenderPass { raw: B::CommandBuffer, cmb_id: Stored, - tracker: Tracker, + buffer_tracker: BufferTracker, + texture_tracker: TextureTracker, } impl RenderPass { @@ -25,7 +25,8 @@ impl RenderPass { RenderPass { raw, cmb_id: Stored(cmb_id), - tracker: Tracker::default(), + buffer_tracker: BufferTracker::new(), + texture_tracker: TextureTracker::new(), } } } @@ -39,11 +40,34 @@ pub extern "C" fn wgpu_render_pass_end_pass( .take(pass_id); pass.raw.end_render_pass(); - HUB.command_buffers - .lock() - .get_mut(pass.cmb_id.0) - .raw - .push(pass.raw); + let buffer_guard = HUB.buffers.lock(); + //let texture_guard = HUB.textures.lock(); + let mut cmb_guard = HUB.command_buffers.lock(); + let cmb = cmb_guard.get_mut(pass.cmb_id.0); + let cmb_buffers = &mut cmb.buffer_tracker; + let buffer_barriers = pass.buffer_tracker + .finish() + .into_iter() + .flat_map(|(id, new)| { + match cmb_buffers.track(id.0, new, TrackPermit::REPLACE) { + Ok(Tracktion::Init) => None, + Ok(Tracktion::Keep) => None, + Ok(Tracktion::Replace { old }) => Some(hal::memory::Barrier::Buffer { + states: conv::map_buffer_state(old) .. conv::map_buffer_state(new), + target: &buffer_guard.get(id.0).raw, + }), + Ok(Tracktion::Extend { .. }) | + Err(_) => panic!("Unable to do the resource transition for a pass"), + } + }); + + pass.raw.pipeline_barrier( + hal::pso::PipelineStage::TOP_OF_PIPE .. hal::pso::PipelineStage::BOTTOM_OF_PIPE, + hal::memory::Dependencies::empty(), + buffer_barriers, + ); + + cmb.raw.push(pass.raw); pass.cmb_id.0 } diff --git a/wgpu-native/src/conv.rs b/wgpu-native/src/conv.rs index 204ae14d66..38818f2f70 100644 --- a/wgpu-native/src/conv.rs +++ b/wgpu-native/src/conv.rs @@ -2,7 +2,8 @@ use hal; use {Extent3d, binding_model, pipeline, resource}; -pub(crate) fn map_buffer_usage( + +pub fn map_buffer_usage( usage: resource::BufferUsageFlags, ) -> (hal::buffer::Usage, hal::memory::Properties) { use hal::buffer::Usage as U; @@ -40,7 +41,7 @@ pub(crate) fn map_buffer_usage( (hal_usage, hal_memory) } -pub(crate) fn map_binding_type( +pub fn map_binding_type( binding_ty: binding_model::BindingType, ) -> hal::pso::DescriptorType { use binding_model::BindingType::*; @@ -53,7 +54,7 @@ pub(crate) fn map_binding_type( } } -pub(crate) fn map_shader_stage_flags( +pub fn map_shader_stage_flags( shader_stage_flags: binding_model::ShaderStageFlags, ) -> hal::pso::ShaderStageFlags { use binding_model::{ @@ -73,7 +74,7 @@ pub(crate) fn map_shader_stage_flags( value } -pub(crate) fn map_primitive_topology( +pub fn map_primitive_topology( primitive_topology: pipeline::PrimitiveTopology, ) -> hal::Primitive { use hal::Primitive as H; @@ -87,7 +88,7 @@ pub(crate) fn map_primitive_topology( } } -pub(crate) fn map_blend_state_descriptor( +pub fn map_blend_state_descriptor( desc: &pipeline::BlendStateDescriptor, ) -> hal::pso::ColorBlendDesc { let color_mask = desc.write_mask; @@ -164,7 +165,7 @@ fn map_blend_factor(blend_factor: pipeline::BlendFactor) -> hal::pso::Factor { } } -pub(crate) fn map_depth_stencil_state( +pub fn map_depth_stencil_state( desc: &pipeline::DepthStencilStateDescriptor, ) -> hal::pso::DepthStencilDesc { hal::pso::DepthStencilDesc { @@ -228,7 +229,7 @@ fn map_stencil_operation(stencil_operation: pipeline::StencilOperation) -> hal:: } } -pub(crate) fn map_texture_format(texture_format: resource::TextureFormat) -> hal::format::Format { +pub fn map_texture_format(texture_format: resource::TextureFormat) -> hal::format::Format { use hal::format::Format as H; use resource::TextureFormat::*; match texture_format { @@ -244,7 +245,7 @@ fn checked_u32_as_u16(value: u32) -> u16 { value as u16 } -pub(crate) fn map_texture_dimension_size( +pub fn map_texture_dimension_size( dimension: resource::TextureDimension, size: Extent3d ) -> hal::image::Kind { use hal::image::Kind as H; @@ -260,7 +261,7 @@ pub(crate) fn map_texture_dimension_size( } } -pub(crate) fn map_texture_usage_flags( +pub fn map_texture_usage( flags: resource::TextureUsageFlags, format: hal::format::Format ) -> hal::image::Usage { use hal::image::Usage as U; @@ -290,3 +291,32 @@ pub(crate) fn map_texture_usage_flags( // TODO: HAL Transient Attachment, HAL Input Attachment value } + +pub fn map_buffer_state( + usage: resource::BufferUsageFlags, +) -> hal::buffer::State { + use hal::buffer::Access as A; + use resource::BufferUsageFlags as W; + + let mut access = A::empty(); + if usage.contains(W::TRANSFER_SRC) { + access |= A::TRANSFER_READ; + } + if usage.contains(W::TRANSFER_DST) { + access |= A::TRANSFER_WRITE; + } + if usage.contains(W::INDEX) { + access |= A::INDEX_BUFFER_READ; + } + if usage.contains(W::VERTEX) { + access |= A::VERTEX_BUFFER_READ; + } + if usage.contains(W::UNIFORM) { + access |= A::CONSTANT_BUFFER_READ | A::SHADER_READ; + } + if usage.contains(W::STORAGE) { + access |= A::SHADER_WRITE; + } + + access +} diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index 3a52453173..fb40e4017e 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -1,8 +1,7 @@ use {back, binding_model, command, conv, pipeline, resource}; use registry::{HUB, Items, Registry}; -use track::{Tracker, UsePermit}; +use track::{BufferTracker, TextureTracker, TrackPermit}; use { - Stored, AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId, DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, TextureId, }; @@ -10,9 +9,10 @@ use { use hal::command::RawCommandBuffer; use hal::queue::RawCommandQueue; use hal::{self, Device as _Device}; +use rendy_memory::{allocator, Config, Heaps}; use std::{ffi, slice}; -use rendy_memory::{allocator, Config, Heaps}; +use std::sync::Mutex; pub struct Device { @@ -20,7 +20,8 @@ pub struct Device { queue_group: hal::QueueGroup, mem_allocator: Heaps, pub(crate) com_allocator: command::CommandAllocator, - tracker: Tracker, + buffer_tracker: Mutex, + texture_tracker: Mutex, mem_props: hal::MemoryProperties, } @@ -56,7 +57,8 @@ impl Device { mem_allocator, com_allocator: command::CommandAllocator::new(queue_group.family()), queue_group, - tracker: Tracker::default(), + buffer_tracker: Mutex::new(BufferTracker::new()), + texture_tracker: Mutex::new(TextureTracker::new()), mem_props, } } @@ -73,7 +75,7 @@ pub extern "C" fn wgpu_device_create_texture( ) -> TextureId { let kind = conv::map_texture_dimension_size(desc.dimension, desc.size); let format = conv::map_texture_format(desc.format); - let usage = conv::map_texture_usage_flags(desc.usage, format); + let usage = conv::map_texture_usage(desc.usage, format); let device_guard = HUB.devices.lock(); let device = &device_guard.get(device_id); let image_unbound = device @@ -111,7 +113,10 @@ pub extern "C" fn wgpu_device_create_texture( .register(resource::Texture { raw: bound_image, }); - device.tracker.use_texture(Stored(id), resource::TextureUsageFlags::empty(), UsePermit::empty()) + device.texture_tracker + .lock() + .unwrap() + .track(id, resource::TextureUsageFlags::empty(), TrackPermit::empty()) .expect("Resource somehow is already registered"); id @@ -224,7 +229,7 @@ pub extern "C" fn wgpu_device_create_command_buffer( device_id: DeviceId, _desc: &command::CommandBufferDescriptor, ) -> CommandBufferId { - let mut device_guard = HUB.devices.lock(); + let device_guard = HUB.devices.lock(); let device = device_guard.get(device_id); let mut cmd_buf = device.com_allocator.allocate(device_id, &device.raw); diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index 5445b4989f..f1705c5bbe 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -96,6 +96,7 @@ pub type DeviceId = Id; type DeviceHandle = Device; pub type QueueId = Id; pub type BufferId = Id; +type BufferHandle = Buffer; // Resource pub type TextureViewId = Id; diff --git a/wgpu-native/src/registry/mod.rs b/wgpu-native/src/registry/mod.rs index ca9a32b5c2..935732323f 100644 --- a/wgpu-native/src/registry/mod.rs +++ b/wgpu-native/src/registry/mod.rs @@ -13,7 +13,7 @@ use { BlendStateHandle, CommandBufferHandle, DepthStencilStateHandle, DeviceHandle, InstanceHandle, RenderPassHandle, ComputePassHandle, PipelineLayoutHandle, RenderPipelineHandle, ComputePipelineHandle, ShaderModuleHandle, - TextureHandle, + BufferHandle, TextureHandle, }; @@ -48,6 +48,7 @@ pub struct Hub { pub(crate) compute_pipelines: ConcreteRegistry, pub(crate) render_passes: ConcreteRegistry, pub(crate) compute_passes: ConcreteRegistry, + pub(crate) buffers: ConcreteRegistry, pub(crate) textures: ConcreteRegistry, } diff --git a/wgpu-native/src/resource.rs b/wgpu-native/src/resource.rs index 6a6f40ee50..6517e01d17 100644 --- a/wgpu-native/src/resource.rs +++ b/wgpu-native/src/resource.rs @@ -25,9 +25,9 @@ pub struct BufferDescriptor { pub usage: BufferUsageFlags, } -pub struct Buffer { - pub(crate) raw: B::UnboundBuffer, - pub(crate) memory_properties: hal::memory::Properties, +pub(crate) struct Buffer { + pub raw: B::UnboundBuffer, + pub memory_properties: hal::memory::Properties, // TODO: mapping, unmap() } @@ -75,8 +75,8 @@ pub struct TextureDescriptor { pub usage: TextureUsageFlags, } -pub struct Texture { - pub(crate) raw: B::Image, +pub(crate) struct Texture { + pub raw: B::Image, } #[repr(C)] diff --git a/wgpu-native/src/track.rs b/wgpu-native/src/track.rs index d3584bb51e..4e5b3bb55f 100644 --- a/wgpu-native/src/track.rs +++ b/wgpu-native/src/track.rs @@ -4,11 +4,10 @@ use resource::{BufferUsageFlags, TextureUsageFlags}; use std::collections::hash_map::{Entry, HashMap}; use std::hash::Hash; use std::ops::BitOr; -use std::sync::Mutex; #[derive(Clone, Debug, PartialEq)] -pub enum UseAction { +pub enum Tracktion { Init, Keep, Extend { old: T }, @@ -16,14 +15,14 @@ pub enum UseAction { } bitflags! { - pub struct UsePermit: u32 { + pub struct TrackPermit: u32 { const EXTEND = 1; const REPLACE = 2; } } -trait GenericUsage { +pub trait GenericUsage { fn is_exclusive(&self) -> bool; } impl GenericUsage for BufferUsageFlags { @@ -37,33 +36,37 @@ impl GenericUsage for TextureUsageFlags { } } -#[derive(Default)] -pub struct Tracker { - buffers: Mutex, BufferUsageFlags>>, - textures: Mutex, TextureUsageFlags>>, -} -impl Tracker { - fn use_impl( - map: &mut HashMap, id: I, usage: U, permit: UsePermit - ) -> Result, U> - where - I: Hash + Eq, - U: Copy + GenericUsage + BitOr + PartialEq, - { - match map.entry(id) { +pub struct Tracker { + map: HashMap, U>, +} +pub type BufferTracker = Tracker; +pub type TextureTracker = Tracker; + +impl< + I: Hash + Eq, + U: Copy + GenericUsage + BitOr + PartialEq, +> Tracker { + pub fn new() -> Self { + Tracker { + map: HashMap::new(), + } + } + + pub fn track(&mut self, id: I, usage: U, permit: TrackPermit) -> Result, U> { + match self.map.entry(Stored(id)) { Entry::Vacant(e) => { e.insert(usage); - Ok(UseAction::Init) + Ok(Tracktion::Init) } Entry::Occupied(mut e) => { let old = *e.get(); if usage == old { - Ok(UseAction::Keep) - } else if permit.contains(UsePermit::EXTEND) && !(old | usage).is_exclusive() { - Ok(UseAction::Extend { old: e.insert(old | usage) }) - } else if permit.contains(UsePermit::REPLACE) { - Ok(UseAction::Replace { old: e.insert(usage) }) + Ok(Tracktion::Keep) + } else if permit.contains(TrackPermit::EXTEND) && !(old | usage).is_exclusive() { + Ok(Tracktion::Extend { old: e.insert(old | usage) }) + } else if permit.contains(TrackPermit::REPLACE) { + Ok(Tracktion::Replace { old: e.insert(usage) }) } else { Err(old) } @@ -71,15 +74,7 @@ impl Tracker { } } - pub(crate) fn use_buffer( - &self, id: Stored, usage: BufferUsageFlags, permit: UsePermit, - ) -> Result, BufferUsageFlags> { - Self::use_impl(&mut *self.buffers.lock().unwrap(), id, usage, permit) - } - - pub(crate) fn use_texture( - &self, id: Stored, usage: TextureUsageFlags, permit: UsePermit, - ) -> Result, TextureUsageFlags> { - Self::use_impl(&mut *self.textures.lock().unwrap(), id, usage, permit) + pub(crate) fn finish(self) -> HashMap, U> { + self.map } }