From e314b3ce8484cd15d3f4956b8f2cbbba5124d5a8 Mon Sep 17 00:00:00 2001 From: Hal Gentz Date: Mon, 16 Jul 2018 20:34:15 -0600 Subject: [PATCH 1/2] Adds colour uniform examples, as per popular demand. Signed-off-by: Hal Gentz --- examples/Cargo.toml | 6 + examples/colour-uniform/data/logo.png | Bin 0 -> 24899 bytes examples/colour-uniform/data/quad.frag | 16 + examples/colour-uniform/data/quad.vert | 17 + examples/colour-uniform/main.rs | 1628 ++++++++++++++++++++++++ 5 files changed, 1667 insertions(+) create mode 100644 examples/colour-uniform/data/logo.png create mode 100644 examples/colour-uniform/data/quad.frag create mode 100644 examples/colour-uniform/data/quad.vert create mode 100644 examples/colour-uniform/main.rs diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 84543cc1214..5f456eb2458 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -12,6 +12,10 @@ dx12 = ["gfx-backend-dx12"] vulkan = ["gfx-backend-vulkan"] unstable = [] +[[bin]] +name = "colour-uniform" +path = "colour-uniform/main.rs" + [[bin]] name = "quad" path = "quad/main.rs" @@ -27,6 +31,8 @@ log = "0.4" winit = "0.16" glsl-to-spirv = "0.1.4" gfx-hal = { path = "../src/hal", version = "0.1" } +gfx-backend-empty = { path = "../src/backend/empty", version = "0.1" } +takeable-option = "0.3.0" [dependencies.gfx-backend-gl] path = "../src/backend/gl" diff --git a/examples/colour-uniform/data/logo.png b/examples/colour-uniform/data/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e0cc9047bc3bd743adbdf53d392fcd38d4bdcd7a GIT binary patch literal 24899 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 { + width: T, + height: T, +} + +use std::cell::RefCell; +use std::io::Cursor; +use std::mem::size_of; +use std::rc::Rc; + +use hal::{ + buffer, command, format as f, image as i, memory as m, pass, pool, pso, Adapter, Backbuffer, + Backend, DescriptorPool, Device, FrameSync, Instance, Limits, MemoryType, PhysicalDevice, + Primitive, QueueGroup, Surface, Swapchain, SwapchainConfig, window::Extent2D, +}; + +use hal::format::{AsFormat, ChannelType, Rgba8Srgb as ColorFormat, Swizzle}; +use hal::pass::Subpass; +use hal::pso::{PipelineStage, ShaderStageFlags, Specialization}; +use hal::queue::Submission; +use takeable_option::Takeable; + +use std::fs; +use std::io::Read; + +const ENTRY_NAME: &str = "main"; +const DIMS: Extent2D = Extent2D { width: 1024, height: 768 }; + +#[derive(Debug, Clone, Copy)] +struct Vertex { + a_pos: [f32; 2], + a_uv: [f32; 2], +} + +#[cfg(not(feature = "gl"))] +type WindowType = winit::Window; + +trait SurfaceTrait { + #[cfg(feature = "gl")] + fn get_window_t(&self) -> &back::glutin::GlWindow; +} + +impl SurfaceTrait for ::Surface { + #[cfg(feature = "gl")] + fn get_window_t(&self) -> &back::glutin::GlWindow { + self.get_window() + } +} + +const QUAD: [Vertex; 6] = [ + Vertex { a_pos: [ -0.5, 0.33 ], a_uv: [0.0, 1.0] }, + Vertex { a_pos: [ 0.5, 0.33 ], a_uv: [1.0, 1.0] }, + Vertex { a_pos: [ 0.5,-0.33 ], a_uv: [1.0, 0.0] }, + + Vertex { a_pos: [ -0.5, 0.33 ], a_uv: [0.0, 1.0] }, + Vertex { a_pos: [ 0.5,-0.33 ], a_uv: [1.0, 0.0] }, + Vertex { a_pos: [ -0.5,-0.33 ], a_uv: [0.0, 0.0] }, +]; + +const COLOR_RANGE: i::SubresourceRange = i::SubresourceRange { + aspects: f::Aspects::COLOR, + levels: 0..1, + layers: 0..1, +}; + +struct RendererState +where + B::Surface: SurfaceTrait { + uniform_desc_pool: Takeable, + img_desc_pool: Takeable, + swapchain: Takeable>, + device: Rc>>, + backend: BackendState, + window: WindowState, + vertex_buffer: BufferState, + render_pass: RenderPassState, + uniform: Uniform, + pipeline: PipelineState, + framebuffer: FramebufferState, + viewport: pso::Viewport, + image: ImageState, +} + +#[derive(Debug)] +enum Color { + Red, + Green, + Blue, + Alpha, +} + +impl RendererState +where + B::Surface: SurfaceTrait { + fn new(mut backend: BackendState, window: WindowState) -> Self { + let device = Rc::new(RefCell::new(DeviceState::new( + Takeable::take(&mut backend.adapter.adapter), + &backend.surface, + ))); + + let image_desc = DescSetLayout::new( + Rc::clone(&device), + vec![ + pso::DescriptorSetLayoutBinding { + binding: 0, + ty: pso::DescriptorType::SampledImage, + count: 1, + stage_flags: ShaderStageFlags::FRAGMENT, + immutable_samplers: false, + }, + pso::DescriptorSetLayoutBinding { + binding: 1, + ty: pso::DescriptorType::Sampler, + count: 1, + stage_flags: ShaderStageFlags::FRAGMENT, + immutable_samplers: false, + }, + ], + ); + + let uniform_desc = DescSetLayout::new( + Rc::clone(&device), + vec![pso::DescriptorSetLayoutBinding { + binding: 0, + ty: pso::DescriptorType::UniformBuffer, + count: 1, + stage_flags: ShaderStageFlags::FRAGMENT, + immutable_samplers: false, + }], + ); + + let mut img_desc_pool = Takeable::new(device.borrow().device.create_descriptor_pool( + 1, // # of sets + &[ + pso::DescriptorRangeDesc { + ty: pso::DescriptorType::SampledImage, + count: 1, + }, + pso::DescriptorRangeDesc { + ty: pso::DescriptorType::Sampler, + count: 1, + }, + ], + )); + + let mut uniform_desc_pool = Takeable::new(device.borrow().device.create_descriptor_pool( + 1, // # of sets + &[pso::DescriptorRangeDesc { + ty: pso::DescriptorType::UniformBuffer, + count: 1, + }], + )); + + let image_desc = image_desc.create_desc_set(&mut img_desc_pool); + let uniform_desc = uniform_desc.create_desc_set(&mut uniform_desc_pool); + + println!("Memory types: {:?}", backend.adapter.memory_types); + + const IMAGE_LOGO: &'static [u8] = include_bytes!("data/logo.png"); + let img = image::load(Cursor::new(&IMAGE_LOGO[..]), image::PNG) + .unwrap() + .to_rgba(); + + let mut staging_pool = device.borrow().device.create_command_pool_typed( + &device.borrow().queues, + pool::CommandPoolCreateFlags::empty(), + 16, + ); + + let image = ImageState::new::( + image_desc, + &img, + &backend.adapter, + buffer::Usage::TRANSFER_SRC, + &mut device.borrow_mut(), + &mut staging_pool, + ); + + let vertex_buffer = BufferState::new::( + Rc::clone(&device), + &QUAD, + buffer::Usage::VERTEX, + &backend.adapter.memory_types, + ); + + let uniform = Uniform::new( + Rc::clone(&device), + &backend.adapter.memory_types, + &[1f32, 1.0f32, 1.0f32, 1.0f32], + uniform_desc, + 0, + ); + + image.wait_for_transfer_completion(); + + device + .borrow() + .device + .destroy_command_pool(staging_pool.into_raw()); + + let mut swapchain = Takeable::new(SwapchainState::new( + &mut backend, + Rc::clone(&device), + )); + + let render_pass = RenderPassState::new( + &swapchain, + Rc::clone(&device), + ); + + let framebuffer = FramebufferState::new( + Rc::clone(&device), + &render_pass, + &mut swapchain, + ); + + let pipeline = PipelineState::new( + vec![image.get_layout(), uniform.get_layout()], + &*render_pass.render_pass, + Rc::clone(&device), + ); + + let viewport = RendererState::create_viewport(&swapchain); + + RendererState { + window, + backend, + device, + image, + img_desc_pool, + uniform_desc_pool, + vertex_buffer, + uniform, + render_pass, + pipeline, + swapchain, + framebuffer, + viewport, + } + } + + fn recreate_swapchain(&mut self) { + self.device.borrow().device.wait_idle().unwrap(); + + Takeable::take(&mut self.swapchain); + + self.swapchain = Takeable::new(SwapchainState::new( + &mut self.backend, + Rc::clone(&self.device), + )); + + self.render_pass = RenderPassState::new( + &self.swapchain, + Rc::clone(&self.device), + ); + + self.framebuffer = FramebufferState::new( + Rc::clone(&self.device), + &self.render_pass, + &mut self.swapchain, + ); + + self.pipeline = PipelineState::new( + vec![self.image.get_layout(), self.uniform.get_layout()], + &*self.render_pass.render_pass, + Rc::clone(&self.device), + ); + + self.viewport = RendererState::create_viewport(&self.swapchain); + } + + fn create_viewport(swapchain: &SwapchainState) -> pso::Viewport { + pso::Viewport { + rect: pso::Rect { + x: 0, + y: 0, + w: swapchain.extent.width as i16, + h: swapchain.extent.height as i16, + }, + depth: 0.0..1.0, + } + } + + fn mainloop(&mut self) { + let mut running = true; + let mut recreate_swapchain = false; + + let mut r = 1.0f32; + let mut g = 1.0f32; + let mut b = 1.0f32; + let mut a = 1.0f32; + + let mut cr = 0.8; + let mut cg = 0.8; + let mut cb = 0.8; + + let mut cur_color = Color::Red; + let mut cur_value: u32 = 0; + + println!("\nInstructions:"); + println!("\tChoose whether to change the (R)ed, (G)reen or (B)lue color by pressing the appropriate key."); + println!("\tType in the value you want to change it to, where 0 is nothing, 255 is normal and 510 is double, ect."); + println!("\tThen press C to change the (C)lear colour or (Enter) for the image color."); + println!( + "\tSet {:?} color to: {} (press enter/C to confirm)", + cur_color, cur_value + ); + + while running { + { + let uniform = &mut self.uniform; + #[cfg(feature = "gl")] + let backend = &self.backend; + + self.window.events_loop.poll_events(|event| { + if let winit::Event::WindowEvent { event, .. } = event { + #[allow(unused_variables)] + match event { + winit::WindowEvent::KeyboardInput { + input: + winit::KeyboardInput { + virtual_keycode: Some(winit::VirtualKeyCode::Escape), + .. + }, + .. + } + | winit::WindowEvent::CloseRequested => running = false, + winit::WindowEvent::Resized(dims) => { + #[cfg(feature = "gl")] + backend + .surface + .get_window_t() + .resize( + dims.to_physical( + backend.surface.get_window_t().get_hidpi_factor() + ) + ); + recreate_swapchain = true; + } + winit::WindowEvent::KeyboardInput { + input: + winit::KeyboardInput { + virtual_keycode, + state: winit::ElementState::Pressed, + .. + }, + .. + } => { + if let Some(kc) = virtual_keycode { + match kc { + winit::VirtualKeyCode::Key0 => { + cur_value = cur_value * 10 + 0 + } + winit::VirtualKeyCode::Key1 => { + cur_value = cur_value * 10 + 1 + } + winit::VirtualKeyCode::Key2 => { + cur_value = cur_value * 10 + 2 + } + winit::VirtualKeyCode::Key3 => { + cur_value = cur_value * 10 + 3 + } + winit::VirtualKeyCode::Key4 => { + cur_value = cur_value * 10 + 4 + } + winit::VirtualKeyCode::Key5 => { + cur_value = cur_value * 10 + 5 + } + winit::VirtualKeyCode::Key6 => { + cur_value = cur_value * 10 + 6 + } + winit::VirtualKeyCode::Key7 => { + cur_value = cur_value * 10 + 7 + } + winit::VirtualKeyCode::Key8 => { + cur_value = cur_value * 10 + 8 + } + winit::VirtualKeyCode::Key9 => { + cur_value = cur_value * 10 + 9 + } + winit::VirtualKeyCode::R => { + cur_value = 0; + cur_color = Color::Red + } + winit::VirtualKeyCode::G => { + cur_value = 0; + cur_color = Color::Green + } + winit::VirtualKeyCode::B => { + cur_value = 0; + cur_color = Color::Blue + } + winit::VirtualKeyCode::A => { + cur_value = 0; + cur_color = Color::Alpha + } + winit::VirtualKeyCode::Return => { + match cur_color { + Color::Red => r = cur_value as f32 / 255.0, + Color::Green => g = cur_value as f32 / 255.0, + Color::Blue => b = cur_value as f32 / 255.0, + Color::Alpha => a = cur_value as f32 / 255.0, + } + uniform.buffer.update_data(0, &[r, g, b, a]); + cur_value = 0; + + println!("Colour updated!"); + } + winit::VirtualKeyCode::C => { + match cur_color { + Color::Red => cr = cur_value as f32 / 255.0, + Color::Green => cg = cur_value as f32 / 255.0, + Color::Blue => cb = cur_value as f32 / 255.0, + Color::Alpha => { + error!( + "Alpha is not valid for the background." + ); + return; + } + } + cur_value = 0; + + println!("Background color updated!"); + } + _ => return, + } + println!( + "Set {:?} color to: {} (press enter/C to confirm)", + cur_color, cur_value + ) + } + } + _ => (), + } + } + }); + } + + if recreate_swapchain { + self.recreate_swapchain(); + recreate_swapchain = false; + } + + let sem_index = self.framebuffer.next_acq_pre_pair_index(); + + let frame: hal::SwapImageIndex = { + let (acquire_semaphore, _) = self + .framebuffer + .get_frame_data(None, Some(sem_index)) + .1 + .unwrap(); + match self + .swapchain + .swapchain + .acquire_image(FrameSync::Semaphore(acquire_semaphore)) + { + Ok(i) => i, + Err(_) => { + recreate_swapchain = true; + continue; + } + } + }; + + let (fid, sid) = self + .framebuffer + .get_frame_data(Some(frame as usize), Some(sem_index)); + + let (framebuffer_fence, framebuffer, command_pool) = fid.unwrap(); + let (image_acquired, image_present) = sid.unwrap(); + + self.device + .borrow() + .device + .wait_for_fence(framebuffer_fence, !0); + self.device.borrow().device.reset_fence(framebuffer_fence); + command_pool.reset(); + + // Rendering + let submit = { + let mut cmd_buffer = command_pool.acquire_command_buffer(false); + + cmd_buffer.set_viewports(0, &[self.viewport.clone()]); + cmd_buffer.set_scissors(0, &[self.viewport.rect]); + cmd_buffer.bind_graphics_pipeline(&*self.pipeline.pipeline); + cmd_buffer.bind_vertex_buffers( + 0, + Some((self.vertex_buffer.get_buffer(), 0)), + ); + cmd_buffer.bind_graphics_descriptor_sets( + &*self.pipeline.pipeline_layout, + 0, + vec![&*self.image.desc.set, &*self.uniform.desc.set], + &[], + ); //TODO + + { + let mut encoder = cmd_buffer.begin_render_pass_inline( + &*self.render_pass.render_pass, + framebuffer, + self.viewport.rect, + &[command::ClearValue::Color(command::ClearColor::Float([ + cr, cg, cb, 1.0, + ]))], + ); + encoder.draw(0..6, 0..1); + } + + cmd_buffer.finish() + }; + + let submission = Submission::new() + .wait_on(&[(&*image_acquired, PipelineStage::BOTTOM_OF_PIPE)]) + .signal(&[&*image_present]) + .submit(Some(submit)); + self.device.borrow_mut().queues.queues[0].submit(submission, Some(framebuffer_fence)); + + // present frame + if let Err(_) = self.swapchain.swapchain.present( + &mut self.device.borrow_mut().queues.queues[0], + frame, + Some(&*image_present), + ) { + recreate_swapchain = true; + continue; + } + } + } +} + +impl Drop for RendererState +where + B::Surface: SurfaceTrait { + fn drop(&mut self) { + self.device.borrow().device.wait_idle().unwrap(); + self.device + .borrow() + .device + .destroy_descriptor_pool(Takeable::take(&mut self.img_desc_pool)); + self.device + .borrow() + .device + .destroy_descriptor_pool(Takeable::take(&mut self.uniform_desc_pool)); + Takeable::take(&mut self.swapchain); + } +} + +struct WindowState { + events_loop: winit::EventsLoop, + wb: Takeable, +} + +impl WindowState { + fn new() -> WindowState { + let events_loop = winit::EventsLoop::new(); + + let wb = winit::WindowBuilder::new() + .with_dimensions(winit::dpi::LogicalSize::from_physical(winit::dpi::PhysicalSize { + width: DIMS.width as _, + height: DIMS.height as _, + }, 1.0)) + .with_title("quad".to_string()); + + WindowState { + events_loop, + wb: Takeable::new(wb), + } + } +} + +struct BackendState { + surface: B::Surface, + adapter: AdapterState, + #[cfg(not(feature = "gl"))] + window: WindowType, +} + +#[cfg(any(feature = "vulkan", feature = "dx12", feature = "metal"))] +fn create_backend(window_state: &mut WindowState) -> (BackendState, back::Instance) { + let window = Takeable::take(&mut window_state.wb) + .build(&window_state.events_loop) + .unwrap(); + let instance = back::Instance::create("gfx-rs quad", 1); + let surface = instance.create_surface(&window); + let mut adapters = instance.enumerate_adapters(); + ( + BackendState { + adapter: AdapterState::new(&mut adapters), + surface, + window, + }, + instance, + ) +} + +#[cfg(feature = "gl")] +fn create_backend(window_state: &mut WindowState) -> (BackendState, ()) { + let window = { + let builder = + back::config_context( + back::glutin::ContextBuilder::new(), + ColorFormat::SELF, + None, + ) + .with_vsync(true); + back::glutin::GlWindow::new( + Takeable::take(&mut window_state.wb), + builder, + &window_state.events_loop, + ).unwrap() + }; + + let surface = back::Surface::from_window(window); + let mut adapters = surface.enumerate_adapters(); + ( + BackendState { + adapter: AdapterState::new(&mut adapters), + surface, + }, + (), + ) +} + +struct AdapterState { + adapter: Takeable>, + memory_types: Vec, + limits: Limits, +} + +impl AdapterState { + fn new(adapters: &mut Vec>) -> Self { + print!("Chosen: "); + + for adapter in adapters.iter() { + println!("{:?}", adapter.info); + } + + AdapterState::::new_adapter(adapters.remove(0)) + } + + fn new_adapter(adapter: Adapter) -> Self { + let memory_types = adapter.physical_device.memory_properties().memory_types; + let limits = adapter.physical_device.limits(); + println!("{:?}", limits); + + AdapterState { + adapter: Takeable::new(adapter), + memory_types, + limits, + } + } +} + +struct DeviceState { + device: B::Device, + physical_device: B::PhysicalDevice, + queues: QueueGroup, +} + +impl DeviceState { + fn new(mut adapter: Adapter, surface: &B::Surface) -> Self { + let (device, queues) = adapter + .open_with::<_, ::hal::Graphics>(1, |family| surface.supports_queue_family(family)) + .unwrap(); + + DeviceState { device, queues, physical_device: adapter.physical_device } + } +} + +struct RenderPassState +where + B::Surface: SurfaceTrait { + render_pass: Takeable, + device: Rc>>, +} + +impl RenderPassState +where + B::Surface: SurfaceTrait { + fn new(swapchain: &SwapchainState, device: Rc>>) -> Self { + let render_pass = { + let attachment = pass::Attachment { + format: Some(swapchain.format.clone()), + samples: 1, + ops: pass::AttachmentOps::new( + pass::AttachmentLoadOp::Clear, + pass::AttachmentStoreOp::Store, + ), + stencil_ops: pass::AttachmentOps::DONT_CARE, + layouts: i::Layout::Undefined..i::Layout::Present, + }; + + let subpass = pass::SubpassDesc { + colors: &[(0, i::Layout::ColorAttachmentOptimal)], + depth_stencil: None, + inputs: &[], + resolves: &[], + preserves: &[], + }; + + let dependency = pass::SubpassDependency { + passes: pass::SubpassRef::External..pass::SubpassRef::Pass(0), + stages: PipelineStage::COLOR_ATTACHMENT_OUTPUT + ..PipelineStage::COLOR_ATTACHMENT_OUTPUT, + accesses: i::Access::empty() + ..(i::Access::COLOR_ATTACHMENT_READ | i::Access::COLOR_ATTACHMENT_WRITE), + }; + + device + .borrow() + .device + .create_render_pass(&[attachment], &[subpass], &[dependency]) + }; + + RenderPassState { + render_pass: Takeable::new(render_pass), + device, + } + } +} + +impl Drop for RenderPassState +where + B::Surface: SurfaceTrait { + fn drop(&mut self) { + let device = &self.device.borrow().device; + device.destroy_render_pass(Takeable::take(&mut self.render_pass)); + } +} + +struct BufferState { + memory: Takeable, + buffer: Takeable, + device: Rc>>, + size: u64, +} + +impl BufferState { + fn get_buffer(&self) -> &B::Buffer { + &self.buffer + } + + fn new( + device_ptr: Rc>>, + data_source: &[T], + usage: buffer::Usage, + memory_types: &[MemoryType], + ) -> Self + where + T: Copy, + { + let memory: B::Memory; + let buffer: B::Buffer; + + let stride = size_of::() as u64; + let upload_size = data_source.len() as u64 * stride; + + { + let device = &device_ptr.borrow().device; + + let unbound = device.create_buffer(upload_size, usage).unwrap(); + let mem_req = device.get_buffer_requirements(&unbound); + + let upload_type = memory_types + .iter() + .enumerate() + .position(|(id, mem_type)| { + mem_req.type_mask & (1 << id) != 0 + && mem_type.properties.contains(m::Properties::CPU_VISIBLE) + }) + .unwrap() + .into(); + + memory = device.allocate_memory(upload_type, mem_req.size).unwrap(); + buffer = device.bind_buffer_memory(&memory, 0, unbound).unwrap(); + + // TODO: check transitions: read/write mapping and vertex buffer read + { + let mut data_target = device + .acquire_mapping_writer::(&memory, 0..upload_size) + .unwrap(); + data_target.copy_from_slice(data_source); + device.release_mapping_writer(data_target); + } + } + + BufferState { + memory: Takeable::new(memory), + buffer: Takeable::new(buffer), + device: device_ptr, + size: upload_size, + } + } + + fn update_data(&mut self, offset: u64, data_source: &[T]) + where + T: Copy, + { + let device = &self.device.borrow().device; + + let stride = size_of::() as u64; + let upload_size = data_source.len() as u64 * stride; + + assert!(offset + upload_size <= self.size); + + let mut data_target = device + .acquire_mapping_writer::(&self.memory, offset..offset + upload_size) + .unwrap(); + data_target.copy_from_slice(data_source); + device.release_mapping_writer(data_target); + } + + fn new_texture( + device_ptr: Rc>>, + device: &mut B::Device, + img: &::image::ImageBuffer<::image::Rgba, Vec>, + adapter: &AdapterState, + usage: buffer::Usage, + ) -> (Self, Dimensions, u32, usize) { + let (width, height) = img.dimensions(); + + let row_alignment_mask = adapter.limits.min_buffer_copy_pitch_alignment as u32 - 1; + let stride = 4usize; + + let row_pitch = (width * stride as u32 + row_alignment_mask) & !row_alignment_mask; + let upload_size = (height * row_pitch) as u64; + + let memory: B::Memory; + let buffer: B::Buffer; + + { + let unbound = device.create_buffer(upload_size, usage).unwrap(); + let mem_reqs = device.get_buffer_requirements(&unbound); + + let upload_type = adapter + .memory_types + .iter() + .enumerate() + .position(|(id, mem_type)| { + mem_reqs.type_mask & (1 << id) != 0 + && mem_type.properties.contains(m::Properties::CPU_VISIBLE) + }) + .unwrap() + .into(); + + memory = device.allocate_memory(upload_type, mem_reqs.size).unwrap(); + buffer = device.bind_buffer_memory(&memory, 0, unbound).unwrap(); + + // copy image data into staging buffer + { + let mut data_target = device + .acquire_mapping_writer::(&memory, 0..upload_size) + .unwrap(); + + for y in 0..height as usize { + let data_source_slice = &(**img) + [y * (width as usize) * stride..(y + 1) * (width as usize) * stride]; + let dest_base = y * row_pitch as usize; + + data_target[dest_base..dest_base + data_source_slice.len()] + .copy_from_slice(data_source_slice); + } + + device.release_mapping_writer(data_target); + } + } + + ( + BufferState { + memory: Takeable::new(memory), + buffer: Takeable::new(buffer), + device: device_ptr, + size: upload_size, + }, + Dimensions { width, height }, + row_pitch, + stride, + ) + } +} + +impl Drop for BufferState { + fn drop(&mut self) { + let device = &self.device.borrow().device; + device.destroy_buffer(Takeable::take(&mut self.buffer)); + device.free_memory(Takeable::take(&mut self.memory)); + } +} + +struct Uniform { + buffer: Takeable>, + desc: Takeable>, +} + +impl Uniform { + fn new( + device: Rc>>, + memory_types: &[MemoryType], + data: &[T], + mut desc: DescSet, + binding: u32, + ) -> Self + where + T: Copy, + { + let buffer = BufferState::new( + Rc::clone(&device), + &data, + buffer::Usage::UNIFORM, + memory_types, + ); + let buffer = Takeable::new(buffer); + + desc.write_to_state( + vec![DescSetWrite { + binding, + array_offset: 0, + descriptors: Some(pso::Descriptor::Buffer(buffer.get_buffer(), None..None)), + }], + &mut device.borrow_mut().device, + ); + + Uniform { + buffer, + desc: Takeable::new(desc), + } + } + + fn get_layout(&self) -> &B::DescriptorSetLayout { + self.desc.get_layout() + } +} + +impl Drop for Uniform { + fn drop(&mut self) { + Takeable::take(&mut self.desc); + Takeable::take(&mut self.buffer); + } +} + +struct DescSetLayout { + layout: Takeable, + device: Rc>>, +} + +impl DescSetLayout { + fn new( + device: Rc>>, + bindings: Vec, + ) -> Self { + let desc_set_layout = device + .borrow() + .device + .create_descriptor_set_layout(bindings, &[]); + + DescSetLayout { + layout: Takeable::new(desc_set_layout), + device, + } + } + + fn create_desc_set(self, desc_pool: &mut B::DescriptorPool) -> DescSet { + let desc_set = desc_pool.allocate_set(&*self.layout).unwrap(); + DescSet { + layout: self, + set: Takeable::new(desc_set), + } + } +} + +impl Drop for DescSetLayout { + fn drop(&mut self) { + let device = &self.device.borrow().device; + device.destroy_descriptor_set_layout(Takeable::take(&mut self.layout)); + } +} + +struct DescSet { + set: Takeable, + layout: DescSetLayout, +} + +struct DescSetWrite { + binding: pso::DescriptorBinding, + array_offset: pso::DescriptorArrayIndex, + descriptors: W, +} + +impl DescSet { + fn write_to_state<'a, 'b: 'a, W>( + &'b mut self, + write: Vec>, + device: &mut B::Device, + ) where + W: IntoIterator, + W::Item: std::borrow::Borrow>, + { + let set = &*self.set; + let write: Vec<_> = write + .into_iter() + .map(|d| pso::DescriptorSetWrite { + binding: d.binding, + array_offset: d.array_offset, + descriptors: d.descriptors, + set, + }) + .collect(); + device.write_descriptor_sets(write); + } + + fn get_layout(&self) -> &B::DescriptorSetLayout { + &*self.layout.layout + } +} + +struct ImageState { + desc: DescSet, + buffer: Takeable>, + sampler: Takeable, + image_view: Takeable, + image: Takeable, + memory: Takeable, + transfered_image_fence: Takeable, +} + +impl ImageState { + fn new>( + mut desc: DescSet, + img: &::image::ImageBuffer<::image::Rgba, Vec>, + adapter: &AdapterState, + usage: buffer::Usage, + device_state: &mut DeviceState, + staging_pool: &mut ::hal::CommandPool, + ) -> Self { + let (buffer, dims, row_pitch, stride) = BufferState::new_texture( + Rc::clone(&desc.layout.device), + &mut device_state.device, + img, + adapter, + usage, + ); + + let buffer = Takeable::new(buffer); + let device = &mut device_state.device; + + let kind = i::Kind::D2(dims.width as i::Size, dims.height as i::Size, 1, 1); + let unbound = device + .create_image( + kind, + 1, + ColorFormat::SELF, + i::Tiling::Optimal, + i::Usage::TRANSFER_DST | i::Usage::SAMPLED, + i::StorageFlags::empty(), + ) + .unwrap(); // TODO: usage + let req = device.get_image_requirements(&unbound); + + let device_type = adapter + .memory_types + .iter() + .enumerate() + .position(|(id, memory_type)| { + req.type_mask & (1 << id) != 0 + && memory_type.properties.contains(m::Properties::DEVICE_LOCAL) + }) + .unwrap() + .into(); + + let memory = device.allocate_memory(device_type, req.size).unwrap(); + + let image = device.bind_image_memory(&memory, 0, unbound).unwrap(); + let image_view = device + .create_image_view( + &image, + i::ViewKind::D2, + ColorFormat::SELF, + Swizzle::NO, + COLOR_RANGE.clone(), + ) + .unwrap(); + + let sampler = + device.create_sampler(i::SamplerInfo::new(i::Filter::Linear, i::WrapMode::Clamp)); + + desc.write_to_state( + vec![ + DescSetWrite { + binding: 0, + array_offset: 0, + descriptors: Some(pso::Descriptor::Image(&image_view, i::Layout::Undefined)), + }, + DescSetWrite { + binding: 1, + array_offset: 0, + descriptors: Some(pso::Descriptor::Sampler(&sampler)), + }, + ], + device, + ); + + let mut transfered_image_fence = device.create_fence(false); + + // copy buffer to texture + { + let submit = { + let mut cmd_buffer = staging_pool.acquire_command_buffer(false); + + let image_barrier = m::Barrier::Image { + states: (i::Access::empty(), i::Layout::Undefined) + ..(i::Access::TRANSFER_WRITE, i::Layout::TransferDstOptimal), + target: &image, + range: COLOR_RANGE.clone(), + }; + + cmd_buffer.pipeline_barrier( + PipelineStage::TOP_OF_PIPE..PipelineStage::TRANSFER, + m::Dependencies::empty(), + &[image_barrier], + ); + + cmd_buffer.copy_buffer_to_image( + buffer.get_buffer(), + &image, + i::Layout::TransferDstOptimal, + &[command::BufferImageCopy { + buffer_offset: 0, + buffer_width: row_pitch / (stride as u32), + buffer_height: dims.height as u32, + image_layers: i::SubresourceLayers { + aspects: f::Aspects::COLOR, + level: 0, + layers: 0..1, + }, + image_offset: i::Offset { x: 0, y: 0, z: 0 }, + image_extent: i::Extent { + width: dims.width, + height: dims.height, + depth: 1, + }, + }], + ); + + let image_barrier = m::Barrier::Image { + states: (i::Access::TRANSFER_WRITE, i::Layout::TransferDstOptimal) + ..(i::Access::SHADER_READ, i::Layout::ShaderReadOnlyOptimal), + target: &image, + range: COLOR_RANGE.clone(), + }; + cmd_buffer.pipeline_barrier( + PipelineStage::TRANSFER..PipelineStage::FRAGMENT_SHADER, + m::Dependencies::empty(), + &[image_barrier], + ); + + cmd_buffer.finish() + }; + + let submission = Submission::new().submit(Some(submit)); + device_state.queues.queues[0].submit(submission, Some(&mut transfered_image_fence)); + } + + ImageState { + desc: desc, + buffer: buffer, + sampler: Takeable::new(sampler), + image_view: Takeable::new(image_view), + image: Takeable::new(image), + memory: Takeable::new(memory), + transfered_image_fence: Takeable::new(transfered_image_fence), + } + } + + fn wait_for_transfer_completion(&self) { + let device = &self.desc.layout.device.borrow().device; + device.wait_for_fence(&*self.transfered_image_fence, !0); + } + + fn get_layout(&self) -> &B::DescriptorSetLayout { + self.desc.get_layout() + } +} + +impl Drop for ImageState { + fn drop(&mut self) { + { + let device = &self.desc.layout.device.borrow().device; + + let fence = Takeable::take(&mut self.transfered_image_fence); + device.wait_for_fence(&fence, !0); + device.destroy_fence(fence); + + device.destroy_sampler(Takeable::take(&mut self.sampler)); + device.destroy_image_view(Takeable::take(&mut self.image_view)); + device.destroy_image(Takeable::take(&mut self.image)); + device.free_memory(Takeable::take(&mut self.memory)); + } + + Takeable::take(&mut self.buffer); + } +} + +struct PipelineState { + pipeline: Takeable, + pipeline_layout: Takeable, + device: Rc>>, +} + +impl PipelineState { + fn new( + desc_layouts: IS, + render_pass: &B::RenderPass, + device_ptr: Rc>>, + ) -> Self + where + IS: IntoIterator, + IS::Item: std::borrow::Borrow, + { + let device = &device_ptr.borrow().device; + let pipeline_layout = + device.create_pipeline_layout(desc_layouts, &[(pso::ShaderStageFlags::VERTEX, 0..8)]); + + let pipeline = { + let vs_module = { + let glsl = fs::read_to_string("colour-uniform/data/quad.vert").unwrap(); + let spirv: Vec = glsl_to_spirv::compile(&glsl, glsl_to_spirv::ShaderType::Vertex) + .unwrap() + .bytes() + .map(|b| b.unwrap()) + .collect(); + device.create_shader_module(&spirv).unwrap() + }; + let fs_module = { + let glsl = fs::read_to_string("colour-uniform/data/quad.frag").unwrap(); + let spirv: Vec = glsl_to_spirv::compile(&glsl, glsl_to_spirv::ShaderType::Fragment) + .unwrap() + .bytes() + .map(|b| b.unwrap()) + .collect(); + device.create_shader_module(&spirv).unwrap() + }; + + let pipeline = { + let (vs_entry, fs_entry) = ( + pso::EntryPoint:: { + entry: ENTRY_NAME, + module: &vs_module, + specialization: &[Specialization { + id: 0, + value: pso::Constant::F32(0.8), + }], + }, + pso::EntryPoint:: { + entry: ENTRY_NAME, + module: &fs_module, + specialization: &[], + }, + ); + + let shader_entries = pso::GraphicsShaderSet { + vertex: vs_entry, + hull: None, + domain: None, + geometry: None, + fragment: Some(fs_entry), + }; + + let subpass = Subpass { + index: 0, + main_pass: render_pass, + }; + + let mut pipeline_desc = pso::GraphicsPipelineDesc::new( + shader_entries, + Primitive::TriangleList, + pso::Rasterizer::FILL, + &pipeline_layout, + subpass, + ); + pipeline_desc.blender.targets.push(pso::ColorBlendDesc( + pso::ColorMask::ALL, + pso::BlendState::ALPHA, + )); + pipeline_desc.vertex_buffers.push(pso::VertexBufferDesc { + binding: 0, + stride: size_of::() as u32, + rate: 0, + }); + + pipeline_desc.attributes.push(pso::AttributeDesc { + location: 0, + binding: 0, + element: pso::Element { + format: f::Format::Rg32Float, + offset: 0, + }, + }); + pipeline_desc.attributes.push(pso::AttributeDesc { + location: 1, + binding: 0, + element: pso::Element { + format: f::Format::Rg32Float, + offset: 8, + }, + }); + + device.create_graphics_pipeline(&pipeline_desc) + }; + + device.destroy_shader_module(vs_module); + device.destroy_shader_module(fs_module); + + pipeline.unwrap() + }; + + PipelineState { + pipeline: Takeable::new(pipeline), + pipeline_layout: Takeable::new(pipeline_layout), + device: Rc::clone(&device_ptr), + } + } +} + +impl Drop for PipelineState { + fn drop(&mut self) { + let device = &self.device.borrow().device; + device.destroy_graphics_pipeline(Takeable::take(&mut self.pipeline)); + device.destroy_pipeline_layout(Takeable::take(&mut self.pipeline_layout)); + } +} + +struct SwapchainState +where + B::Surface: SurfaceTrait { + swapchain: Takeable, + backbuffer: Takeable>, + device: Rc>>, + extent: hal::window::Extent2D, + format: f::Format, +} + +impl SwapchainState +where + B::Surface: SurfaceTrait { + fn new( + backend: &mut BackendState, + device: Rc>>, + ) -> Self { + let (caps, formats, _present_modes) = backend.surface.compatibility(&device.borrow().physical_device); + println!("formats: {:?}", formats); + let format = formats + .map_or(f::Format::Rgba8Srgb, |formats| { + formats + .iter() + .find(|format| format.base_format().1 == ChannelType::Srgb) + .map(|format| *format) + .unwrap_or(formats[0]) + }); + + let extent = match caps.current_extent { + Some(e) => e, + None => { + #[cfg(not(feature = "gl"))] + let window = &backend.window; + #[cfg(feature = "gl")] + let window = backend.surface.get_window_t(); + + let window_size = window.get_inner_size().unwrap().to_physical(window.get_hidpi_factor()); + let mut extent = hal::window::Extent2D { width: window_size.width as _, height: window_size.height as _}; + + extent.width = extent.width.max(caps.extents.start.width).min(caps.extents.end.width); + extent.height = extent.height.max(caps.extents.start.height).min(caps.extents.end.height); + + extent + } + }; + + println!("Surface format: {:?}", format); + + let swap_config = SwapchainConfig::new() + .with_color(format) + .with_image_count(caps.image_count.start) + .with_image_usage(i::Usage::COLOR_ATTACHMENT); + let (swapchain, backbuffer) = device.borrow().device.create_swapchain( + &mut backend.surface, + swap_config, + None, + &extent, + ); + + let swapchain = SwapchainState { + swapchain: Takeable::new(swapchain), + backbuffer: Takeable::new(backbuffer), + device, + extent, + format, + }; + swapchain + } +} + +impl Drop for SwapchainState +where + B::Surface: SurfaceTrait { + fn drop(&mut self) { + self.device + .borrow() + .device + .destroy_swapchain(Takeable::take(&mut self.swapchain)); + } +} + +struct FramebufferState +where + B::Surface: SurfaceTrait { + framebuffers: Takeable>, + framebuffer_fences: Takeable>, + command_pools: Takeable>>, + frame_images: Takeable>, + acquire_semaphores: Takeable>, + present_semaphores: Takeable>, + last_ref: usize, + device: Rc>>, +} + +impl FramebufferState +where + B::Surface: SurfaceTrait { + fn new( + device: Rc>>, + render_pass: &RenderPassState, + swapchain: &mut SwapchainState, + ) -> Self { + let (frame_images, framebuffers) = match Takeable::take(&mut swapchain.backbuffer) { + Backbuffer::Images(images) => { + let extent = i::Extent { + width: swapchain.extent.width as _, + height: swapchain.extent.height as _, + depth: 1, + }; + let pairs = images + .into_iter() + .map(|image| { + let rtv = device + .borrow() + .device + .create_image_view( + &image, + i::ViewKind::D2, + swapchain.format, + Swizzle::NO, + COLOR_RANGE.clone(), + ) + .unwrap(); + (image, rtv) + }) + .collect::>(); + let fbos = pairs + .iter() + .map(|&(_, ref rtv)| { + device + .borrow() + .device + .create_framebuffer(&*render_pass.render_pass, Some(rtv), extent) + .unwrap() + }) + .collect(); + (pairs, fbos) + } + Backbuffer::Framebuffer(fbo) => (Vec::new(), vec![fbo]), + }; + + let iter_count = if frame_images.len() != 0 { + frame_images.len() + } else { + 1 // GL can have zero + }; + + let mut fences: Vec = vec![]; + let mut command_pools: Vec> = vec![]; + let mut acquire_semaphores: Vec = vec![]; + let mut present_semaphores: Vec = vec![]; + + for _ in 0..iter_count { + fences.push(device.borrow().device.create_fence(true)); + command_pools.push(device.borrow().device.create_command_pool_typed( + &device.borrow().queues, + pool::CommandPoolCreateFlags::empty(), + 16, + )); + + acquire_semaphores.push(device.borrow().device.create_semaphore()); + present_semaphores.push(device.borrow().device.create_semaphore()); + } + + FramebufferState { + frame_images: Takeable::new(frame_images), + framebuffers: Takeable::new(framebuffers), + framebuffer_fences: Takeable::new(fences), + command_pools: Takeable::new(command_pools), + present_semaphores: Takeable::new(present_semaphores), + acquire_semaphores: Takeable::new(acquire_semaphores), + device, + last_ref: 0, + } + } + + fn next_acq_pre_pair_index(&mut self) -> usize { + if self.last_ref >= self.acquire_semaphores.len() { + self.last_ref = 0 + } + + let ret = self.last_ref; + self.last_ref += 1; + ret + } + + fn get_frame_data( + &mut self, + frame_id: Option, + sem_index: Option, + ) -> ( + Option<( + &mut B::Fence, + &mut B::Framebuffer, + &mut hal::CommandPool, + )>, + Option<(&mut B::Semaphore, &mut B::Semaphore)>, + ) { + ( + if let Some(fid) = frame_id { + Some(( + &mut self.framebuffer_fences[fid], + &mut self.framebuffers[fid], + &mut self.command_pools[fid], + )) + } else { + None + }, + if let Some(sid) = sem_index { + Some(( + &mut self.acquire_semaphores[sid], + &mut self.present_semaphores[sid], + )) + } else { + None + }, + ) + } +} + +impl Drop for FramebufferState +where + B::Surface: SurfaceTrait { + fn drop(&mut self) { + let device = &self.device.borrow().device; + + for fence in Takeable::take(&mut self.framebuffer_fences) { + device.wait_for_fence(&fence, !0); + device.destroy_fence(fence); + } + + for command_pool in Takeable::take(&mut self.command_pools) { + device.destroy_command_pool(command_pool.into_raw()); + } + + for acquire_semaphore in Takeable::take(&mut self.acquire_semaphores) { + device.destroy_semaphore(acquire_semaphore); + } + + for present_semaphore in Takeable::take(&mut self.present_semaphores) { + device.destroy_semaphore(present_semaphore); + } + + for framebuffer in Takeable::take(&mut self.framebuffers) { + device.destroy_framebuffer(framebuffer); + } + + for (_, rtv) in Takeable::take(&mut self.frame_images) { + device.destroy_image_view(rtv); + } + } +} + +#[cfg(any(feature = "vulkan", feature = "dx12", feature = "metal", feature = "gl"))] +fn main() { + env_logger::init(); + + let mut window = WindowState::new(); + let (backend, _instance) = create_backend(&mut window); + + let mut renderer_state = + RendererState::new(backend, window); + renderer_state.mainloop(); +} + +#[cfg(not(any(feature = "vulkan", feature = "dx12", feature = "metal", feature = "gl")))] +fn main() { + println!("You need to enable the native API feature (vulkan/metal) in order to test the LL"); +} From d5d38e6a7386db358d168b6b4734776181e67eee Mon Sep 17 00:00:00 2001 From: Hal Gentz Date: Thu, 19 Jul 2018 20:44:06 -0600 Subject: [PATCH 2/2] Use option over takeable Signed-off-by: Hal Gentz --- examples/Cargo.toml | 1 - examples/colour-uniform/main.rs | 249 ++++++++++++++++---------------- 2 files changed, 122 insertions(+), 128 deletions(-) diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 5f456eb2458..114f3c433fc 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -32,7 +32,6 @@ winit = "0.16" glsl-to-spirv = "0.1.4" gfx-hal = { path = "../src/hal", version = "0.1" } gfx-backend-empty = { path = "../src/backend/empty", version = "0.1" } -takeable-option = "0.3.0" [dependencies.gfx-backend-gl] path = "../src/backend/gl" diff --git a/examples/colour-uniform/main.rs b/examples/colour-uniform/main.rs index 38b5eefe042..dce0b05f8c7 100644 --- a/examples/colour-uniform/main.rs +++ b/examples/colour-uniform/main.rs @@ -23,7 +23,6 @@ extern crate env_logger; extern crate gfx_hal as hal; extern crate glsl_to_spirv; extern crate image; -extern crate takeable_option; extern crate winit; struct Dimensions { @@ -46,7 +45,6 @@ use hal::format::{AsFormat, ChannelType, Rgba8Srgb as ColorFormat, Swizzle}; use hal::pass::Subpass; use hal::pso::{PipelineStage, ShaderStageFlags, Specialization}; use hal::queue::Submission; -use takeable_option::Takeable; use std::fs; use std::io::Read; @@ -94,9 +92,9 @@ const COLOR_RANGE: i::SubresourceRange = i::SubresourceRange { struct RendererState where B::Surface: SurfaceTrait { - uniform_desc_pool: Takeable, - img_desc_pool: Takeable, - swapchain: Takeable>, + uniform_desc_pool: Option, + img_desc_pool: Option, + swapchain: Option>, device: Rc>>, backend: BackendState, window: WindowState, @@ -122,7 +120,7 @@ where B::Surface: SurfaceTrait { fn new(mut backend: BackendState, window: WindowState) -> Self { let device = Rc::new(RefCell::new(DeviceState::new( - Takeable::take(&mut backend.adapter.adapter), + backend.adapter.adapter.take().unwrap(), &backend.surface, ))); @@ -157,7 +155,7 @@ where }], ); - let mut img_desc_pool = Takeable::new(device.borrow().device.create_descriptor_pool( + let mut img_desc_pool = Some(device.borrow().device.create_descriptor_pool( 1, // # of sets &[ pso::DescriptorRangeDesc { @@ -171,7 +169,7 @@ where ], )); - let mut uniform_desc_pool = Takeable::new(device.borrow().device.create_descriptor_pool( + let mut uniform_desc_pool = Some(device.borrow().device.create_descriptor_pool( 1, // # of sets &[pso::DescriptorRangeDesc { ty: pso::DescriptorType::UniformBuffer, @@ -179,8 +177,8 @@ where }], )); - let image_desc = image_desc.create_desc_set(&mut img_desc_pool); - let uniform_desc = uniform_desc.create_desc_set(&mut uniform_desc_pool); + let image_desc = image_desc.create_desc_set(img_desc_pool.as_mut().unwrap()); + let uniform_desc = uniform_desc.create_desc_set(uniform_desc_pool.as_mut().unwrap()); println!("Memory types: {:?}", backend.adapter.memory_types); @@ -226,29 +224,29 @@ where .device .destroy_command_pool(staging_pool.into_raw()); - let mut swapchain = Takeable::new(SwapchainState::new( + let mut swapchain = Some(SwapchainState::new( &mut backend, Rc::clone(&device), )); let render_pass = RenderPassState::new( - &swapchain, + swapchain.as_ref().unwrap(), Rc::clone(&device), ); let framebuffer = FramebufferState::new( Rc::clone(&device), &render_pass, - &mut swapchain, + swapchain.as_mut().unwrap(), ); let pipeline = PipelineState::new( vec![image.get_layout(), uniform.get_layout()], - &*render_pass.render_pass, + render_pass.render_pass.as_ref().unwrap(), Rc::clone(&device), ); - let viewport = RendererState::create_viewport(&swapchain); + let viewport = RendererState::create_viewport(swapchain.as_ref().unwrap()); RendererState { window, @@ -270,31 +268,31 @@ where fn recreate_swapchain(&mut self) { self.device.borrow().device.wait_idle().unwrap(); - Takeable::take(&mut self.swapchain); + self.swapchain.take().unwrap(); - self.swapchain = Takeable::new(SwapchainState::new( + self.swapchain = Some(SwapchainState::new( &mut self.backend, Rc::clone(&self.device), )); self.render_pass = RenderPassState::new( - &self.swapchain, + self.swapchain.as_ref().unwrap(), Rc::clone(&self.device), ); self.framebuffer = FramebufferState::new( Rc::clone(&self.device), &self.render_pass, - &mut self.swapchain, + self.swapchain.as_mut().unwrap(), ); self.pipeline = PipelineState::new( vec![self.image.get_layout(), self.uniform.get_layout()], - &*self.render_pass.render_pass, + self.render_pass.render_pass.as_ref().unwrap(), Rc::clone(&self.device), ); - self.viewport = RendererState::create_viewport(&self.swapchain); + self.viewport = RendererState::create_viewport(self.swapchain.as_ref().unwrap()); } fn create_viewport(swapchain: &SwapchainState) -> pso::Viewport { @@ -429,7 +427,7 @@ where Color::Blue => b = cur_value as f32 / 255.0, Color::Alpha => a = cur_value as f32 / 255.0, } - uniform.buffer.update_data(0, &[r, g, b, a]); + uniform.buffer.as_mut().unwrap().update_data(0, &[r, g, b, a]); cur_value = 0; println!("Colour updated!"); @@ -479,7 +477,11 @@ where .unwrap(); match self .swapchain + .as_mut() + .unwrap() .swapchain + .as_mut() + .unwrap() .acquire_image(FrameSync::Semaphore(acquire_semaphore)) { Ok(i) => i, @@ -510,21 +512,21 @@ where cmd_buffer.set_viewports(0, &[self.viewport.clone()]); cmd_buffer.set_scissors(0, &[self.viewport.rect]); - cmd_buffer.bind_graphics_pipeline(&*self.pipeline.pipeline); + cmd_buffer.bind_graphics_pipeline(self.pipeline.pipeline.as_ref().unwrap()); cmd_buffer.bind_vertex_buffers( 0, Some((self.vertex_buffer.get_buffer(), 0)), ); cmd_buffer.bind_graphics_descriptor_sets( - &*self.pipeline.pipeline_layout, + self.pipeline.pipeline_layout.as_ref().unwrap(), 0, - vec![&*self.image.desc.set, &*self.uniform.desc.set], + vec![self.image.desc.set.as_ref().unwrap(), self.uniform.desc.as_ref().unwrap().set.as_ref().unwrap()], &[], ); //TODO { let mut encoder = cmd_buffer.begin_render_pass_inline( - &*self.render_pass.render_pass, + self.render_pass.render_pass.as_ref().unwrap(), framebuffer, self.viewport.rect, &[command::ClearValue::Color(command::ClearColor::Float([ @@ -544,7 +546,7 @@ where self.device.borrow_mut().queues.queues[0].submit(submission, Some(framebuffer_fence)); // present frame - if let Err(_) = self.swapchain.swapchain.present( + if let Err(_) = self.swapchain.as_ref().unwrap().swapchain.as_ref().unwrap().present( &mut self.device.borrow_mut().queues.queues[0], frame, Some(&*image_present), @@ -564,18 +566,18 @@ where self.device .borrow() .device - .destroy_descriptor_pool(Takeable::take(&mut self.img_desc_pool)); + .destroy_descriptor_pool(self.img_desc_pool.take().unwrap()); self.device .borrow() .device - .destroy_descriptor_pool(Takeable::take(&mut self.uniform_desc_pool)); - Takeable::take(&mut self.swapchain); + .destroy_descriptor_pool(self.uniform_desc_pool.take().unwrap()); + self.swapchain.take(); } } struct WindowState { events_loop: winit::EventsLoop, - wb: Takeable, + wb: Option, } impl WindowState { @@ -591,7 +593,7 @@ impl WindowState { WindowState { events_loop, - wb: Takeable::new(wb), + wb: Some(wb), } } } @@ -605,7 +607,7 @@ struct BackendState { #[cfg(any(feature = "vulkan", feature = "dx12", feature = "metal"))] fn create_backend(window_state: &mut WindowState) -> (BackendState, back::Instance) { - let window = Takeable::take(&mut window_state.wb) + let window = window_state.wb.take().unwrap() .build(&window_state.events_loop) .unwrap(); let instance = back::Instance::create("gfx-rs quad", 1); @@ -632,7 +634,7 @@ fn create_backend(window_state: &mut WindowState) -> (BackendState (BackendState { - adapter: Takeable>, + adapter: Option>, memory_types: Vec, limits: Limits, } @@ -672,7 +674,7 @@ impl AdapterState { println!("{:?}", limits); AdapterState { - adapter: Takeable::new(adapter), + adapter: Some(adapter), memory_types, limits, } @@ -698,7 +700,7 @@ impl DeviceState { struct RenderPassState where B::Surface: SurfaceTrait { - render_pass: Takeable, + render_pass: Option, device: Rc>>, } @@ -741,7 +743,7 @@ where }; RenderPassState { - render_pass: Takeable::new(render_pass), + render_pass: Some(render_pass), device, } } @@ -752,20 +754,20 @@ where B::Surface: SurfaceTrait { fn drop(&mut self) { let device = &self.device.borrow().device; - device.destroy_render_pass(Takeable::take(&mut self.render_pass)); + device.destroy_render_pass(self.render_pass.take().unwrap()); } } struct BufferState { - memory: Takeable, - buffer: Takeable, + memory: Option, + buffer: Option, device: Rc>>, size: u64, } impl BufferState { fn get_buffer(&self) -> &B::Buffer { - &self.buffer + self.buffer.as_ref().unwrap() } fn new( @@ -813,8 +815,8 @@ impl BufferState { } BufferState { - memory: Takeable::new(memory), - buffer: Takeable::new(buffer), + memory: Some(memory), + buffer: Some(buffer), device: device_ptr, size: upload_size, } @@ -832,7 +834,7 @@ impl BufferState { assert!(offset + upload_size <= self.size); let mut data_target = device - .acquire_mapping_writer::(&self.memory, offset..offset + upload_size) + .acquire_mapping_writer::(self.memory.as_ref().unwrap(), offset..offset + upload_size) .unwrap(); data_target.copy_from_slice(data_source); device.release_mapping_writer(data_target); @@ -895,8 +897,8 @@ impl BufferState { ( BufferState { - memory: Takeable::new(memory), - buffer: Takeable::new(buffer), + memory: Some(memory), + buffer: Some(buffer), device: device_ptr, size: upload_size, }, @@ -910,14 +912,14 @@ impl BufferState { impl Drop for BufferState { fn drop(&mut self) { let device = &self.device.borrow().device; - device.destroy_buffer(Takeable::take(&mut self.buffer)); - device.free_memory(Takeable::take(&mut self.memory)); + device.destroy_buffer(self.buffer.take().unwrap()); + device.free_memory(self.memory.take().unwrap()); } } struct Uniform { - buffer: Takeable>, - desc: Takeable>, + buffer: Option>, + desc: Option>, } impl Uniform { @@ -937,37 +939,30 @@ impl Uniform { buffer::Usage::UNIFORM, memory_types, ); - let buffer = Takeable::new(buffer); + let buffer = Some(buffer); desc.write_to_state( vec![DescSetWrite { binding, array_offset: 0, - descriptors: Some(pso::Descriptor::Buffer(buffer.get_buffer(), None..None)), + descriptors: Some(pso::Descriptor::Buffer(buffer.as_ref().unwrap().get_buffer(), None..None)), }], &mut device.borrow_mut().device, ); Uniform { buffer, - desc: Takeable::new(desc), + desc: Some(desc), } } fn get_layout(&self) -> &B::DescriptorSetLayout { - self.desc.get_layout() - } -} - -impl Drop for Uniform { - fn drop(&mut self) { - Takeable::take(&mut self.desc); - Takeable::take(&mut self.buffer); + self.desc.as_ref().unwrap().get_layout() } } struct DescSetLayout { - layout: Takeable, + layout: Option, device: Rc>>, } @@ -982,16 +977,16 @@ impl DescSetLayout { .create_descriptor_set_layout(bindings, &[]); DescSetLayout { - layout: Takeable::new(desc_set_layout), + layout: Some(desc_set_layout), device, } } fn create_desc_set(self, desc_pool: &mut B::DescriptorPool) -> DescSet { - let desc_set = desc_pool.allocate_set(&*self.layout).unwrap(); + let desc_set = desc_pool.allocate_set(self.layout.as_ref().unwrap()).unwrap(); DescSet { layout: self, - set: Takeable::new(desc_set), + set: Some(desc_set), } } } @@ -999,12 +994,12 @@ impl DescSetLayout { impl Drop for DescSetLayout { fn drop(&mut self) { let device = &self.device.borrow().device; - device.destroy_descriptor_set_layout(Takeable::take(&mut self.layout)); + device.destroy_descriptor_set_layout(self.layout.take().unwrap()); } } struct DescSet { - set: Takeable, + set: Option, layout: DescSetLayout, } @@ -1023,7 +1018,7 @@ impl DescSet { W: IntoIterator, W::Item: std::borrow::Borrow>, { - let set = &*self.set; + let set = self.set.as_ref().unwrap(); let write: Vec<_> = write .into_iter() .map(|d| pso::DescriptorSetWrite { @@ -1037,18 +1032,18 @@ impl DescSet { } fn get_layout(&self) -> &B::DescriptorSetLayout { - &*self.layout.layout + self.layout.layout.as_ref().unwrap() } } struct ImageState { desc: DescSet, - buffer: Takeable>, - sampler: Takeable, - image_view: Takeable, - image: Takeable, - memory: Takeable, - transfered_image_fence: Takeable, + buffer: Option>, + sampler: Option, + image_view: Option, + image: Option, + memory: Option, + transfered_image_fence: Option, } impl ImageState { @@ -1068,7 +1063,7 @@ impl ImageState { usage, ); - let buffer = Takeable::new(buffer); + let buffer = Some(buffer); let device = &mut device_state.device; let kind = i::Kind::D2(dims.width as i::Size, dims.height as i::Size, 1, 1); @@ -1148,7 +1143,7 @@ impl ImageState { ); cmd_buffer.copy_buffer_to_image( - buffer.get_buffer(), + buffer.as_ref().unwrap().get_buffer(), &image, i::Layout::TransferDstOptimal, &[command::BufferImageCopy { @@ -1191,17 +1186,17 @@ impl ImageState { ImageState { desc: desc, buffer: buffer, - sampler: Takeable::new(sampler), - image_view: Takeable::new(image_view), - image: Takeable::new(image), - memory: Takeable::new(memory), - transfered_image_fence: Takeable::new(transfered_image_fence), + sampler: Some(sampler), + image_view: Some(image_view), + image: Some(image), + memory: Some(memory), + transfered_image_fence: Some(transfered_image_fence), } } fn wait_for_transfer_completion(&self) { let device = &self.desc.layout.device.borrow().device; - device.wait_for_fence(&*self.transfered_image_fence, !0); + device.wait_for_fence(self.transfered_image_fence.as_ref().unwrap(), !0); } fn get_layout(&self) -> &B::DescriptorSetLayout { @@ -1214,23 +1209,23 @@ impl Drop for ImageState { { let device = &self.desc.layout.device.borrow().device; - let fence = Takeable::take(&mut self.transfered_image_fence); + let fence = self.transfered_image_fence.take().unwrap(); device.wait_for_fence(&fence, !0); device.destroy_fence(fence); - device.destroy_sampler(Takeable::take(&mut self.sampler)); - device.destroy_image_view(Takeable::take(&mut self.image_view)); - device.destroy_image(Takeable::take(&mut self.image)); - device.free_memory(Takeable::take(&mut self.memory)); + device.destroy_sampler(self.sampler.take().unwrap()); + device.destroy_image_view(self.image_view.take().unwrap()); + device.destroy_image(self.image.take().unwrap()); + device.free_memory(self.memory.take().unwrap()); } - Takeable::take(&mut self.buffer); + self.buffer.take().unwrap(); } } struct PipelineState { - pipeline: Takeable, - pipeline_layout: Takeable, + pipeline: Option, + pipeline_layout: Option, device: Rc>>, } @@ -1342,8 +1337,8 @@ impl PipelineState { }; PipelineState { - pipeline: Takeable::new(pipeline), - pipeline_layout: Takeable::new(pipeline_layout), + pipeline: Some(pipeline), + pipeline_layout: Some(pipeline_layout), device: Rc::clone(&device_ptr), } } @@ -1352,16 +1347,16 @@ impl PipelineState { impl Drop for PipelineState { fn drop(&mut self) { let device = &self.device.borrow().device; - device.destroy_graphics_pipeline(Takeable::take(&mut self.pipeline)); - device.destroy_pipeline_layout(Takeable::take(&mut self.pipeline_layout)); + device.destroy_graphics_pipeline(self.pipeline.take().unwrap()); + device.destroy_pipeline_layout(self.pipeline_layout.take().unwrap()); } } struct SwapchainState where B::Surface: SurfaceTrait { - swapchain: Takeable, - backbuffer: Takeable>, + swapchain: Option, + backbuffer: Option>, device: Rc>>, extent: hal::window::Extent2D, format: f::Format, @@ -1417,8 +1412,8 @@ where ); let swapchain = SwapchainState { - swapchain: Takeable::new(swapchain), - backbuffer: Takeable::new(backbuffer), + swapchain: Some(swapchain), + backbuffer: Some(backbuffer), device, extent, format, @@ -1434,19 +1429,19 @@ where self.device .borrow() .device - .destroy_swapchain(Takeable::take(&mut self.swapchain)); + .destroy_swapchain(self.swapchain.take().unwrap()); } } struct FramebufferState where B::Surface: SurfaceTrait { - framebuffers: Takeable>, - framebuffer_fences: Takeable>, - command_pools: Takeable>>, - frame_images: Takeable>, - acquire_semaphores: Takeable>, - present_semaphores: Takeable>, + framebuffers: Option>, + framebuffer_fences: Option>, + command_pools: Option>>, + frame_images: Option>, + acquire_semaphores: Option>, + present_semaphores: Option>, last_ref: usize, device: Rc>>, } @@ -1459,7 +1454,7 @@ where render_pass: &RenderPassState, swapchain: &mut SwapchainState, ) -> Self { - let (frame_images, framebuffers) = match Takeable::take(&mut swapchain.backbuffer) { + let (frame_images, framebuffers) = match swapchain.backbuffer.take().unwrap() { Backbuffer::Images(images) => { let extent = i::Extent { width: swapchain.extent.width as _, @@ -1489,7 +1484,7 @@ where device .borrow() .device - .create_framebuffer(&*render_pass.render_pass, Some(rtv), extent) + .create_framebuffer(render_pass.render_pass.as_ref().unwrap(), Some(rtv), extent) .unwrap() }) .collect(); @@ -1522,19 +1517,19 @@ where } FramebufferState { - frame_images: Takeable::new(frame_images), - framebuffers: Takeable::new(framebuffers), - framebuffer_fences: Takeable::new(fences), - command_pools: Takeable::new(command_pools), - present_semaphores: Takeable::new(present_semaphores), - acquire_semaphores: Takeable::new(acquire_semaphores), + frame_images: Some(frame_images), + framebuffers: Some(framebuffers), + framebuffer_fences: Some(fences), + command_pools: Some(command_pools), + present_semaphores: Some(present_semaphores), + acquire_semaphores: Some(acquire_semaphores), device, last_ref: 0, } } fn next_acq_pre_pair_index(&mut self) -> usize { - if self.last_ref >= self.acquire_semaphores.len() { + if self.last_ref >= self.acquire_semaphores.as_ref().unwrap().len() { self.last_ref = 0 } @@ -1558,17 +1553,17 @@ where ( if let Some(fid) = frame_id { Some(( - &mut self.framebuffer_fences[fid], - &mut self.framebuffers[fid], - &mut self.command_pools[fid], + &mut self.framebuffer_fences.as_mut().unwrap()[fid], + &mut self.framebuffers.as_mut().unwrap()[fid], + &mut self.command_pools.as_mut().unwrap()[fid], )) } else { None }, if let Some(sid) = sem_index { Some(( - &mut self.acquire_semaphores[sid], - &mut self.present_semaphores[sid], + &mut self.acquire_semaphores.as_mut().unwrap()[sid], + &mut self.present_semaphores.as_mut().unwrap()[sid], )) } else { None @@ -1583,28 +1578,28 @@ where fn drop(&mut self) { let device = &self.device.borrow().device; - for fence in Takeable::take(&mut self.framebuffer_fences) { + for fence in self.framebuffer_fences.take().unwrap() { device.wait_for_fence(&fence, !0); device.destroy_fence(fence); } - for command_pool in Takeable::take(&mut self.command_pools) { + for command_pool in self.command_pools.take().unwrap() { device.destroy_command_pool(command_pool.into_raw()); } - for acquire_semaphore in Takeable::take(&mut self.acquire_semaphores) { + for acquire_semaphore in self.acquire_semaphores.take().unwrap() { device.destroy_semaphore(acquire_semaphore); } - for present_semaphore in Takeable::take(&mut self.present_semaphores) { + for present_semaphore in self.present_semaphores.take().unwrap() { device.destroy_semaphore(present_semaphore); } - for framebuffer in Takeable::take(&mut self.framebuffers) { + for framebuffer in self.framebuffers.take().unwrap() { device.destroy_framebuffer(framebuffer); } - for (_, rtv) in Takeable::take(&mut self.frame_images) { + for (_, rtv) in self.frame_images.take().unwrap() { device.destroy_image_view(rtv); } }