Skip to content

Instantly share code, notes, and snippets.

@StarArawn
Created January 8, 2019 13:36
Show Gist options
  • Save StarArawn/b7044b04b99d1684d02d0ebce1abd9c5 to your computer and use it in GitHub Desktop.
Save StarArawn/b7044b04b99d1684d02d0ebce1abd9c5 to your computer and use it in GitHub Desktop.
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