From 0823e5a5714bfb85f7b58b00f2e42c579e45a19b Mon Sep 17 00:00:00 2001 From: Thomas Koehler Date: Wed, 4 Oct 2017 23:56:48 +0200 Subject: [PATCH] [ll][render] encoder.draw draft --- examples/render/quad_render/main.rs | 53 +++----- src/backend/gl/src/native.rs | 3 - src/render/src/allocators/stack.rs | 51 ++++--- src/render/src/device.rs | 35 ++++- src/render/src/encoder.rs | 63 +++------ src/render/src/handle.rs | 10 +- src/render/src/lib.rs | 13 +- src/render/src/macros.rs | 198 +++++++++++++++++++--------- src/render/src/pso/mod.rs | 197 ++++++++++++++++++++------- 9 files changed, 388 insertions(+), 235 deletions(-) diff --git a/examples/render/quad_render/main.rs b/examples/render/quad_render/main.rs index 9103572fddc..54403c4f852 100644 --- a/examples/render/quad_render/main.rs +++ b/examples/render/quad_render/main.rs @@ -7,14 +7,13 @@ extern crate gfx_backend_vulkan as back; extern crate winit; extern crate image; -use std::mem; use std::io::Cursor; use core::{command, device as d, image as i, pso, state}; use core::{Adapter, Device, Instance, Primitive}; use gfx::format::{Srgba8 as ColorFormat}; use core::target::Rect; -use gfx::pso::{Descriptors, GraphicsPipelineMeta}; +use gfx::pso::Descriptors; use gfx::allocators::StackAllocator as Allocator; gfx_buffer_struct! { @@ -34,8 +33,8 @@ const QUAD: [Vertex; 6] = [ Vertex { a_Pos: [ -0.5,-0.33 ], a_Uv: [0.0, 0.0] }, ]; -gfx_descriptor_struct! { - SampleDesc { +gfx_descriptors! { + desc { sampled_image: gfx::pso::SampledImage, sampler: gfx::pso::Sampler, } @@ -43,7 +42,7 @@ gfx_descriptor_struct! { gfx_graphics_pipeline! { pipe { - sample: gfx::pso::DescriptorSet>, // TODO remove + desc: gfx::pso::DescriptorSet>, // TODO: improve color: gfx::pso::RenderTarget, vertices: gfx::pso::VertexBuffer, } @@ -81,9 +80,9 @@ fn main() { let vs_module = device.create_shader_module(include_bytes!("data/vs_main.spv")).unwrap(); let fs_module = device.create_shader_module(include_bytes!("data/ps_main.spv")).unwrap(); - let sample_desc = context.mut_device().create_descriptors(1).pop().unwrap(); + let (desc, mut desc_data) = context.mut_device().create_descriptors(1).pop().unwrap(); let pipe_init = pipe::Init { - sample: &sample_desc, + desc: &desc, color: pso::ColorInfo { mask: state::MASK_ALL, color: Some(state::BlendChannel { @@ -120,7 +119,7 @@ fn main() { }).collect::>(); let framebuffers = frame_rtvs.iter().map(|rtv| { let extent = d::Extent { width: pixel_width as _, height: pixel_height as _, depth: 1 }; - device.create_framebuffer(pipeline.render_pass(), &[rtv.resource()], &[], extent) + context.mut_device().create_framebuffer(&pipeline, &[&rtv], &[], extent) }).collect::>(); let mut upload = Allocator::new( @@ -196,8 +195,8 @@ fn main() { ); context.mut_device().update_descriptor_sets() - .write(sample_desc.sampled_image(), 0, vec![&image_srv]) - .write(sample_desc.sampler(), 0, vec![&sampler]) + .write(desc_data.sampled_image(&desc), 0, &[&image_srv as _]) + .write(desc_data.sampler(&desc), 0, &[&sampler as _]) .finish(); // Rendering setup @@ -259,37 +258,23 @@ fn main() { let mut encoder_pool = context.acquire_encoder_pool(); let mut encoder = encoder_pool.acquire_encoder(); - // Rendering { - let cmd_buffer = encoder.mut_buffer(); - - cmd_buffer.set_viewports(&[viewport]); - cmd_buffer.set_scissors(&[scissor]); - cmd_buffer.bind_graphics_pipeline(pipeline.pipeline()); - // TODO: data instead of upload ? - // TODO: vertex access ? - cmd_buffer.bind_vertex_buffers(pso::VertexBufferSet(vec![(vertex_buffer.resource(), 0)])); - cmd_buffer.bind_graphics_descriptor_sets(pipeline.layout(), 0, &[&sample_desc.set()]); // TODO - - { - let mut encoder = cmd_buffer.begin_renderpass_inline( - pipeline.render_pass(), - &framebuffers[frame.id()], - Rect { x: 0, y: 0, w: pixel_width, h: pixel_height }, - &[command::ClearValue::Color(command::ClearColor::Float([0.8, 0.8, 0.8, 1.0]))], - ); - encoder.draw(0..6, 0..1); - } + let data = pipe::Data { + desc: (&desc, &desc_data), + color: &frame_rtvs[frame.id()], + vertices: &vertex_buffer, + viewports: &[viewport], + scissors: &[scissor], + framebuffer: &framebuffers[frame.id()], + }; + encoder.draw(0..6, &pipeline, data); } submits.push(encoder.finish()); - context.present(mem::replace(&mut submits, Vec::new())); + context.present(submits.drain(..).collect::>()); } println!("cleanup!"); device.destroy_shader_module(vs_module); device.destroy_shader_module(fs_module); - for framebuffer in framebuffers { - device.destroy_framebuffer(framebuffer); - } } diff --git a/src/backend/gl/src/native.rs b/src/backend/gl/src/native.rs index 8d838ee63f8..768ee246ccb 100644 --- a/src/backend/gl/src/native.rs +++ b/src/backend/gl/src/native.rs @@ -88,11 +88,8 @@ pub struct DescriptorSetLayout; #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct DescriptorSet; -<<<<<<< HEAD #[allow(missing_copy_implementations)] #[derive(Debug)] -======= ->>>>>>> 5495511ec01856d486eb3b7cbf2d4c3a9bb49244 pub struct DescriptorPool {} impl core::DescriptorPool for DescriptorPool { diff --git a/src/render/src/allocators/stack.rs b/src/render/src/allocators/stack.rs index 139f633d21b..b8356403572 100644 --- a/src/render/src/allocators/stack.rs +++ b/src/render/src/allocators/stack.rs @@ -1,6 +1,7 @@ use std::sync::mpsc; +use std::collections::HashMap; -use core::{self, Device as CoreDevice}; +use core::{self, MemoryType, Device as CoreDevice}; use core::memory::Requirements; use memory::{self, Allocator, Memory, ReleaseFn, Provider, Dependency}; use {buffer, image}; @@ -11,10 +12,9 @@ pub struct StackAllocator(Provider>); pub struct InnerStackAllocator { device: B::Device, usage: memory::Usage, - // TODO: Any support ? - buffers: ChunkStack, - images: ChunkStack, - targets: ChunkStack, + // stacks by memory type + // TODO: VecMap ? + stacks: HashMap>, chunk_size: u64, } @@ -38,9 +38,7 @@ impl StackAllocator { StackAllocator(Provider::new(InnerStackAllocator { device: (*device.ref_raw()).clone(), usage, - buffers: ChunkStack::new(), - images: ChunkStack::new(), - targets: ChunkStack::new(), + stacks: HashMap::new(), chunk_size, })) } @@ -52,9 +50,9 @@ impl StackAllocator { impl InnerStackAllocator { fn shrink(&mut self) { - self.buffers.shrink(&mut self.device); - self.images.shrink(&mut self.device); - self.targets.shrink(&mut self.device); + for (_, stack) in &mut self.stacks { + stack.shrink(&mut self.device); + } } } @@ -68,9 +66,12 @@ impl Allocator for StackAllocator { let inner: &mut InnerStackAllocator = &mut self.0; let requirements = core::buffer::complete_requirements::( device.mut_raw(), &buffer, usage); - let (memory, offset, release) = inner.buffers.allocate( + let memory_type = device.find_usage_memory(inner.usage, requirements.type_mask) + .expect("could not find suitable memory"); + let mut stack = inner.stacks.entry(memory_type.id) + .or_insert_with(|| ChunkStack::new(memory_type)); + let (memory, offset, release) = stack.allocate( device, - inner.usage, inner.chunk_size, requirements, dependency, @@ -82,20 +83,18 @@ impl Allocator for StackAllocator { fn allocate_image(&mut self, device: &mut Device, - usage: image::Usage, + _: image::Usage, image: B::UnboundImage ) -> (B::Image, Memory) { let dependency = self.0.dependency(); let inner: &mut InnerStackAllocator = &mut self.0; let requirements = device.mut_raw().get_image_requirements(&image); - let stack = if usage.can_target() { - &mut inner.targets - } else { - &mut inner.images - }; + let memory_type = device.find_usage_memory(inner.usage, requirements.type_mask) + .expect("could not find suitable memory"); + let mut stack = inner.stacks.entry(memory_type.id) + .or_insert_with(|| ChunkStack::new(memory_type)); let (memory, offset, release) = stack.allocate( device, - inner.usage, inner.chunk_size, requirements, dependency, @@ -107,6 +106,7 @@ impl Allocator for StackAllocator { } struct ChunkStack { + memory_type: MemoryType, chunks: Vec, allocs: Vec, receiver: mpsc::Receiver, @@ -120,10 +120,11 @@ struct StackAlloc { } impl ChunkStack { - fn new() -> Self { + fn new(memory_type: MemoryType) -> Self { let (sender, receiver) = mpsc::channel(); ChunkStack { + memory_type, chunks: Vec::new(), allocs: Vec::new(), receiver, @@ -133,7 +134,6 @@ impl ChunkStack { fn allocate(&mut self, device: &mut Device, - usage: memory::Usage, chunk_size: u64, req: Requirements, dependency: Dependency>, @@ -161,7 +161,7 @@ impl ChunkStack { }; if chunk_index == self.chunks.len() { - self.grow(device, usage, chunk_size); + self.grow(device, chunk_size); } let alloc_index = self.allocs.len(); @@ -182,13 +182,10 @@ impl ChunkStack { fn grow(&mut self, device: &mut Device, - usage: memory::Usage, chunk_size: u64 ) { - let type_mask = 0xFF; //TODO - let memory_type = device.find_usage_memory(usage, type_mask).unwrap(); let memory = device.mut_raw() - .allocate_memory(&memory_type, chunk_size) + .allocate_memory(&self.memory_type, chunk_size) .unwrap(); self.chunks.push(memory); } diff --git a/src/render/src/device.rs b/src/render/src/device.rs index bbcd4dc4449..303fe2c2f14 100644 --- a/src/render/src/device.rs +++ b/src/render/src/device.rs @@ -10,7 +10,7 @@ use memory::{self, Allocator, Typed}; use handle::{self, GarbageSender}; use handle::inner::*; use {core, buffer, image, format, mapping, pso}; -use {Backend, Primitive}; +use {Backend, Primitive, Extent}; #[derive(Clone)] pub struct Device { @@ -426,20 +426,19 @@ impl Device { } // TODO: smarter allocation - pub fn create_descriptors(&mut self, count: usize) -> Vec + pub fn create_descriptors(&mut self, count: usize) -> Vec<(D, D::Data)> where D: pso::Descriptors { use core::DescriptorPool as CDP; let bindings = &D::layout_bindings()[..]; let layout = self.create_descriptor_set_layout(bindings); - let mut ranges = Vec::new(); - for binding in bindings { - ranges.push(core::pso::DescriptorRangeDesc { + let ranges = bindings.iter().map(|binding| { + core::pso::DescriptorRangeDesc { ty: binding.ty, count: binding.count * count, - }); - } + } + }).collect::>(); let mut pool = self.raw.create_descriptor_pool(count, &ranges[..]); let sets = { @@ -515,6 +514,28 @@ impl Device { { init.create(self, shader_entries, primitive, rasterizer) } + + // TODO?: typed + pub fn create_framebuffer

( + &mut self, + pipeline: &P, + rtvs: &[&handle::raw::RenderTargetView], + dsvs: &[&handle::raw::DepthStencilView], + extent: Extent, + ) -> handle::raw::FrameBuffer + where P: pso::GraphicsPipelineMeta + { + let rtv_res: Vec<_> = rtvs.iter().map(|&rtv| rtv.resource()).collect(); + let dsv_res: Vec<_> = dsvs.iter().map(|&dsv| dsv.resource()).collect(); + let buffer = self.raw.create_framebuffer( + pipeline.render_pass(), &rtv_res[..], &dsv_res[..], extent); + let info = handle::FrameBufferInfo { + rtvs: rtvs.iter().map(|&rtv| rtv.clone()).collect(), + dsvs: dsvs.iter().map(|&dsv| dsv.clone()).collect(), + extent, + }; + FrameBuffer::new(buffer, info, self.garbage.clone()).into() + } /* /// Creates a `ShaderSet` from the supplied vertex and pixel shader source code. fn create_shader_set(&mut self, vs_code: &[u8], ps_code: &[u8]) diff --git a/src/render/src/encoder.rs b/src/render/src/encoder.rs index fba9d308819..32f21d38daf 100644 --- a/src/render/src/encoder.rs +++ b/src/render/src/encoder.rs @@ -10,7 +10,9 @@ use core::command::CommandBuffer; use core::image::ImageLayout; use memory::{Provider, Dependency, cast_slice}; use device::InitToken; -use {handle, buffer, image, format, Backend}; +use {handle, buffer, image, format, pso}; +use {Backend, Supports, Transfer, Graphics}; +use {VertexCount}; pub use core::command::{ BufferCopy, ImageCopy, BufferImageCopy, @@ -183,7 +185,7 @@ impl<'a, B: Backend, C> Encoder<'a, B, C> { } impl<'a, B: Backend, C> Encoder<'a, B, C> - where C: core::queue::Supports + where C: Supports { pub fn finish(mut self) -> Submit { self.transition_to_stable_state(); @@ -270,7 +272,6 @@ impl<'a, B: Backend, C> Encoder<'a, B, C> Some(core::memory::Barrier::Buffer { states: state..next, target: buffer.resource(), - range: 0..buffer.info().size, }) } else { None @@ -296,6 +297,7 @@ impl<'a, B: Backend, C> Encoder<'a, B, C> } } + #[doc(hidden)] pub fn require_state( &mut self, stage: core::pso::PipelineStage, @@ -539,12 +541,12 @@ impl<'a, B: Backend, C> Encoder<'a, B, C> } impl<'a, B: Backend, C> Encoder<'a, B, C> - where C: core::queue::Supports + core::queue::Supports + where C: Supports + Supports { fn require_clear_state(&mut self, image: &handle::raw::Image) -> ImageLayout { let levels = image.info().kind.get_num_levels(); let layers = image.info().kind.get_num_slices().unwrap_or(1); - let state = (core::image::RENDER_TARGET_CLEAR, ImageLayout::ColorAttachmentOptimal); + let state = (core::image::TRANSFER_WRITE, ImageLayout::TransferDstOptimal); let mut image_states = Vec::new(); for level in 0..levels { for layer in 0..layers { @@ -593,50 +595,19 @@ impl<'a, B: Backend, C> Encoder<'a, B, C> self.buffer.clear_depth_stencil(dsv.resource(), layout, depth_value, stencil_value); } - /* - fn draw_indexed(&mut self, buf: &handle::Buffer, ty: IndexType, - slice: &slice::Slice, base: VertexCount, - instances: Option) { - self.access_info.buffer_read(buf.raw()); - self.command_buffer.bind_index(self.handles.ref_buffer(buf.raw()).clone(), ty); - self.command_buffer.call_draw_indexed(slice.start, slice.end - slice.start, base, instances); - } - - fn draw_slice(&mut self, slice: &slice::Slice, instances: Option) { - match slice.buffer { - slice::IndexBuffer::Auto => self.command_buffer.call_draw( - slice.start + slice.base_vertex, slice.end - slice.start, instances), - slice::IndexBuffer::Index16(ref buf) => - self.draw_indexed(buf, IndexType::U16, slice, slice.base_vertex, instances), - slice::IndexBuffer::Index32(ref buf) => - self.draw_indexed(buf, IndexType::U32, slice, slice.base_vertex, instances), - } - } - - /// Draws a `slice::Slice` using a pipeline state object, and its matching `Data` structure. - pub fn draw>(&mut self, slice: &slice::Slice, - pipeline: &pso::PipelineState, user_data: &D) + pub fn draw( + &mut self, + vertices: Range, + pipeline: &D::Pipeline, + data: D + ) + where D: pso::GraphicsPipelineData { - let (pso, _) = self.handles.ref_pso(pipeline.get_handle()); - //TODO: make `raw_data` a member to this struct, to re-use the heap allocation - self.raw_pso_data.clear(); - user_data.bake_to(&mut self.raw_pso_data, pipeline.get_meta(), &mut self.handles, &mut self.access_info); - self.command_buffer.bind_pixel_targets(self.raw_pso_data.pixel_targets.clone()); - self.command_buffer.bind_pipeline_state(pso.clone()); - self.command_buffer.bind_vertex_buffers(self.raw_pso_data.vertex_buffers.clone()); - self.command_buffer.set_ref_values(self.raw_pso_data.ref_values); - self.command_buffer.set_scissor(self.raw_pso_data.scissor); - self.command_buffer.bind_constant_buffers(&self.raw_pso_data.constant_buffers); - for &(location, value) in &self.raw_pso_data.global_constants { - self.command_buffer.bind_global_constant(location, value); - } - self.command_buffer.bind_unordered_views(&self.raw_pso_data.unordered_views); - //Note: it's important to bind RTV, DSV, and UAV before SRV - self.command_buffer.bind_resource_views(&self.raw_pso_data.resource_views); - self.command_buffer.bind_samplers(&self.raw_pso_data.samplers); - self.draw_slice(slice, slice.instances); + // TODO: instances + data.begin_renderpass(self, pipeline).draw(vertices, 0..1); } +/* /// Generate a mipmap chain for the given resource view. pub fn generate_mipmap(&mut self, view: &handle::ShaderResourceView) { self.generate_mipmap_raw(view.raw()) diff --git a/src/render/src/handle.rs b/src/render/src/handle.rs index c3fba4e733b..ef719714d3a 100644 --- a/src/render/src/handle.rs +++ b/src/render/src/handle.rs @@ -55,6 +55,7 @@ impl InnerGarbageCollector { RenderPass(rp) => dev.destroy_renderpass(rp), PipelineLayout(pl) => dev.destroy_pipeline_layout(pl), GraphicsPipeline(pl) => dev.destroy_graphics_pipeline(pl), + FrameBuffer(fb) => dev.destroy_framebuffer(fb), Buffer(b) => dev.destroy_buffer(b), Image(i) => dev.destroy_image(i), RenderTargetView(rtv) => dev.destroy_render_target_view(rtv), @@ -230,7 +231,7 @@ define_resources! { PipelineLayout: (), GraphicsPipeline: (), // ComputePipeline - // FrameBuffer + FrameBuffer: ::handle::FrameBufferInfo, Buffer: ::buffer::Info, Image: ::image::Info, RenderTargetView: ::handle::raw::Image, @@ -255,6 +256,13 @@ pub type UnorderedAccessView = Typed, T>; pub use self::raw::Sampler; +#[derive(Debug, Clone)] +pub struct FrameBufferInfo { + pub rtvs: Vec>, + pub dsvs: Vec>, + pub extent: ::Extent, +} + #[derive(Debug, Clone)] pub enum ViewSource { Image(raw::Image), diff --git a/src/render/src/lib.rs b/src/render/src/lib.rs index 18cc98101d2..f13d7fe4709 100644 --- a/src/render/src/lib.rs +++ b/src/render/src/lib.rs @@ -107,11 +107,10 @@ pub use draw_state::target::*; // public re-exports pub use core::format; pub use core::{Adapter, Backend, Frame, Primitive}; -/* +pub use core::queue::{Supports, Transfer, Compute, Graphics, General}; pub use core::{VertexCount, InstanceCount}; -pub use core::{ShaderSet, VertexShader, HullShader, DomainShader, GeometryShader, PixelShader}; -pub use core::command::{InstanceParams}; -*/ +pub use core::device::Extent; +// pub use core::{ShaderSet, VertexShader, HullShader, DomainShader, GeometryShader, PixelShader}; pub use encoder::Encoder; pub use device::Device; @@ -167,7 +166,7 @@ impl Queue { } pub struct Context - where C: core::queue::Supports + where C: Supports { surface: B::Surface, device: Device, @@ -296,7 +295,7 @@ impl Context { } impl Context - where C: core::queue::Supports + where C: Supports { fn init(mut surface: B::Surface, adapter: &B::Adapter) -> (Self, Vec>) @@ -450,7 +449,7 @@ impl Context } impl Drop for Context - where C: core::queue::Supports + where C: Supports { fn drop(&mut self) { self.wait_idle(); diff --git a/src/render/src/macros.rs b/src/render/src/macros.rs index f4d56bc4680..1004d72f1be 100644 --- a/src/render/src/macros.rs +++ b/src/render/src/macros.rs @@ -45,59 +45,89 @@ macro_rules! gfx_buffer_struct { } #[macro_export] -macro_rules! gfx_descriptor_struct { +macro_rules! gfx_descriptors { ($name:ident { $( $field:ident: $bind:ty, )* }) => { #[allow(missing_docs)] - #[derive(Debug)] - pub struct $name { - $( $field: usize, )* - layout: $crate::handle::raw::DescriptorSetLayout, - set: $crate::pso::RawDescriptorSet, - } + pub mod $name { + #[allow(unused_imports)] + use super::*; + use $crate::{pso, handle, buffer, image}; + use $crate::core; - impl $crate::pso::Descriptors for $name { - fn from_raw( - layout: $crate::handle::raw::DescriptorSetLayout, - set: $crate::pso::RawDescriptorSet - ) -> Self { - let mut binding = 0; - let mut next_binding = || {let b = binding; binding += 1; b }; - $name { - $( $field: next_binding(), )* - layout, - set - } + pub struct Set { + $( $field: usize, )* + layout: handle::raw::DescriptorSetLayout, + raw: pso::RawDescriptorSet, } - fn layout_bindings() -> Vec<$crate::core::pso::DescriptorSetLayoutBinding> { - let mut bindings = Vec::new(); - $({ - let binding = bindings.len(); - bindings.push($crate::core::pso::DescriptorSetLayoutBinding { - binding, - ty: <$bind as $crate::pso::Bind>::desc_type(), - count: <$bind as $crate::pso::Bind>::desc_count(), - // TODO: specify stage - stage_flags: $crate::core::pso::ShaderStageFlags::all(), - }); - })* - bindings + pub struct Data { + $( $field: [Option<<$bind as pso::Bind>::Handle>; <$bind as pso::BindDesc>::COUNT], )* } - - fn layout(&self) -> &B::DescriptorSetLayout { self.layout.resource() } - fn set(&self) -> &B::DescriptorSet { self.set.resource() } - } - impl $name { - $( - fn $field(&self) -> $crate::pso::DescriptorSetBindRef { - $crate::pso::DescriptorSetBindRef { - set: self.set(), - binding: self.$field, - phantom: ::std::marker::PhantomData, - } + impl pso::Descriptors for Set { + type Data = Data; + + fn from_raw( + layout: handle::raw::DescriptorSetLayout, + raw: pso::RawDescriptorSet + ) -> (Self, Self::Data) { + let mut binding = 0; + let mut next_binding = || {let b = binding; binding += 1; b }; + (Set { + $( $field: next_binding(), )* + layout, + raw + }, Data { + $( $field: [None; <$bind as pso::BindDesc>::COUNT], )* + }) + } + + fn layout_bindings() -> Vec { + let mut bindings = Vec::new(); + $({ + let binding = bindings.len(); + bindings.push(core::pso::DescriptorSetLayoutBinding { + binding, + ty: <$bind as pso::BindDesc>::TYPE, + count: <$bind as pso::BindDesc>::COUNT, + // TODO: specify stage + stage_flags: core::pso::ShaderStageFlags::all(), + }); + })* + bindings + } + + fn layout(&self) -> &B::DescriptorSetLayout { self.layout.resource() } + fn set(&self) -> &B::DescriptorSet { self.raw.resource() } + + fn require_state<'a>( + data: &'a Self::Data, + buffers: &mut Vec<(&'a handle::raw::Buffer, core::buffer::State)>, + images: &mut Vec<(&'a handle::raw::Image, image::Subresource, core::image::State)> + ) { + $( + for handle_opt in &data.$field { + handle_opt.as_ref().map(|h| { + <$bind as pso::Bind>::require_state(h, buffers, images); + }); + } + )* } - )* + } + + impl Data { + $( + pub fn $field<'a, 'b>(&'a mut self, set: &'b Set) + -> pso::DescriptorSetBindRef<'b, 'a, B, $bind> + { + pso::DescriptorSetBindRef { + set: set.raw.resource(), + binding: set.$field, + handles: &mut self.$field, + } + } + )* + } } } } @@ -111,9 +141,13 @@ macro_rules! gfx_graphics_pipeline { pub mod $name { #[allow(unused_imports)] use super::*; - use $crate::{pso, handle, Backend, Device, Encoder, Primitive}; - use $crate::core::pass::{self as cpass, SubpassRef}; - use $crate::core::{pso as cpso, image as cimg}; + use $crate::{pso, handle}; + use $crate::{ + Backend, Supports, Transfer, Graphics, Encoder, + Device, Primitive + }; + use $crate::core::{pass as cpass, pso as cpso}; + use $crate::core::command::RenderPassInlineEncoder; pub struct Meta { layout: handle::raw::PipelineLayout, @@ -126,6 +160,10 @@ macro_rules! gfx_graphics_pipeline { } pub struct Data<'a, B: Backend> { + // TODO: + pub viewports: &'a [$crate::core::Viewport], + pub scissors: &'a [$crate::core::target::Rect], + pub framebuffer: &'a handle::raw::FrameBuffer, $( pub $cmp_name: <$cmp as pso::Component<'a, B>>::Data, )* } @@ -159,16 +197,11 @@ macro_rules! gfx_graphics_pipeline { )* let subpass = cpass::SubpassDesc { color_attachments: &color_attachments[..], + input_attachments: &[], + preserve_attachments: &[], }; - // TODO: - let dependency = cpass::SubpassDependency { - passes: SubpassRef::External..SubpassRef::Pass(0), - stages: cpso::COLOR_ATTACHMENT_OUTPUT..cpso::COLOR_ATTACHMENT_OUTPUT, - accesses: cimg::Access::empty()..(cimg::COLOR_ATTACHMENT_READ | cimg::COLOR_ATTACHMENT_WRITE), - }; - - device.create_renderpass_raw(&attachments[..], &[subpass], &[dependency]) + device.create_renderpass_raw(&attachments[..], &[subpass], &[]) }; let mut pipeline_desc = cpso::GraphicsPipelineDesc::new( @@ -194,19 +227,60 @@ macro_rules! gfx_graphics_pipeline { impl pso::GraphicsPipelineMeta for Meta { fn layout(&self) -> &B::PipelineLayout { self.layout.resource() } fn render_pass(&self) -> &B::RenderPass { self.render_pass.resource() } - fn pipeline(&self) -> &B::GraphicsPipeline { self.pipeline.resource() } } impl<'a, B: Backend> pso::GraphicsPipelineData for Data<'a, B> { type Pipeline = Meta; - fn bind( + fn begin_renderpass<'b, 'c, C>( self, - _viewport: $crate::core::Viewport, - _scissor: $crate::core::target::Rect, - _pipeline: &Self::Pipeline) + encoder: &'b mut Encoder<'c, B, C>, + meta: &'b Self::Pipeline + ) -> RenderPassInlineEncoder<'b, B> + where Self: 'a, 'c: 'b, C: Supports + Supports { - + let mut buffer_states = Vec::new(); + let mut image_states = Vec::new(); + $( + <$cmp as pso::Component<'a, B>>::require_state( + &self.$cmp_name, + &mut buffer_states, + &mut image_states); + )* + encoder.require_state( + cpso::VERTEX_INPUT, + &buffer_states[..], + &image_states[..] + ); + + let cmd_buffer = encoder.mut_buffer(); + cmd_buffer.set_viewports(self.viewports); + cmd_buffer.set_scissors(self.scissors); + cmd_buffer.bind_graphics_pipeline(meta.pipeline.resource()); + let mut vbs = Vec::new(); + $( + vbs.extend(<$cmp as pso::Component<'a, B>>::vertex_buffer(&self.$cmp_name)); + )* + cmd_buffer.bind_vertex_buffers(cpso::VertexBufferSet(vbs)); + let mut descs = Vec::new(); + $( + descs.extend(<$cmp as pso::Component<'a, B>>::descriptor_set(&self.$cmp_name)); + )* + cmd_buffer.bind_graphics_descriptor_sets(meta.layout.resource(), 0, &descs[..]); + // TODO: difference with viewport ? + let extent = self.framebuffer.info().extent; + let render_rect = $crate::core::target::Rect { + x: 0, + y: 0, + w: extent.width as u16, + h: extent.height as u16 + }; + cmd_buffer.begin_renderpass_inline( + meta.render_pass.resource(), + self.framebuffer.resource(), + render_rect, + &[], // TODO + ) } } } diff --git a/src/render/src/pso/mod.rs b/src/render/src/pso/mod.rs index a38cb9166a7..8c9b837b9cb 100644 --- a/src/render/src/pso/mod.rs +++ b/src/render/src/pso/mod.rs @@ -4,10 +4,10 @@ use std::mem; use std::marker::PhantomData; use {core, handle}; -use core::image::ImageLayout; +use core::image::{self, ImageLayout}; use core::pass::{AttachmentOps, AttachmentLoadOp, AttachmentStoreOp}; use format::{self, Format}; -use {Backend, Device, Primitive}; +use {Backend, Device, Primitive, Supports, Transfer, Graphics, Encoder}; pub use core::pso::{Rasterizer, CreationError, InstanceRate}; @@ -21,64 +21,74 @@ impl RawDescriptorSet { pub fn resource(&self) -> &B::DescriptorSet { &self.resource } } -pub trait Descriptors { - fn from_raw(handle::raw::DescriptorSetLayout, RawDescriptorSet) -> Self; +pub trait Descriptors: Sized { + type Data: Sized; + + fn from_raw(handle::raw::DescriptorSetLayout, RawDescriptorSet) -> (Self, Self::Data); fn layout_bindings() -> Vec; fn layout(&self) -> &B::DescriptorSetLayout; fn set(&self) -> &B::DescriptorSet; + + fn require_state<'a>( + &'a Self::Data, + &mut Vec<(&'a handle::raw::Buffer, core::buffer::State)>, + &mut Vec<(&'a handle::raw::Image, image::Subresource, core::image::State)> + ); } -pub trait Bind { - fn desc_type() -> core::pso::DescriptorType; - fn desc_count() -> usize; +pub trait BindDesc { + const TYPE: core::pso::DescriptorType; + const COUNT: usize; } -pub trait BindWrite<'a, B: Backend> { - type Input: 'a; - fn write(input: Self::Input) -> core::pso::DescriptorWrite<'a, B>; +pub trait Bind: BindDesc { + type Handle: 'static + Clone; + fn write<'a>(&[&'a Self::Handle]) -> core::pso::DescriptorWrite<'a, B>; + fn require_state<'a>( + &'a Self::Handle, + &mut Vec<(&'a handle::raw::Buffer, core::buffer::State)>, + &mut Vec<(&'a handle::raw::Image, image::Subresource, core::image::State)> + ) {} } macro_rules! define_descriptors { ([$( $array_len:expr ),*] $( $name:ident, )*) => { $( - impl Bind for [T; $array_len] { - fn desc_type() -> core::pso::DescriptorType { - T::desc_type() - } - fn desc_count() -> usize { $array_len * T::desc_count() } + impl BindDesc for [T; $array_len] { + const TYPE: core::pso::DescriptorType = T::TYPE; + const COUNT: usize = $array_len * T::COUNT; } - impl<'a, B, T> BindWrite<'a, B> for [T; $array_len] - where B: Backend, T: BindWrite<'a, B> + impl Bind for [T; $array_len] + where B: Backend, T: Bind { - type Input = T::Input; - fn write(input: Self::Input) -> core::pso::DescriptorWrite<'a, B> { - T::write(input) + type Handle = T::Handle; + fn write<'a>(handles: &[&'a Self::Handle]) -> core::pso::DescriptorWrite<'a, B> { + T::write(handles) } } )* $( pub struct $name; - impl Bind for $name { - fn desc_type() -> core::pso::DescriptorType { - core::pso::DescriptorType::$name - } - fn desc_count() -> usize { 1 } + impl BindDesc for $name { + const TYPE: core::pso::DescriptorType = core::pso::DescriptorType::$name; + const COUNT: usize = 1; } )* } } +// TODO: type-safe formats define_descriptors! { [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ] SampledImage, Sampler, } -impl<'a, B: Backend> BindWrite<'a, B> for SampledImage { - type Input = Vec<&'a handle::raw::ShaderResourceView>; - fn write(srvs: Self::Input) -> core::pso::DescriptorWrite<'a, B> { - core::pso::DescriptorWrite::SampledImage(srvs.into_iter() - .map(|srv| match srv.info() { +impl Bind for SampledImage { + type Handle = handle::raw::ShaderResourceView; + fn write<'a>(srvs: &[&'a Self::Handle]) -> core::pso::DescriptorWrite<'a, B> { + core::pso::DescriptorWrite::SampledImage(srvs.iter() + .map(|&srv| match srv.info() { &handle::ViewSource::Image(_) => { let layout = ImageLayout::ShaderReadOnlyOptimal; (srv.resource(), layout) @@ -86,21 +96,42 @@ impl<'a, B: Backend> BindWrite<'a, B> for SampledImage { &handle::ViewSource::Buffer(_) => unreachable!(), }).collect()) } + fn require_state<'a>( + srv: &'a Self::Handle, + _: &mut Vec<(&'a handle::raw::Buffer, core::buffer::State)>, + images: &mut Vec<(&'a handle::raw::Image, image::Subresource, core::image::State)> + ) { + match srv.info() { + &handle::ViewSource::Image(ref img) => { + let levels = img.info().kind.get_num_levels(); + let layers = img.info().kind.get_num_slices().unwrap_or(1); + let state = (image::SHADER_READ, ImageLayout::ShaderReadOnlyOptimal); + for level in 0..levels { + for layer in 0..layers { + images.push((img, (level, layer), state)); + } + } + } + &handle::ViewSource::Buffer(_) => { + unimplemented!() + } + } + } } -impl<'a, B: Backend> BindWrite<'a, B> for Sampler { - type Input = Vec<&'a handle::raw::Sampler>; - fn write(samplers: Self::Input) -> core::pso::DescriptorWrite<'a, B> { - core::pso::DescriptorWrite::Sampler(samplers.into_iter() - .map(|sampler| sampler.resource()) +impl Bind for Sampler { + type Handle = handle::raw::Sampler; + fn write<'a>(samplers: &[&'a Self::Handle]) -> core::pso::DescriptorWrite<'a, B> { + core::pso::DescriptorWrite::Sampler(samplers.iter() + .map(|&sampler| sampler.resource()) .collect()) } } -pub struct DescriptorSetBindRef<'a, B: Backend, T> { +pub struct DescriptorSetBindRef<'a, 'b, B: Backend, T: Bind> { pub set: &'a B::DescriptorSet, pub binding: usize, - pub phantom: PhantomData, + pub handles: &'b mut [Option], } pub struct DescriptorSetsUpdate<'a, B: Backend> { @@ -113,17 +144,21 @@ impl<'a, B: Backend> DescriptorSetsUpdate<'a, B> { DescriptorSetsUpdate { device, writes: Vec::new() } } - pub fn write>( + pub fn write<'b, T: Bind>( mut self, - bind_ref: DescriptorSetBindRef<'a, B, T>, + bind_ref: DescriptorSetBindRef<'a, 'b, B, T>, array_offset: usize, - write: T::Input + handles: &[&'a T::Handle], ) -> Self { + for (slot, &handle) in bind_ref.handles[array_offset..].iter_mut().zip(handles.iter()) { + *slot = Some(handle.clone()); + } + self.writes.push(core::pso::DescriptorSetWrite { set: bind_ref.set, binding: bind_ref.binding, array_offset, - write: T::write(write) + write: T::write(handles) }); self } @@ -148,17 +183,16 @@ pub trait GraphicsPipelineInit { pub trait GraphicsPipelineMeta { fn layout(&self) -> &B::PipelineLayout; fn render_pass(&self) -> &B::RenderPass; - fn pipeline(&self) -> &B::GraphicsPipeline; } pub trait GraphicsPipelineData { type Pipeline; - fn bind( + fn begin_renderpass<'a, 'b, C>( self, - viewport: core::Viewport, - scissor: core::target::Rect, - pipeline: &Self::Pipeline - ); // TODO + encoder: &'a mut Encoder<'b, B, C>, + pipeline: &'a Self::Pipeline + ) -> core::command::RenderPassInlineEncoder<'a, B> + where Self: 'a, 'b: 'a, C: Supports + Supports; } pub trait Component<'a, B: Backend> { @@ -170,25 +204,59 @@ pub trait Component<'a, B: Backend> { { None } + fn attachment(&Self::Init) -> Option { None } + fn append_desc( Self::Init, &mut core::pso::GraphicsPipelineDesc, ) {} + + fn require_state<'b>( + &'b Self::Data, + &mut Vec<(&'b handle::raw::Buffer, core::buffer::State)>, + &mut Vec<(&'b handle::raw::Image, image::Subresource, core::image::State)> + ) where 'a: 'b {} + + fn vertex_buffer<'b>(&'b Self::Data) -> Option<(&'b B::Buffer, core::pso::BufferOffset)> + where 'a: 'b + { + None + } + + fn descriptor_set<'b>(&'b Self::Data) -> Option<&'b B::DescriptorSet> + where 'a: 'b + { + None + } } pub struct DescriptorSet(PhantomData); impl<'a, B: Backend, D: 'a + Descriptors> Component<'a, B> for DescriptorSet { type Init = &'a D; - type Data = &'a D; + type Data = (&'a D, &'a D::Data); fn descriptor_layout<'b>(init: &'b Self::Init) -> Option<&'b B::DescriptorSetLayout> where 'a: 'b { Some(init.layout()) } + + fn descriptor_set<'b>(data: &'b Self::Data) -> Option<&'b B::DescriptorSet> + where 'a: 'b + { + Some(data.0.set()) + } + + fn require_state<'b>( + data: &'b Self::Data, + buffers: &mut Vec<(&'b handle::raw::Buffer, core::buffer::State)>, + images: &mut Vec<(&'b handle::raw::Image, image::Subresource, core::image::State)> + ) where 'a: 'b { + D::require_state(data.1, buffers, images); + } } pub struct Attachment { @@ -221,6 +289,24 @@ impl<'a, B, F> Component<'a, B> for RenderTarget ) { pipeline_desc.blender.targets.push(init); } + + fn require_state<'b>( + data: &'b Self::Data, + _: &mut Vec<(&'b handle::raw::Buffer, core::buffer::State)>, + images: &mut Vec<(&'b handle::raw::Image, image::Subresource, core::image::State)> + ) where 'a: 'b { + let img = data.info(); + let levels = img.info().kind.get_num_levels(); + let layers = img.info().kind.get_num_slices().unwrap_or(1); + // TODO: READ not always necessary + let state = (image::COLOR_ATTACHMENT_READ | image::COLOR_ATTACHMENT_WRITE, + ImageLayout::ColorAttachmentOptimal); + for level in 0..levels { + for layer in 0..layers { + images.push((img, (level, layer), state)); + } + } + } } pub trait Structure: Sized { @@ -279,6 +365,21 @@ impl<'a, B, T, I> Component<'a, B> for VertexBuffer location += 1; } } + + fn require_state<'b>( + data: &'b Self::Data, + buffers: &mut Vec<(&'b handle::raw::Buffer, core::buffer::State)>, + _: &mut Vec<(&'b handle::raw::Image, image::Subresource, core::image::State)> + ) where 'a: 'b { + buffers.push((data, core::buffer::VERTEX_BUFFER_READ)); + } + + fn vertex_buffer<'b>(data: &'b Self::Data) -> Option<(&'b B::Buffer, core::pso::BufferOffset)> + where 'a: 'b + { + // TODO: offset + Some((data.resource(), 0)) + } } pub type InstanceBuffer = VertexBuffer;