Cache render passes on Device level

This commit is contained in:
Dzmitry Malyshau 2018-10-30 16:37:36 -04:00
parent f3cfd2e09c
commit fee276afa5
6 changed files with 117 additions and 102 deletions

View File

@ -37,9 +37,6 @@ fn main() {
let blend_state0 = device.create_blend_state(&wgpu::BlendStateDescriptor::REPLACE); let blend_state0 = device.create_blend_state(&wgpu::BlendStateDescriptor::REPLACE);
let depth_stencil_state = device.create_depth_stencil_state(&wgpu::DepthStencilStateDescriptor::IGNORE); 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 { let _render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
layout: &pipeline_layout, layout: &pipeline_layout,
@ -56,11 +53,19 @@ fn main() {
}, },
], ],
primitive_topology: wgpu::PrimitiveTopology::TriangleList, 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_states: &[
&blend_state0, &blend_state0,
], ],
depth_stencil_state: &depth_stencil_state, depth_stencil_state: &depth_stencil_state,
attachment_state: &attachment_state,
}); });
let mut cmd_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor {}); let mut cmd_buf = device.create_command_buffer(&wgpu::CommandBufferDescriptor {});

View File

@ -3,7 +3,7 @@ use registry::{HUB, Items, Registry};
use track::{BufferTracker, TextureTracker}; use track::{BufferTracker, TextureTracker};
use { use {
CommandBuffer, Stored, TextureUsageFlags, CommandBuffer, Stored, TextureUsageFlags,
AttachmentStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId, BindGroupLayoutId, BlendStateId, CommandBufferId, DepthStencilStateId,
DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId, DeviceId, PipelineLayoutId, QueueId, RenderPipelineId, ShaderModuleId,
TextureId, TextureViewId, TextureId, TextureViewId,
}; };
@ -14,9 +14,17 @@ use hal::{self, Device as _Device};
use rendy_memory::{allocator, Config, Heaps}; use rendy_memory::{allocator, Config, Heaps};
use std::{ffi, slice}; use std::{ffi, slice};
use std::collections::hash_map::{Entry, HashMap};
use std::sync::Mutex; use std::sync::Mutex;
#[derive(Hash, PartialEq)]
pub(crate) struct RenderPassKey {
pub attachments: Vec<hal::pass::Attachment>,
}
impl Eq for RenderPassKey {}
pub struct Device<B: hal::Backend> { pub struct Device<B: hal::Backend> {
pub(crate) raw: B::Device, pub(crate) raw: B::Device,
queue_group: hal::QueueGroup<B, hal::General>, queue_group: hal::QueueGroup<B, hal::General>,
@ -25,6 +33,7 @@ pub struct Device<B: hal::Backend> {
buffer_tracker: Mutex<BufferTracker>, buffer_tracker: Mutex<BufferTracker>,
texture_tracker: Mutex<TextureTracker>, texture_tracker: Mutex<TextureTracker>,
mem_props: hal::MemoryProperties, mem_props: hal::MemoryProperties,
render_passes: Mutex<HashMap<RenderPassKey, B::RenderPass>>,
} }
impl<B: hal::Backend> Device<B> { impl<B: hal::Backend> Device<B> {
@ -62,6 +71,7 @@ impl<B: hal::Backend> Device<B> {
buffer_tracker: Mutex::new(BufferTracker::new()), buffer_tracker: Mutex::new(BufferTracker::new()),
texture_tracker: Mutex::new(TextureTracker::new()), texture_tracker: Mutex::new(TextureTracker::new()),
mem_props, 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] #[no_mangle]
pub extern "C" fn wgpu_device_create_render_pipeline( pub extern "C" fn wgpu_device_create_render_pipeline(
device_id: DeviceId, device_id: DeviceId,
@ -464,11 +421,78 @@ pub extern "C" fn wgpu_device_create_render_pipeline(
}; };
let device_guard = HUB.devices.lock(); 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 pipeline_layout_guard = HUB.pipeline_layouts.lock();
let layout = &pipeline_layout_guard.get(desc.layout).raw; let layout = &pipeline_layout_guard.get(desc.layout).raw;
let pipeline_stages = unsafe { slice::from_raw_parts(desc.stages, desc.stages_length) }; let pipeline_stages = unsafe { slice::from_raw_parts(desc.stages, desc.stages_length) };
let shader_module_guard = HUB.shader_modules.lock(); 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 shaders = {
let mut vertex = None; let mut vertex = None;
let mut fragment = None; let mut fragment = None;
@ -564,18 +588,13 @@ pub extern "C" fn wgpu_device_create_render_pipeline(
depth_bounds: None, 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 { let subpass = hal::pass::Subpass {
index: 0, index: 0,
main_pass: &attachment_state.base_pass, main_pass,
}; };
// TODO // TODO
let flags = hal::pso::PipelineCreationFlags::empty(); let flags = hal::pso::PipelineCreationFlags::empty();
// TODO // TODO
let parent = hal::pso::BasePipeline::None; let parent = hal::pso::BasePipeline::None;
@ -596,7 +615,7 @@ pub extern "C" fn wgpu_device_create_render_pipeline(
}; };
// TODO: cache // TODO: cache
let pipeline = device let pipeline = device.raw
.create_graphics_pipeline(&pipeline_desc, None) .create_graphics_pipeline(&pipeline_desc, None)
.unwrap(); .unwrap();

View File

@ -123,8 +123,6 @@ type DepthStencilStateHandle = DepthStencilState;
pub type InputStateId = Id; pub type InputStateId = Id;
pub type ShaderModuleId = Id; pub type ShaderModuleId = Id;
type ShaderModuleHandle = ShaderModule<B>; type ShaderModuleHandle = ShaderModule<B>;
pub type AttachmentStateId = Id;
type AttachmentStateHandle = AttachmentState<B>;
pub type RenderPipelineId = Id; pub type RenderPipelineId = Id;
type RenderPipelineHandle = RenderPipeline<B>; type RenderPipelineHandle = RenderPipeline<B>;
pub type ComputePipelineId = Id; pub type ComputePipelineId = Id;

View File

@ -2,7 +2,7 @@ use hal;
use resource; use resource;
use { use {
AttachmentStateId, BlendStateId, ByteArray, DepthStencilStateId, PipelineLayoutId, BlendStateId, ByteArray, DepthStencilStateId, PipelineLayoutId,
ShaderModuleId, ShaderModuleId,
}; };
@ -194,18 +194,6 @@ pub struct ShaderModuleDescriptor {
pub code: ByteArray, pub code: ByteArray,
} }
#[repr(C)]
pub struct AttachmentStateDescriptor {
pub formats: *const resource::TextureFormat,
pub formats_length: usize,
}
pub(crate) struct AttachmentState<B: hal::Backend> {
pub base_pass: B::RenderPass,
pub color_formats: Vec<hal::format::Format>,
pub depth_stencil_format: Option<hal::format::Format>,
}
#[repr(C)] #[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum ShaderStage { pub enum ShaderStage {
@ -241,16 +229,29 @@ pub enum PrimitiveTopology {
TriangleStrip = 4, 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)] #[repr(C)]
pub struct RenderPipelineDescriptor { pub struct RenderPipelineDescriptor {
pub layout: PipelineLayoutId, pub layout: PipelineLayoutId,
pub stages: *const PipelineStageDescriptor, pub stages: *const PipelineStageDescriptor,
pub stages_length: usize, pub stages_length: usize,
pub primitive_topology: PrimitiveTopology, pub primitive_topology: PrimitiveTopology,
pub attachments_state: AttachmentsState,
pub blend_states: *const BlendStateId, pub blend_states: *const BlendStateId,
pub blend_states_length: usize, pub blend_states_length: usize,
pub depth_stencil_state: DepthStencilStateId, pub depth_stencil_state: DepthStencilStateId,
pub attachment_state: AttachmentStateId,
} }
pub(crate) struct RenderPipeline<B: hal::Backend> { pub(crate) struct RenderPipeline<B: hal::Backend> {

View File

@ -9,7 +9,7 @@ pub use self::local::{Id, ItemsGuard, Registry as ConcreteRegistry};
pub use self::remote::{Id, ItemsGuard, Registry as ConcreteRegistry}; pub use self::remote::{Id, ItemsGuard, Registry as ConcreteRegistry};
use { use {
AdapterHandle, AttachmentStateHandle, BindGroupLayoutHandle, BindGroupHandle, AdapterHandle, BindGroupLayoutHandle, BindGroupHandle,
BlendStateHandle, CommandBufferHandle, DepthStencilStateHandle, DeviceHandle, InstanceHandle, BlendStateHandle, CommandBufferHandle, DepthStencilStateHandle, DeviceHandle, InstanceHandle,
RenderPassHandle, ComputePassHandle, RenderPassHandle, ComputePassHandle,
PipelineLayoutHandle, RenderPipelineHandle, ComputePipelineHandle, ShaderModuleHandle, PipelineLayoutHandle, RenderPipelineHandle, ComputePipelineHandle, ShaderModuleHandle,
@ -39,7 +39,6 @@ pub struct Hub {
pub(crate) pipeline_layouts: ConcreteRegistry<PipelineLayoutHandle>, pub(crate) pipeline_layouts: ConcreteRegistry<PipelineLayoutHandle>,
pub(crate) bind_group_layouts: ConcreteRegistry<BindGroupLayoutHandle>, pub(crate) bind_group_layouts: ConcreteRegistry<BindGroupLayoutHandle>,
pub(crate) bind_groups: ConcreteRegistry<BindGroupHandle>, pub(crate) bind_groups: ConcreteRegistry<BindGroupHandle>,
pub(crate) attachment_states: ConcreteRegistry<AttachmentStateHandle>,
pub(crate) blend_states: ConcreteRegistry<BlendStateHandle>, pub(crate) blend_states: ConcreteRegistry<BlendStateHandle>,
pub(crate) depth_stencil_states: ConcreteRegistry<DepthStencilStateHandle>, pub(crate) depth_stencil_states: ConcreteRegistry<DepthStencilStateHandle>,
pub(crate) shader_modules: ConcreteRegistry<ShaderModuleHandle>, pub(crate) shader_modules: ConcreteRegistry<ShaderModuleHandle>,

View File

@ -4,6 +4,7 @@ extern crate arrayvec;
use arrayvec::ArrayVec; use arrayvec::ArrayVec;
use std::ffi::CString; use std::ffi::CString;
use std::ptr;
pub use wgn::{ pub use wgn::{
AdapterDescriptor, Color, CommandBufferDescriptor, DeviceDescriptor, Extensions, Extent3d, AdapterDescriptor, Color, CommandBufferDescriptor, DeviceDescriptor, Extensions, Extent3d,
@ -12,7 +13,7 @@ pub use wgn::{
TextureUsageFlags, TextureViewDescriptor, TextureUsageFlags, TextureViewDescriptor,
PrimitiveTopology, BlendStateDescriptor, ColorWriteFlags, DepthStencilStateDescriptor, PrimitiveTopology, BlendStateDescriptor, ColorWriteFlags, DepthStencilStateDescriptor,
RenderPassDescriptor, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, RenderPassDescriptor, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor,
LoadOp, StoreOp, Attachment, LoadOp, StoreOp,
ShaderStageFlags_NONE, ShaderStageFlags_VERTEX, ShaderStageFlags_FRAGMENT, ShaderStageFlags_COMPUTE ShaderStageFlags_NONE, ShaderStageFlags_VERTEX, ShaderStageFlags_FRAGMENT, ShaderStageFlags_COMPUTE
}; };
@ -61,10 +62,6 @@ pub struct DepthStencilState {
id: wgn::DepthStencilStateId, id: wgn::DepthStencilStateId,
} }
pub struct AttachmentState {
id: wgn::AttachmentStateId,
}
pub struct RenderPipeline { pub struct RenderPipeline {
id: wgn::RenderPipelineId, id: wgn::RenderPipelineId,
} }
@ -105,17 +102,18 @@ pub struct PipelineStageDescriptor<'a> {
pub entry_point: &'a str, pub entry_point: &'a str,
} }
pub struct AttachmentStateDescriptor<'a> { pub struct AttachmentsState<'a> {
pub formats: &'a [TextureFormat], pub color_attachments: &'a [Attachment],
pub depth_stencil_attachment: Option<Attachment>,
} }
pub struct RenderPipelineDescriptor<'a> { pub struct RenderPipelineDescriptor<'a> {
pub layout: &'a PipelineLayout, pub layout: &'a PipelineLayout,
pub stages: &'a [PipelineStageDescriptor<'a>], pub stages: &'a [PipelineStageDescriptor<'a>],
pub primitive_topology: PrimitiveTopology, pub primitive_topology: PrimitiveTopology,
pub attachments_state: AttachmentsState<'a>,
pub blend_states: &'a [&'a BlendState], pub blend_states: &'a [&'a BlendState],
pub depth_stencil_state: &'a DepthStencilState, 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 { pub fn create_render_pipeline(&self, desc: &RenderPipelineDescriptor) -> RenderPipeline {
let entry_points = desc.stages let entry_points = desc.stages
.iter() .iter()
@ -236,10 +225,14 @@ impl Device {
stages: stages.as_ptr(), stages: stages.as_ptr(),
stages_length: stages.len(), stages_length: stages.len(),
primitive_topology: desc.primitive_topology, 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: temp_blend_states.as_ptr(),
blend_states_length: temp_blend_states.len(), blend_states_length: temp_blend_states.len(),
depth_stencil_state: desc.depth_stencil_state.id, depth_stencil_state: desc.depth_stencil_state.id,
attachment_state: desc.attachment_state.id,
}), }),
} }
} }