diff --git a/wgpu-native/src/command/mod.rs b/wgpu-native/src/command/mod.rs index 14bdbcf89..4e699cc80 100644 --- a/wgpu-native/src/command/mod.rs +++ b/wgpu-native/src/command/mod.rs @@ -6,15 +6,17 @@ pub use self::allocator::CommandAllocator; pub use self::compute::*; pub use self::render::*; -use hal; +use hal::{self, Device}; use { Color, Origin3d, Stored, BufferId, CommandBufferId, ComputePassId, DeviceId, RenderPassId, TextureId, TextureViewId, }; +use conv; use registry::{HUB, Items, Registry}; use track::{BufferTracker, TextureTracker}; +use std::iter; use std::thread::ThreadId; @@ -88,17 +90,72 @@ pub struct CommandBufferDescriptor {} #[no_mangle] pub extern "C" fn wgpu_command_buffer_begin_render_pass( command_buffer_id: CommandBufferId, - _descriptor: RenderPassDescriptor, + desc: RenderPassDescriptor, ) -> RenderPassId { let mut cmb_guard = HUB.command_buffers.lock(); let cmb = cmb_guard.get_mut(command_buffer_id); - let device_guard = HUB.devices.lock(); let device = device_guard.get(cmb.device_id.0); let current_comb = device.com_allocator.extend(cmb); - //let render_pass = device.create_render_pass(); + let render_pass = { + let tracker = &mut cmb.texture_tracker; + let view_guard = HUB.texture_views.lock(); + + let depth_stencil_attachment = match desc.depth_stencil_attachment { + Some(ref at) => { + let view = view_guard.get(at.attachment); + let query = tracker.query(view.source_id.0); + let (_, layout) = conv::map_texture_state( + query.usage, + hal::format::Aspects::DEPTH | hal::format::Aspects::STENCIL, + ); + Some(hal::pass::Attachment { + format: Some(conv::map_texture_format(view.format)), + samples: view.samples, + ops: conv::map_load_store_ops(at.depth_load_op, at.depth_store_op), + stencil_ops: conv::map_load_store_ops(at.stencil_load_op, at.stencil_store_op), + layouts: layout .. layout, + }) + } + None => None, + }; + let color_attachments = desc.color_attachments + .iter() + .map(|at| { + let view = view_guard.get(at.attachment); + let query = tracker.query(view.source_id.0); + let (_, layout) = conv::map_texture_state(query.usage, hal::format::Aspects::COLOR); + hal::pass::Attachment { + format: Some(conv::map_texture_format(view.format)), + samples: view.samples, + ops: conv::map_load_store_ops(at.load_op, at.store_op), + stencil_ops: hal::pass::AttachmentOps::DONT_CARE, + layouts: layout .. layout, + } + }); + let attachments = color_attachments.chain(depth_stencil_attachment); + + //TODO: retain the storage + let color_refs = (0 .. desc.color_attachments.len()) + .map(|i| { + (i, hal::image::Layout::ColorAttachmentOptimal) + }) + .collect::>(); + let ds_ref = desc.depth_stencil_attachment.as_ref().map(|_| { + (desc.color_attachments.len(), hal::image::Layout::DepthStencilAttachmentOptimal) + }); + let subpass = hal::pass::SubpassDesc { + colors: &color_refs, + depth_stencil: ds_ref.as_ref(), + inputs: &[], + resolves: &[], + preserves: &[], + }; + + device.raw.create_render_pass(attachments, iter::once(subpass), &[]) + }; //let framebuffer = device.create_framebuffer(); /*TODO: diff --git a/wgpu-native/src/conv.rs b/wgpu-native/src/conv.rs index c266e1e8f..c84f8a366 100644 --- a/wgpu-native/src/conv.rs +++ b/wgpu-native/src/conv.rs @@ -1,6 +1,6 @@ use hal; -use {Extent3d, binding_model, pipeline, resource}; +use {Extent3d, binding_model, command, pipeline, resource}; pub fn map_buffer_usage( @@ -358,3 +358,15 @@ pub fn map_texture_state( (access, layout) } + +pub fn map_load_store_ops(load: command::LoadOp, store: command::StoreOp) -> hal::pass::AttachmentOps { + hal::pass::AttachmentOps { + load: match load { + command::LoadOp::Clear => hal::pass::AttachmentLoadOp::Clear, + command::LoadOp::Load => hal::pass::AttachmentLoadOp::Load, + }, + store: match store { + command::StoreOp::Store => hal::pass::AttachmentStoreOp::Store, + }, + } +} diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index 3c7c4e6ad..539da439d 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -1,6 +1,6 @@ use {back, binding_model, command, conv, pipeline, resource}; use registry::{HUB, Items, Registry}; -use track::{BufferTracker, TextureTracker, TrackPermit}; +use track::{BufferTracker, TextureTracker}; use { AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId, DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, TextureId, @@ -115,11 +115,11 @@ pub extern "C" fn wgpu_device_create_texture( raw: bound_image, aspects, }); - device.texture_tracker + let query = device.texture_tracker .lock() .unwrap() - .track(id, resource::TextureUsageFlags::empty(), TrackPermit::empty()) - .expect("Resource somehow is already registered"); + .query(id); + assert!(query.initialized); id } diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index f1705c5bb..88932c393 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -100,6 +100,7 @@ type BufferHandle = Buffer; // Resource pub type TextureViewId = Id; +type TextureViewHandle = TextureView; pub type TextureId = Id; type TextureHandle = Texture; pub type SamplerId = Id; diff --git a/wgpu-native/src/registry/mod.rs b/wgpu-native/src/registry/mod.rs index 935732323..5c5344efe 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, - BufferHandle, TextureHandle, + BufferHandle, TextureHandle, TextureViewHandle, }; @@ -50,6 +50,7 @@ pub struct Hub { pub(crate) compute_passes: ConcreteRegistry, pub(crate) buffers: ConcreteRegistry, pub(crate) textures: ConcreteRegistry, + pub(crate) texture_views: ConcreteRegistry, } lazy_static! { diff --git a/wgpu-native/src/resource.rs b/wgpu-native/src/resource.rs index 14df48e7a..45b7e674a 100644 --- a/wgpu-native/src/resource.rs +++ b/wgpu-native/src/resource.rs @@ -1,4 +1,4 @@ -use {Extent3d}; +use {Extent3d, Stored, TextureId}; use hal; @@ -32,9 +32,6 @@ pub(crate) struct Buffer { // TODO: mapping, unmap() } -pub struct TextureView { - // TODO -} #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] @@ -81,6 +78,13 @@ pub(crate) struct Texture { pub aspects: hal::format::Aspects, } +pub(crate) struct TextureView { + pub raw: B::ImageView, + pub source_id: Stored, + pub format: TextureFormat, + pub samples: hal::image::NumSamples, +} + #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum AddressMode { diff --git a/wgpu-native/src/track.rs b/wgpu-native/src/track.rs index 752e06116..ee628b1b7 100644 --- a/wgpu-native/src/track.rs +++ b/wgpu-native/src/track.rs @@ -14,6 +14,12 @@ pub enum Tracktion { Replace { old: T }, } +#[derive(Clone, Debug, PartialEq)] +pub struct Query { + pub usage: T, + pub initialized: bool, +} + bitflags! { pub struct TrackPermit: u32 { const EXTEND = 1; @@ -23,14 +29,21 @@ bitflags! { pub trait GenericUsage { + fn default() -> Self; fn is_exclusive(&self) -> bool; } impl GenericUsage for BufferUsageFlags { + fn default() -> Self { + BufferUsageFlags::empty() + } fn is_exclusive(&self) -> bool { BufferUsageFlags::WRITE_ALL.intersects(*self) } } impl GenericUsage for TextureUsageFlags { + fn default() -> Self { + TextureUsageFlags::empty() + } fn is_exclusive(&self) -> bool { TextureUsageFlags::WRITE_ALL.intersects(*self) } @@ -53,7 +66,26 @@ impl< } } - pub fn track(&mut self, id: I, usage: U, permit: TrackPermit) -> Result, U> { + pub fn query(&mut self, id: I) -> Query { + match self.map.entry(Stored(id)) { + Entry::Vacant(e) => { + let usage = U::default(); + e.insert(usage); + Query { + usage, + initialized: true, + } + } + Entry::Occupied(e) => { + Query { + usage: *e.get(), + initialized: false, + } + } + } + } + + pub fn transit(&mut self, id: I, usage: U, permit: TrackPermit) -> Result, U> { match self.map.entry(Stored(id)) { Entry::Vacant(e) => { e.insert(usage); @@ -77,7 +109,7 @@ impl< pub(crate) fn consume<'a>(&'a mut self, other: Self) -> impl 'a + Iterator)> { other.map .into_iter() - .flat_map(move |(id, new)| match self.track(id.0.clone(), new, TrackPermit::REPLACE) { + .flat_map(move |(id, new)| match self.transit(id.0.clone(), new, TrackPermit::REPLACE) { Ok(Tracktion::Init) | Ok(Tracktion::Keep) => None, Ok(Tracktion::Replace { old }) => Some((id.0, old .. new)),