diff --git a/examples/hello_triangle_rust/main.rs b/examples/hello_triangle_rust/main.rs index 5cd9d225ce..4f63bf0349 100644 --- a/examples/hello_triangle_rust/main.rs +++ b/examples/hello_triangle_rust/main.rs @@ -37,9 +37,6 @@ fn main() { let blend_state0 = device.create_blend_state(&wgpu::BlendStateDescriptor::REPLACE); let depth_stencil_state = device.create_depth_stencil_state(&wgpu::DepthStencilStateDescriptor::IGNORE); - let attachment_state = device.create_attachment_state(&wgpu::AttachmentStateDescriptor { - formats: &[wgpu::TextureFormat::R8g8b8a8Unorm], - }); let _render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { layout: &pipeline_layout, @@ -56,11 +53,19 @@ fn main() { }, ], primitive_topology: wgpu::PrimitiveTopology::TriangleList, + attachments_state: wgpu::AttachmentsState { + color_attachments: &[ + wgpu::Attachment { + format: wgpu::TextureFormat::R8g8b8a8Unorm, + samples: 1, + }, + ], + depth_stencil_attachment: None, + }, blend_states: &[ &blend_state0, ], depth_stencil_state: &depth_stencil_state, - attachment_state: &attachment_state, }); let mut cmd_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor {}); diff --git a/wgpu-native/src/device.rs b/wgpu-native/src/device.rs index 43f8a2dbd5..2e0e55efcd 100644 --- a/wgpu-native/src/device.rs +++ b/wgpu-native/src/device.rs @@ -3,7 +3,7 @@ use registry::{HUB, Items, Registry}; use track::{BufferTracker, TextureTracker}; use { CommandBuffer, Stored, TextureUsageFlags, - AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId, + BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId, DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, TextureId, TextureViewId, }; @@ -14,9 +14,17 @@ use hal::{self, Device as _Device}; use rendy_memory::{allocator, Config, Heaps}; use std::{ffi, slice}; +use std::collections::hash_map::{Entry, HashMap}; use std::sync::Mutex; +#[derive(Hash, PartialEq)] +pub(crate) struct RenderPassKey { + pub attachments: Vec, +} +impl Eq for RenderPassKey {} + + pub struct Device { pub(crate) raw: B::Device, queue_group: hal::QueueGroup, @@ -25,6 +33,7 @@ pub struct Device { buffer_tracker: Mutex, texture_tracker: Mutex, mem_props: hal::MemoryProperties, + render_passes: Mutex>, } impl Device { @@ -62,6 +71,7 @@ impl Device { buffer_tracker: Mutex::new(BufferTracker::new()), texture_tracker: Mutex::new(TextureTracker::new()), mem_props, + render_passes: Mutex::new(HashMap::new()), } } } @@ -399,59 +409,6 @@ pub extern "C" fn wgpu_queue_submit( } } -#[no_mangle] -pub extern "C" fn wgpu_device_create_attachment_state( - device_id: DeviceId, - desc: &pipeline::AttachmentStateDescriptor, -) -> AttachmentStateId { - let device_guard = HUB.devices.lock(); - let device = &device_guard.get(device_id).raw; - - let color_formats = unsafe { - slice::from_raw_parts(desc.formats, desc.formats_length) - }; - let color_formats: Vec<_> = color_formats - .iter() - .cloned() - .map(conv::map_texture_format) - .collect(); - let depth_stencil_format = None; - - let base_pass = { - let attachments = color_formats.iter().map(|cf| hal::pass::Attachment { - format: Some(*cf), - samples: 1, - ops: hal::pass::AttachmentOps::DONT_CARE, - stencil_ops: hal::pass::AttachmentOps::DONT_CARE, - layouts: hal::image::Layout::General .. hal::image::Layout::General, - }); - - let subpass = hal::pass::SubpassDesc { - colors: &[(0, hal::image::Layout::ColorAttachmentOptimal)], - depth_stencil: None, - inputs: &[], - resolves: &[], - preserves: &[], - }; - - device.create_render_pass( - attachments, - &[subpass], - &[], - ) - }; - - let at_state = pipeline::AttachmentState { - base_pass, - color_formats, - depth_stencil_format, - }; - - HUB.attachment_states - .lock() - .register(at_state) -} - #[no_mangle] pub extern "C" fn wgpu_device_create_render_pipeline( device_id: DeviceId, @@ -464,11 +421,78 @@ pub extern "C" fn wgpu_device_create_render_pipeline( }; let device_guard = HUB.devices.lock(); - let device = &device_guard.get(device_id).raw; + let device = device_guard.get(device_id); let pipeline_layout_guard = HUB.pipeline_layouts.lock(); let layout = &pipeline_layout_guard.get(desc.layout).raw; let pipeline_stages = unsafe { slice::from_raw_parts(desc.stages, desc.stages_length) }; let shader_module_guard = HUB.shader_modules.lock(); + + let rp_key = { + let op_keep = hal::pass::AttachmentOps { + load: hal::pass::AttachmentLoadOp::Load, + store: hal::pass::AttachmentStoreOp::Store, + }; + let color_attachments = unsafe { + slice::from_raw_parts( + desc.attachments_state.color_attachments, + desc.attachments_state.color_attachments_length, + ) + }; + let depth_stencil_attachment = unsafe { + desc.attachments_state.depth_stencil_attachment.as_ref() + }; + let color_keys = color_attachments.iter().map(|at| hal::pass::Attachment { + format: Some(conv::map_texture_format(at.format)), + samples: at.samples as u8, + ops: op_keep, + stencil_ops: hal::pass::AttachmentOps::DONT_CARE, + layouts: hal::image::Layout::General .. hal::image::Layout::General, + }); + let depth_stencil_key = depth_stencil_attachment.map(|at| hal::pass::Attachment { + format: Some(conv::map_texture_format(at.format)), + samples: at.samples as u8, + ops: op_keep, + stencil_ops: op_keep, + layouts: hal::image::Layout::General .. hal::image::Layout::General, + }); + RenderPassKey { + attachments: color_keys.chain(depth_stencil_key).collect(), + } + }; + + let mut render_pass_cache = device.render_passes.lock().unwrap(); + let main_pass = match render_pass_cache.entry(rp_key) { + Entry::Occupied(e) => e.into_mut(), + Entry::Vacant(e) => { + let color_ids = [ + (0, hal::image::Layout::ColorAttachmentOptimal), + (1, hal::image::Layout::ColorAttachmentOptimal), + (2, hal::image::Layout::ColorAttachmentOptimal), + (3, hal::image::Layout::ColorAttachmentOptimal), + ]; + let depth_id = (desc.attachments_state.color_attachments_length, hal::image::Layout::DepthStencilAttachmentOptimal); + + let subpass = hal::pass::SubpassDesc { + colors: &color_ids[.. desc.attachments_state.color_attachments_length], + depth_stencil: if desc.attachments_state.depth_stencil_attachment.is_null() { + None + } else { + Some(&depth_id) + }, + inputs: &[], + resolves: &[], + preserves: &[], + }; + + let pass = device.raw.create_render_pass( + &e.key().attachments, + &[subpass], + &[], + ); + e.insert(pass) + } + }; + let shaders = { let mut vertex = None; let mut fragment = None; @@ -564,18 +588,13 @@ pub extern "C" fn wgpu_device_create_render_pipeline( depth_bounds: None, }; - let attachment_state_guard = HUB.attachment_states.lock(); - let attachment_state = attachment_state_guard.get(desc.attachment_state); - - // TODO let subpass = hal::pass::Subpass { index: 0, - main_pass: &attachment_state.base_pass, + main_pass, }; // TODO let flags = hal::pso::PipelineCreationFlags::empty(); - // TODO let parent = hal::pso::BasePipeline::None; @@ -596,7 +615,7 @@ pub extern "C" fn wgpu_device_create_render_pipeline( }; // TODO: cache - let pipeline = device + let pipeline = device.raw .create_graphics_pipeline(&pipeline_desc, None) .unwrap(); diff --git a/wgpu-native/src/lib.rs b/wgpu-native/src/lib.rs index e8a9996276..924d7460ee 100644 --- a/wgpu-native/src/lib.rs +++ b/wgpu-native/src/lib.rs @@ -123,8 +123,6 @@ type DepthStencilStateHandle = DepthStencilState; pub type InputStateId = Id; pub type ShaderModuleId = Id; type ShaderModuleHandle = ShaderModule; -pub type AttachmentStateId = Id; -type AttachmentStateHandle = AttachmentState; pub type RenderPipelineId = Id; type RenderPipelineHandle = RenderPipeline; pub type ComputePipelineId = Id; diff --git a/wgpu-native/src/pipeline.rs b/wgpu-native/src/pipeline.rs index b0e4800b10..9eebd0eb7a 100644 --- a/wgpu-native/src/pipeline.rs +++ b/wgpu-native/src/pipeline.rs @@ -2,7 +2,7 @@ use hal; use resource; use { - AttachmentStateId, BlendStateId, ByteArray, DepthStencilStateId, PipelineLayoutId, + BlendStateId, ByteArray, DepthStencilStateId, PipelineLayoutId, ShaderModuleId, }; @@ -194,18 +194,6 @@ pub struct ShaderModuleDescriptor { pub code: ByteArray, } -#[repr(C)] -pub struct AttachmentStateDescriptor { - pub formats: *const resource::TextureFormat, - pub formats_length: usize, -} - -pub(crate) struct AttachmentState { - pub base_pass: B::RenderPass, - pub color_formats: Vec, - pub depth_stencil_format: Option, -} - #[repr(C)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum ShaderStage { @@ -241,16 +229,29 @@ pub enum PrimitiveTopology { TriangleStrip = 4, } +#[repr(C)] +pub struct Attachment { + pub format: resource::TextureFormat, + pub samples: u32, +} + +#[repr(C)] +pub struct AttachmentsState { + pub color_attachments: *const Attachment, + pub color_attachments_length: usize, + pub depth_stencil_attachment: *const Attachment, +} + #[repr(C)] pub struct RenderPipelineDescriptor { pub layout: PipelineLayoutId, pub stages: *const PipelineStageDescriptor, pub stages_length: usize, pub primitive_topology: PrimitiveTopology, + pub attachments_state: AttachmentsState, pub blend_states: *const BlendStateId, pub blend_states_length: usize, pub depth_stencil_state: DepthStencilStateId, - pub attachment_state: AttachmentStateId, } pub(crate) struct RenderPipeline { diff --git a/wgpu-native/src/registry/mod.rs b/wgpu-native/src/registry/mod.rs index 5c5344efe8..1ddd7f791e 100644 --- a/wgpu-native/src/registry/mod.rs +++ b/wgpu-native/src/registry/mod.rs @@ -9,7 +9,7 @@ pub use self::local::{Id, ItemsGuard, Registry as ConcreteRegistry}; pub use self::remote::{Id, ItemsGuard, Registry as ConcreteRegistry}; use { - AdapterHandle, AttachmentStateHandle, BindGroupLayoutHandle, BindGroupHandle, + AdapterHandle, BindGroupLayoutHandle, BindGroupHandle, BlendStateHandle, CommandBufferHandle, DepthStencilStateHandle, DeviceHandle, InstanceHandle, RenderPassHandle, ComputePassHandle, PipelineLayoutHandle, RenderPipelineHandle, ComputePipelineHandle, ShaderModuleHandle, @@ -39,7 +39,6 @@ pub struct Hub { pub(crate) pipeline_layouts: ConcreteRegistry, pub(crate) bind_group_layouts: ConcreteRegistry, pub(crate) bind_groups: ConcreteRegistry, - pub(crate) attachment_states: ConcreteRegistry, pub(crate) blend_states: ConcreteRegistry, pub(crate) depth_stencil_states: ConcreteRegistry, pub(crate) shader_modules: ConcreteRegistry, diff --git a/wgpu-rs/src/lib.rs b/wgpu-rs/src/lib.rs index ad7e11f608..d25a08a5d4 100644 --- a/wgpu-rs/src/lib.rs +++ b/wgpu-rs/src/lib.rs @@ -4,6 +4,7 @@ extern crate arrayvec; use arrayvec::ArrayVec; use std::ffi::CString; +use std::ptr; pub use wgn::{ AdapterDescriptor, Color, CommandBufferDescriptor, DeviceDescriptor, Extensions, Extent3d, @@ -12,7 +13,7 @@ pub use wgn::{ TextureUsageFlags, TextureViewDescriptor, PrimitiveTopology, BlendStateDescriptor, ColorWriteFlags, DepthStencilStateDescriptor, RenderPassDescriptor, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, - LoadOp, StoreOp, + Attachment, LoadOp, StoreOp, ShaderStageFlags_NONE, ShaderStageFlags_VERTEX, ShaderStageFlags_FRAGMENT, ShaderStageFlags_COMPUTE }; @@ -61,10 +62,6 @@ pub struct DepthStencilState { id: wgn::DepthStencilStateId, } -pub struct AttachmentState { - id: wgn::AttachmentStateId, -} - pub struct RenderPipeline { id: wgn::RenderPipelineId, } @@ -105,17 +102,18 @@ pub struct PipelineStageDescriptor<'a> { pub entry_point: &'a str, } -pub struct AttachmentStateDescriptor<'a> { - pub formats: &'a [TextureFormat], +pub struct AttachmentsState<'a> { + pub color_attachments: &'a [Attachment], + pub depth_stencil_attachment: Option, } pub struct RenderPipelineDescriptor<'a> { pub layout: &'a PipelineLayout, pub stages: &'a [PipelineStageDescriptor<'a>], pub primitive_topology: PrimitiveTopology, + pub attachments_state: AttachmentsState<'a>, pub blend_states: &'a [&'a BlendState], pub depth_stencil_state: &'a DepthStencilState, - pub attachment_state: &'a AttachmentState, } @@ -201,15 +199,6 @@ impl Device { } } - pub fn create_attachment_state(&self, desc: &AttachmentStateDescriptor) -> AttachmentState { - AttachmentState { - id: wgn::wgpu_device_create_attachment_state(self.id, &wgn::AttachmentStateDescriptor { - formats: desc.formats.as_ptr(), - formats_length: desc.formats.len(), - }), - } - } - pub fn create_render_pipeline(&self, desc: &RenderPipelineDescriptor) -> RenderPipeline { let entry_points = desc.stages .iter() @@ -236,10 +225,14 @@ impl Device { stages: stages.as_ptr(), stages_length: stages.len(), primitive_topology: desc.primitive_topology, + attachments_state: wgn::AttachmentsState { + color_attachments: desc.attachments_state.color_attachments.as_ptr(), + color_attachments_length: desc.attachments_state.color_attachments.len(), + depth_stencil_attachment: desc.attachments_state.depth_stencil_attachment.as_ref().map(|at| at as *const _).unwrap_or(ptr::null()), + }, blend_states: temp_blend_states.as_ptr(), blend_states_length: temp_blend_states.len(), depth_stencil_state: desc.depth_stencil_state.id, - attachment_state: desc.attachment_state.id, }), } }