Created
January 8, 2019 13:36
-
-
Save StarArawn/b7044b04b99d1684d02d0ebce1abd9c5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use rendy::{ | |
command::{RenderPassInlineEncoder}, | |
factory::{Config, Factory}, | |
graph::{Graph, GraphBuilder, render::RenderPass, present::PresentNode, NodeBuffer, NodeImage}, | |
memory::MemoryUsageValue, | |
mesh::{AsVertex, PosColor}, | |
shader::{Shader, StaticShaderInfo, ShaderKind, SourceLanguage}, | |
resource::buffer::Buffer, | |
}; | |
use winit::{ | |
EventsLoop, WindowBuilder, KeyboardInput, WindowEvent, Event, VirtualKeyCode | |
}; | |
#[cfg(feature = "dx12")] | |
type Backend = rendy::dx12::Backend; | |
#[cfg(feature = "metal")] | |
type Backend = rendy::metal::Backend; | |
#[cfg(feature = "vulkan")] | |
type Backend = rendy::vulkan::Backend; | |
#[derive(Debug)] | |
struct ClearRenderPass { | |
} | |
lazy_static::lazy_static! { | |
static ref vertex: StaticShaderInfo = StaticShaderInfo::new( | |
concat!(env!("CARGO_MANIFEST_DIR"), "/examples/shader.vert"), | |
ShaderKind::Vertex, | |
SourceLanguage::GLSL, | |
"main", | |
); | |
static ref fragment: StaticShaderInfo = StaticShaderInfo::new( | |
concat!(env!("CARGO_MANIFEST_DIR"), "/examples/shader.frag"), | |
ShaderKind::Fragment, | |
SourceLanguage::GLSL, | |
"main", | |
); | |
} | |
#[derive(Debug)] | |
struct TriangleRenderPass<B: gfx_hal::Backend> { | |
vertex: Option<Buffer<B>>, | |
} | |
impl<B, T> RenderPass<B, T> for TriangleRenderPass<B> | |
where | |
B: gfx_hal::Backend, | |
T: ?Sized, | |
{ | |
fn name() -> &'static str { | |
"Triangle" | |
} | |
fn vertices() -> Vec<( | |
Vec<gfx_hal::pso::Element<gfx_hal::format::Format>>, | |
gfx_hal::pso::ElemStride, | |
)> { | |
vec![PosColor::VERTEX.gfx_vertex_input_desc()] | |
} | |
fn load_shader_sets<'a>( | |
storage: &'a mut Vec<B::ShaderModule>, | |
factory: &mut Factory<B>, | |
_aux: &mut T, | |
) -> Vec<gfx_hal::pso::GraphicsShaderSet<'a, B>> { | |
storage.clear(); | |
log::trace!("Load shader module '{:#?}'", *vertex); | |
storage.push(vertex.module(factory).unwrap()); | |
log::trace!("Load shader module '{:#?}'", *fragment); | |
storage.push(fragment.module(factory).unwrap()); | |
vec![gfx_hal::pso::GraphicsShaderSet { | |
vertex: gfx_hal::pso::EntryPoint { | |
entry: "main", | |
module: &storage[0], | |
specialization: gfx_hal::pso::Specialization::default(), | |
}, | |
fragment: Some(gfx_hal::pso::EntryPoint { | |
entry: "main", | |
module: &storage[1], | |
specialization: gfx_hal::pso::Specialization::default(), | |
}), | |
hull: None, | |
domain: None, | |
geometry: None, | |
}] | |
} | |
fn build<'a>( | |
_factory: &mut Factory<B>, | |
_aux: &mut T, | |
buffers: &mut [NodeBuffer<'a, B>], | |
images: &mut [NodeImage<'a, B>], | |
sets: &[impl AsRef<[B::DescriptorSetLayout]>], | |
) -> Self { | |
assert!(buffers.is_empty()); | |
assert!(images.is_empty()); | |
assert_eq!(sets.len(), 1); | |
assert!(sets[0].as_ref().is_empty()); | |
TriangleRenderPass { | |
vertex: None, | |
} | |
} | |
fn prepare(&mut self, factory: &mut Factory<B>, _aux: &T) -> bool { | |
if self.vertex.is_some() { | |
return false; | |
} | |
let mut vbuf = factory.create_buffer(512, PosColor::VERTEX.stride as u64 * 3, (gfx_hal::buffer::Usage::VERTEX, MemoryUsageValue::Dynamic)) | |
.unwrap(); | |
unsafe { | |
// Fresh buffer. | |
factory.upload_visible_buffer(&mut vbuf, 0, &[ | |
PosColor { | |
position: [0.0, -0.5, 0.0].into(), | |
color: [1.0, 0.0, 0.0, 1.0].into(), | |
}, | |
PosColor { | |
position: [0.5, 0.5, 0.0].into(), | |
color: [0.0, 1.0, 0.0, 1.0].into(), | |
}, | |
PosColor { | |
position: [-0.5, 0.5, 0.0].into(), | |
color: [0.0, 0.0, 1.0, 1.0].into(), | |
}, | |
]).unwrap(); | |
} | |
self.vertex = Some(vbuf); | |
true | |
} | |
fn draw( | |
&mut self, | |
_layouts: &[B::PipelineLayout], | |
pipelines: &[B::GraphicsPipeline], | |
mut encoder: RenderPassInlineEncoder<'_, B>, | |
_index: usize, | |
_aux: &T, | |
) { | |
let vbuf = self.vertex.as_ref().unwrap(); | |
encoder.bind_graphics_pipeline(&pipelines[0]); | |
encoder.bind_vertex_buffers(0, Some((vbuf.raw(), 0))); | |
encoder.draw(0..3, 0..1); | |
} | |
fn dispose(self, _factory: &mut Factory<B>, _aux: &mut T) { | |
} | |
} | |
impl<B, T> RenderPass<B, T> for ClearRenderPass | |
where | |
B: gfx_hal::Backend, | |
T: ?Sized, | |
{ | |
fn name() -> &'static str { | |
"Triangle" | |
} | |
fn load_shader_sets<'a>( | |
storage: &'a mut Vec<B::ShaderModule>, | |
factory: &mut Factory<B>, | |
_aux: &mut T, | |
) -> Vec<gfx_hal::pso::GraphicsShaderSet<'a, B>> { | |
storage.clear(); | |
vec![] | |
} | |
fn build<'a>( | |
_factory: &mut Factory<B>, | |
_aux: &mut T, | |
buffers: &mut [NodeBuffer<'a, B>], | |
images: &mut [NodeImage<'a, B>], | |
sets: &[impl AsRef<[B::DescriptorSetLayout]>], | |
) -> Self { | |
assert!(buffers.is_empty()); | |
assert!(images.is_empty()); | |
assert_eq!(sets.len(), 1); | |
assert!(sets[0].as_ref().is_empty()); | |
ClearRenderPass { | |
} | |
} | |
fn prepare(&mut self, factory: &mut Factory<B>, _aux: &T) -> bool { | |
true | |
} | |
fn draw( | |
&mut self, | |
_layouts: &[B::PipelineLayout], | |
pipelines: &[B::GraphicsPipeline], | |
mut encoder: RenderPassInlineEncoder<'_, B>, | |
_index: usize, | |
_aux: &T, | |
) { | |
} | |
fn dispose(self, _factory: &mut Factory<B>, _aux: &mut T) { | |
} | |
} | |
fn run(events_loop: &mut EventsLoop, factory: &mut Factory<Backend>, mut graph: Graph<Backend, ()>) { | |
let mut t: f32 = 0.0; | |
let dt: f32 = 1.0 / 60.0; | |
let _counted_frames = 0; | |
let mut current_time = std::time::Instant::now(); | |
let mut frame_time_buffer = std::collections::VecDeque::<f32>::with_capacity(256); | |
// Mainloop starts here | |
loop { | |
let mut quitting = false; | |
let new_time = std::time::Instant::now(); | |
let mut frame_time: f32 = (new_time.duration_since(current_time).subsec_nanos() as f32) / 1000000000.0; // from ns to s | |
frame_time_buffer.push_back(frame_time); | |
// println!("Frame time: {}ms", (frame_time_buffer.iter().sum::<f32>() / (frame_time_buffer.len() as f32) * 1000.0).floor()); | |
current_time = new_time; | |
while frame_time > 0.0 { | |
let delta_time = frame_time.min(dt); | |
// If the window is closed, or Escape is pressed, quit | |
events_loop.poll_events(|event| { | |
if let Event::WindowEvent { event, .. } = event { | |
match event { | |
WindowEvent::CloseRequested => quitting = true, | |
WindowEvent::KeyboardInput { | |
input: | |
KeyboardInput { | |
virtual_keycode: Some(VirtualKeyCode::Escape), | |
.. | |
}, | |
.. | |
} => quitting = true, | |
_ => {} | |
} | |
} | |
}); | |
// Update stuff here.. | |
frame_time -= delta_time; | |
t += delta_time; | |
} | |
// Render stuff here.. | |
graph.run(factory, &mut ()); | |
if quitting { | |
break; | |
} | |
} | |
} | |
#[cfg(any(feature = "dx12", feature = "metal", feature = "vulkan"))] | |
fn main() { | |
env_logger::Builder::from_default_env() | |
.filter_level(log::LevelFilter::Info) | |
.filter_module("simple", log::LevelFilter::Trace) | |
.init(); | |
let config: Config = Default::default(); | |
let mut factory: Factory<Backend> = Factory::new(config).unwrap(); | |
let mut event_loop = EventsLoop::new(); | |
let window = WindowBuilder::new() | |
.with_title("Rendy example") | |
.build(&event_loop).unwrap(); | |
let surface = factory.create_surface(window.into()); | |
let mut graph_builder = GraphBuilder::<Backend, ()>::new(); | |
let color = graph_builder.create_image( | |
surface.kind(), | |
1, | |
gfx_hal::format::Format::Rgba8Srgb, | |
MemoryUsageValue::Data, | |
Some(gfx_hal::command::ClearValue::Color(gfx_hal::command::ClearColor::Float([1.0, 0.0, 0.0, 1.0]))), | |
); | |
let pass = graph_builder.add_node( | |
ClearRenderPass::builder() | |
.with_image(color) | |
); | |
let color2 = graph_builder.create_image( | |
surface.kind(), | |
1, | |
gfx_hal::format::Format::Rgba8Srgb, | |
MemoryUsageValue::Data, | |
None, | |
); | |
let pass2 = graph_builder.add_node( | |
TriangleRenderPass::builder() | |
.with_image(color2) | |
.with_dependency(pass) | |
); | |
graph_builder.add_node( | |
PresentNode::builder(surface) | |
.with_image(color) | |
.with_dependency(pass2) | |
); | |
let graph = graph_builder.build(&mut factory, &mut ()).unwrap(); | |
run(&mut event_loop, &mut factory, graph); | |
factory.dispose(); | |
} | |
#[cfg(not(any(feature = "dx12", feature = "metal", feature = "vulkan")))] | |
fn main() { | |
panic!("Specify feature: { dx12, metal, vulkan }"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment