refactor: renderable
parent
8b82aeac1c
commit
86e5d03a91
|
@ -6,9 +6,11 @@ rust_binary(
|
||||||
srcs = [
|
srcs = [
|
||||||
"src/main.rs",
|
"src/main.rs",
|
||||||
"src/render/mod.rs",
|
"src/render/mod.rs",
|
||||||
|
"src/render/renderable.rs",
|
||||||
"src/render/vulkan/mod.rs",
|
"src/render/vulkan/mod.rs",
|
||||||
"src/render/vulkan/binding.rs",
|
"src/render/vulkan/binding.rs",
|
||||||
"src/render/vulkan/data.rs",
|
"src/render/vulkan/data.rs",
|
||||||
|
"src/render/vulkan/pipeline.rs",
|
||||||
"src/render/vulkan/qfi.rs",
|
"src/render/vulkan/qfi.rs",
|
||||||
"src/render/vulkan/shaders.rs",
|
"src/render/vulkan/shaders.rs",
|
||||||
"src/render/vulkan/swapchains.rs",
|
"src/render/vulkan/swapchains.rs",
|
||||||
|
|
|
@ -1,12 +1,35 @@
|
||||||
use log;
|
use log;
|
||||||
use env_logger;
|
use env_logger;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use cgmath as cgm;
|
||||||
|
|
||||||
mod render;
|
mod render;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
use render::vulkan::data;
|
||||||
|
use render::renderable::Renderable;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
log::info!("Starting...");
|
log::info!("Starting...");
|
||||||
|
|
||||||
|
let elapsed = 0.0;
|
||||||
|
let transform = cgm::Matrix4::from_angle_z(cgm::Rad::from(cgm::Deg(elapsed as f32 * 0.180)));
|
||||||
|
let vertices = Arc::new(vec![
|
||||||
|
data::Vertex::new([-0.5, -0.5, 0.0], [1.0, 0.0, 0.0]),
|
||||||
|
data::Vertex::new([0.5, -0.5, 0.0], [0.0, 1.0, 0.0]),
|
||||||
|
data::Vertex::new([0.5, 0.5, 0.0], [0.0, 0.0, 1.0]),
|
||||||
|
data::Vertex::new([-0.5, 0.5, 0.0], [1.0, 1.0, 1.0])
|
||||||
|
]);
|
||||||
|
let indices = Arc::new(vec![
|
||||||
|
0, 1, 2, 2, 3, 0,
|
||||||
|
]);
|
||||||
|
let demo = render::renderable::Mesh {
|
||||||
|
transform, vertices, indices
|
||||||
|
};
|
||||||
|
|
||||||
let mut renderer = render::Renderer::initialize();
|
let mut renderer = render::Renderer::initialize();
|
||||||
|
renderer.set_render_data(vec![demo.data().unwrap()]);
|
||||||
renderer.main_loop();
|
renderer.main_loop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,8 @@ use vulkano_win::VkSurfaceBuild;
|
||||||
use vulkano::instance as vi;
|
use vulkano::instance as vi;
|
||||||
use vulkano::swapchain as vs;
|
use vulkano::swapchain as vs;
|
||||||
|
|
||||||
mod vulkan;
|
pub mod vulkan;
|
||||||
|
pub mod renderable;
|
||||||
|
|
||||||
const WIDTH: u32 = 800;
|
const WIDTH: u32 = 800;
|
||||||
const HEIGHT: u32 = 600;
|
const HEIGHT: u32 = 600;
|
||||||
|
@ -20,6 +21,8 @@ const HEIGHT: u32 = 600;
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
instance: vulkan::Instance<winit::Window>,
|
instance: vulkan::Instance<winit::Window>,
|
||||||
events_loop: EventsLoop,
|
events_loop: EventsLoop,
|
||||||
|
|
||||||
|
render_data: Vec<renderable::Data>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer {
|
impl Renderer {
|
||||||
|
@ -31,9 +34,14 @@ impl Renderer {
|
||||||
Self {
|
Self {
|
||||||
instance,
|
instance,
|
||||||
events_loop,
|
events_loop,
|
||||||
|
render_data: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_render_data(&mut self, render_data: Vec<renderable::Data>) {
|
||||||
|
self.render_data = render_data;
|
||||||
|
}
|
||||||
|
|
||||||
fn init_window(instance: Arc<vi::Instance>) -> (EventsLoop, Arc<vs::Surface<Window>>) {
|
fn init_window(instance: Arc<vi::Instance>) -> (EventsLoop, Arc<vs::Surface<Window>>) {
|
||||||
let events_loop = EventsLoop::new();
|
let events_loop = EventsLoop::new();
|
||||||
let surface = WindowBuilder::new()
|
let surface = WindowBuilder::new()
|
||||||
|
@ -45,7 +53,7 @@ impl Renderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_frame(&mut self) {
|
fn draw_frame(&mut self) {
|
||||||
self.instance.flip();
|
self.instance.flip(self.render_data.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main_loop(&mut self) {
|
pub fn main_loop(&mut self) {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use cgmath as cgm;
|
||||||
|
|
||||||
|
use crate::render::vulkan::data;
|
||||||
|
|
||||||
|
pub trait Renderable {
|
||||||
|
fn data(&self) -> Option<Data> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Data {
|
||||||
|
pub vertices: Arc<Vec<data::Vertex>>,
|
||||||
|
pub indices: Arc<Vec<u16>>,
|
||||||
|
pub transform: cgm::Matrix4<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Mesh {
|
||||||
|
pub vertices: Arc<Vec<data::Vertex>>,
|
||||||
|
pub indices: Arc<Vec<u16>>,
|
||||||
|
pub transform: cgm::Matrix4<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderable for Mesh {
|
||||||
|
fn data(&self) -> Option<Data> {
|
||||||
|
Some(Data {
|
||||||
|
vertices: self.vertices.clone(),
|
||||||
|
indices: self.indices.clone(),
|
||||||
|
transform: self.transform.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,19 +13,6 @@ impl Vertex {
|
||||||
}
|
}
|
||||||
vulkano::impl_vertex!(Vertex, pos, color);
|
vulkano::impl_vertex!(Vertex, pos, color);
|
||||||
|
|
||||||
pub fn vertices() -> [Vertex; 4] {
|
|
||||||
[
|
|
||||||
Vertex::new([-0.5, -0.5, 0.0], [1.0, 0.0, 0.0]),
|
|
||||||
Vertex::new([0.5, -0.5, 0.0], [0.0, 1.0, 0.0]),
|
|
||||||
Vertex::new([0.5, 0.5, 0.0], [0.0, 0.0, 1.0]),
|
|
||||||
Vertex::new([-0.5, 0.5, 0.0], [1.0, 1.0, 1.0])
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn indices() -> [u16; 6] {
|
|
||||||
[0, 1, 2, 2, 3, 0]
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct UniformBufferObject {
|
pub struct UniformBufferObject {
|
||||||
pub model: cgm::Matrix4<f32>,
|
pub model: cgm::Matrix4<f32>,
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
|
||||||
use std::time;
|
use std::time;
|
||||||
use log;
|
use log;
|
||||||
|
|
||||||
use cgmath as cgm;
|
use cgmath as cgm;
|
||||||
use cgmath::prelude::SquareMatrix;
|
|
||||||
use vulkano::buffer as vb;
|
use vulkano::buffer as vb;
|
||||||
use vulkano::command_buffer as vc;
|
use vulkano::command_buffer as vc;
|
||||||
use vulkano::descriptor::descriptor_set as vdd;
|
use vulkano::framebuffer as vf;
|
||||||
use vulkano::instance as vi;
|
use vulkano::instance as vi;
|
||||||
use vulkano::pipeline as vp;
|
|
||||||
use vulkano::swapchain as vs;
|
use vulkano::swapchain as vs;
|
||||||
use vulkano::sync::{FenceSignalFuture, GpuFuture};
|
use vulkano::sync::{FenceSignalFuture, GpuFuture};
|
||||||
|
|
||||||
mod binding;
|
mod binding;
|
||||||
mod data;
|
pub mod data;
|
||||||
|
mod pipeline;
|
||||||
|
mod qfi;
|
||||||
mod shaders;
|
mod shaders;
|
||||||
mod swapchains;
|
mod swapchains;
|
||||||
mod qfi;
|
|
||||||
|
use crate::render::renderable;
|
||||||
|
|
||||||
const VERSION: vi::Version = vi::Version { major: 1, minor: 0, patch: 0};
|
const VERSION: vi::Version = vi::Version { major: 1, minor: 0, patch: 0};
|
||||||
|
|
||||||
|
@ -33,10 +33,8 @@ pub struct Instance<WT> {
|
||||||
|
|
||||||
surface_binding: Option<binding::SurfaceBinding<WT>>,
|
surface_binding: Option<binding::SurfaceBinding<WT>>,
|
||||||
swapchain_binding: Option<swapchains::SwapchainBinding<WT>>,
|
swapchain_binding: Option<swapchains::SwapchainBinding<WT>>,
|
||||||
command_buffers: Vec<Arc<vc::AutoCommandBuffer>>,
|
|
||||||
uniform_buffers: Vec<Arc<vb::CpuAccessibleBuffer<data::UniformBufferObject>>>,
|
|
||||||
descriptor_sets: Vec<Arc<vdd::FixedSizeDescriptorSet<Arc<dyn vp::GraphicsPipelineAbstract + Send + Sync>, ((), vdd::PersistentDescriptorSetBuf<Arc<vb::CpuAccessibleBuffer<data::UniformBufferObject>>>)>>>,
|
|
||||||
|
|
||||||
|
pipeline: Option<Box<dyn pipeline::Pipeline>>,
|
||||||
armed: bool,
|
armed: bool,
|
||||||
previous_frame_end: Option<Box<FlipFuture<WT>>>,
|
previous_frame_end: Option<Box<FlipFuture<WT>>>,
|
||||||
fps_counter: crate::util::counter::Counter,
|
fps_counter: crate::util::counter::Counter,
|
||||||
|
@ -66,10 +64,8 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
|
||||||
|
|
||||||
surface_binding: None,
|
surface_binding: None,
|
||||||
swapchain_binding: None,
|
swapchain_binding: None,
|
||||||
command_buffers: vec![],
|
|
||||||
uniform_buffers: vec![],
|
|
||||||
descriptor_sets: vec![],
|
|
||||||
|
|
||||||
|
pipeline: None,
|
||||||
previous_frame_end: None,
|
previous_frame_end: None,
|
||||||
armed: false,
|
armed: false,
|
||||||
fps_counter: crate::util::counter::Counter::new(time::Duration::from_millis(1000)),
|
fps_counter: crate::util::counter::Counter::new(time::Duration::from_millis(1000)),
|
||||||
|
@ -102,33 +98,18 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
|
||||||
let chain = self.swapchain_binding().chain.clone();
|
let chain = self.swapchain_binding().chain.clone();
|
||||||
|
|
||||||
let render_pass = self.swapchain_binding().render_pass.clone();
|
let render_pass = self.swapchain_binding().render_pass.clone();
|
||||||
let pipeline = shaders::pipeline_forward(device.clone(), chain.dimensions(), render_pass);
|
|
||||||
|
|
||||||
let (vbuffer, future) = vb::immutable::ImmutableBuffer::from_iter(
|
|
||||||
data::vertices().iter().cloned(),
|
|
||||||
vb::BufferUsage::vertex_buffer(),
|
|
||||||
self.surface_binding().graphics_queue.clone(),
|
|
||||||
).unwrap();
|
|
||||||
future.flush().unwrap();
|
|
||||||
|
|
||||||
let (ibuffer, future) = vb::immutable::ImmutableBuffer::from_iter(
|
|
||||||
data::indices().iter().cloned(),
|
|
||||||
vb::BufferUsage::index_buffer(),
|
|
||||||
self.surface_binding().graphics_queue.clone(),
|
|
||||||
).unwrap();
|
|
||||||
future.flush().unwrap();
|
|
||||||
|
|
||||||
self.create_uniform_buffers();
|
|
||||||
self.create_descriptor_sets(pipeline.clone());
|
|
||||||
self.create_command_buffers(pipeline.clone(), vbuffer, ibuffer);
|
|
||||||
|
|
||||||
|
self.pipeline = Some(Box::new(pipeline::Forward::new(device.clone(), chain.dimensions(), render_pass)));
|
||||||
self.previous_frame_end = None;
|
self.previous_frame_end = None;
|
||||||
self.armed = true;
|
self.armed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// (╯°□°)╯︵ ┻━┻
|
// (╯°□°)╯︵ ┻━┻
|
||||||
pub fn flip(&mut self) {
|
pub fn flip(
|
||||||
|
&mut self,
|
||||||
|
render_data: Vec<renderable::Data>,
|
||||||
|
) {
|
||||||
match &self.previous_frame_end {
|
match &self.previous_frame_end {
|
||||||
None => (),
|
None => (),
|
||||||
Some(future) => future.wait(None).unwrap(),
|
Some(future) => future.wait(None).unwrap(),
|
||||||
|
@ -148,7 +129,9 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
|
||||||
},
|
},
|
||||||
Err(err) => panic!("{:?}", err),
|
Err(err) => panic!("{:?}", err),
|
||||||
};
|
};
|
||||||
let command_buffer = self.command_buffers[image_index].clone();
|
|
||||||
|
let fb = self.swapchain_binding().framebuffers[image_index].clone();
|
||||||
|
let command_buffer = self.make_command_buffer(fb, render_data);
|
||||||
|
|
||||||
let gq = self.surface_binding().graphics_queue.clone();
|
let gq = self.surface_binding().graphics_queue.clone();
|
||||||
let pq = self.surface_binding().present_queue.clone();
|
let pq = self.surface_binding().present_queue.clone();
|
||||||
|
@ -176,103 +159,69 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_descriptor_sets(
|
|
||||||
&mut self,
|
|
||||||
pipeline: Arc<dyn vp::GraphicsPipelineAbstract + Send + Sync>
|
|
||||||
) {
|
|
||||||
let pool = Arc::new(
|
|
||||||
Mutex::new(
|
|
||||||
vdd::FixedSizeDescriptorSetsPool::new(pipeline.clone(), 0)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
self.descriptor_sets = self.uniform_buffers
|
|
||||||
.iter()
|
|
||||||
.map(|uniform_buffer|
|
|
||||||
Arc::new(
|
|
||||||
pool
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.next()
|
|
||||||
.add_buffer(uniform_buffer.clone())
|
|
||||||
.unwrap()
|
|
||||||
.build()
|
|
||||||
.unwrap()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dimensions(&self) -> [f32; 2] {
|
fn dimensions(&self) -> [f32; 2] {
|
||||||
let dimensions_u32 = self.swapchain_binding().chain.dimensions();
|
let dimensions_u32 = self.swapchain_binding().chain.dimensions();
|
||||||
[dimensions_u32[0] as f32, dimensions_u32[1] as f32]
|
[dimensions_u32[0] as f32, dimensions_u32[1] as f32]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_uniform_buffer(&self) -> data::UniformBufferObject {
|
fn make_command_buffer(
|
||||||
let elapsed = 40.0 as f32;
|
&mut self,
|
||||||
|
framebuffer: Arc<dyn vf::FramebufferAbstract + Send + Sync>,
|
||||||
|
render_data: Vec<renderable::Data>,
|
||||||
|
) -> Arc<vc::AutoCommandBuffer> {
|
||||||
|
let device = self.surface_binding().device.clone();
|
||||||
|
let qf = self.surface_binding().graphics_queue.family();
|
||||||
let dimensions = self.dimensions();
|
let dimensions = self.dimensions();
|
||||||
|
let mut c = vc::AutoCommandBufferBuilder::primary_simultaneous_use(device.clone(), qf)
|
||||||
|
.unwrap()
|
||||||
|
.begin_render_pass(framebuffer.clone(), false, vec![[0.0, 0.0, 0.0, 1.0].into()])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let model = cgm::Matrix4::from_angle_z(cgm::Rad::from(cgm::Deg(elapsed as f32 * 0.180)));
|
|
||||||
let view = cgm::Matrix4::look_at(
|
let view = cgm::Matrix4::look_at(
|
||||||
cgm::Point3::new(2.0, 2.0, 2.0),
|
cgm::Point3::new(2.0, 2.0, 2.0),
|
||||||
cgm::Point3::new(0.0, 0.0, 0.0),
|
cgm::Point3::new(0.0, 0.0, 0.0),
|
||||||
cgm::Vector3::new(0.0, 0.0, 1.0)
|
cgm::Vector3::new(0.0, 0.0, 1.0)
|
||||||
);
|
);
|
||||||
let mut proj = cgm::perspective(
|
let proj = cgm::perspective(
|
||||||
cgm::Rad::from(cgm::Deg(45.0)),
|
cgm::Rad::from(cgm::Deg(45.0)),
|
||||||
dimensions[0] as f32 / dimensions[1] as f32,
|
dimensions[0] / dimensions[1],
|
||||||
0.1,
|
0.1,
|
||||||
10.0
|
10.0
|
||||||
);
|
);
|
||||||
log::info!("model: {:?}", model);
|
|
||||||
log::info!(" view: {:?}", view);
|
|
||||||
log::info!(" proj: {:?}", proj);
|
|
||||||
data::UniformBufferObject { model, view, proj }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_uniform_buffers(&mut self) {
|
for d in render_data {
|
||||||
let mut buffers = Vec::new();
|
let (vbuffer, future) = vb::immutable::ImmutableBuffer::from_iter(
|
||||||
|
d.vertices.iter().cloned(),
|
||||||
let uniform_buffer = self.build_uniform_buffer();
|
vb::BufferUsage::vertex_buffer(),
|
||||||
for _ in 0..self.swapchain_binding().images.len() {
|
self.surface_binding().graphics_queue.clone(),
|
||||||
let buffer = vb::CpuAccessibleBuffer::from_data(
|
|
||||||
self.surface_binding().device.clone(),
|
|
||||||
vb::BufferUsage::uniform_buffer_transfer_destination(),
|
|
||||||
uniform_buffer,
|
|
||||||
).unwrap();
|
).unwrap();
|
||||||
buffers.push(buffer);
|
future.flush().unwrap();
|
||||||
|
|
||||||
|
let (ibuffer, future) = vb::immutable::ImmutableBuffer::from_iter(
|
||||||
|
d.indices.iter().cloned(),
|
||||||
|
vb::BufferUsage::index_buffer(),
|
||||||
|
self.surface_binding().graphics_queue.clone(),
|
||||||
|
).unwrap();
|
||||||
|
future.flush().unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
let ubo = data::UniformBufferObject {
|
||||||
|
model: d.transform.clone(),
|
||||||
|
view: view.clone(),
|
||||||
|
proj: proj.clone(),
|
||||||
|
};
|
||||||
|
let ds = self.pipeline.as_mut().unwrap().make_descriptor_set(ubo);
|
||||||
|
let pipeline = self.pipeline.as_ref().unwrap().get_pipeline();
|
||||||
|
c = c.draw_indexed(pipeline, &vc::DynamicState::none(),
|
||||||
|
vec![vbuffer.clone()],
|
||||||
|
ibuffer.clone(),
|
||||||
|
ds,
|
||||||
|
()).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.uniform_buffers = buffers;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_command_buffers(
|
Arc::new(c.end_render_pass().unwrap()
|
||||||
&mut self,
|
.build().unwrap())
|
||||||
pipeline: Arc<dyn vp::GraphicsPipelineAbstract + Send + Sync>,
|
|
||||||
vertex_buffer: Arc<dyn vb::BufferAccess + Send + Sync>,
|
|
||||||
index_buffer: Arc<dyn vb::TypedBufferAccess<Content=[u16]> + Send + Sync>,
|
|
||||||
) {
|
|
||||||
let device = self.surface_binding().device.clone();
|
|
||||||
let qf = self.surface_binding().graphics_queue.family();
|
|
||||||
self.command_buffers = self.swapchain_binding().framebuffers.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, framebuffer)| {
|
|
||||||
Arc::new(vc::AutoCommandBufferBuilder::primary_simultaneous_use(device.clone(), qf)
|
|
||||||
.unwrap()
|
|
||||||
.begin_render_pass(framebuffer.clone(), false, vec![[0.0, 0.0, 0.0, 1.0].into()])
|
|
||||||
.unwrap()
|
|
||||||
.draw_indexed(pipeline.clone(), &vc::DynamicState::none(),
|
|
||||||
vec![vertex_buffer.clone()],
|
|
||||||
index_buffer.clone(),
|
|
||||||
self.descriptor_sets[i].clone(),
|
|
||||||
())
|
|
||||||
.unwrap()
|
|
||||||
.end_render_pass()
|
|
||||||
.unwrap()
|
|
||||||
.build()
|
|
||||||
.unwrap())
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use vulkano::buffer as vb;
|
||||||
|
use vulkano::descriptor::descriptor_set as vdd;
|
||||||
|
use vulkano::device as vd;
|
||||||
|
use vulkano::format::Format;
|
||||||
|
use vulkano::framebuffer as vf;
|
||||||
|
use vulkano::pipeline as vp;
|
||||||
|
use vulkano::pipeline::shader as vps;
|
||||||
|
|
||||||
|
use crate::render::vulkan::data;
|
||||||
|
use crate::render::vulkan::shaders;
|
||||||
|
|
||||||
|
type VulkanoPipeline = dyn vp::GraphicsPipelineAbstract + Send + Sync;
|
||||||
|
type VulkanoDescriptorSet = dyn vdd::DescriptorSet + Send + Sync;
|
||||||
|
|
||||||
|
pub trait Pipeline {
|
||||||
|
fn get_pipeline(&self) -> Arc<VulkanoPipeline>;
|
||||||
|
fn make_descriptor_set(&mut self, ubo: data::UniformBufferObject) -> Arc<VulkanoDescriptorSet>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Forward {
|
||||||
|
device: Arc<vd::Device>,
|
||||||
|
|
||||||
|
pipeline: Arc<VulkanoPipeline>,
|
||||||
|
descriptor_set_pool: vdd::FixedSizeDescriptorSetsPool<Arc<VulkanoPipeline>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Forward {
|
||||||
|
pub fn new(
|
||||||
|
device: Arc<vd::Device>,
|
||||||
|
viewport_dimensions: [u32; 2],
|
||||||
|
render_pass: Arc<dyn vf::RenderPassAbstract + Send + Sync>,
|
||||||
|
) -> Forward {
|
||||||
|
let vertex_shader = shaders::ShaderDefinition {
|
||||||
|
name: "forward_vert.spv".to_string(),
|
||||||
|
ty: vps::GraphicsShaderType::Vertex,
|
||||||
|
inputs: vec![
|
||||||
|
vps::ShaderInterfaceDefEntry { location: 0..1, format: Format::R32G32B32Sfloat, name: Some(Cow::Borrowed("pos")) },
|
||||||
|
vps::ShaderInterfaceDefEntry { location: 1..2, format: Format::R32G32B32Sfloat, name: Some(Cow::Borrowed("color")) },
|
||||||
|
],
|
||||||
|
outputs: vec![
|
||||||
|
vps::ShaderInterfaceDefEntry { location: 0..1, format: Format::R32G32B32Sfloat, name: Some(Cow::Borrowed("fragColor")) }
|
||||||
|
],
|
||||||
|
}.load_into(device.clone()).expect("could not load vertex shader");
|
||||||
|
|
||||||
|
let fragment_shader = shaders::ShaderDefinition {
|
||||||
|
name: "forward_frag.spv".to_string(),
|
||||||
|
ty: vps::GraphicsShaderType::Fragment,
|
||||||
|
inputs: vec![
|
||||||
|
vps::ShaderInterfaceDefEntry { location: 0..1, format: Format::R32G32B32Sfloat, name: Some(Cow::Borrowed("fragColor")) }
|
||||||
|
],
|
||||||
|
outputs: vec![
|
||||||
|
vps::ShaderInterfaceDefEntry { location: 0..1, format: Format::R32G32B32A32Sfloat, name: Some(Cow::Borrowed("outColor")) }
|
||||||
|
],
|
||||||
|
}.load_into(device.clone()).expect("could not load fragment shader");
|
||||||
|
|
||||||
|
let dimensions = [viewport_dimensions[0] as f32, viewport_dimensions[1] as f32];
|
||||||
|
let viewport = vp::viewport::Viewport {
|
||||||
|
origin: [0.0, 0.0],
|
||||||
|
dimensions,
|
||||||
|
depth_range: 0.0 .. 1.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Counter-clockwise facing triangles - this is because geometry data is left-handed, and
|
||||||
|
// the vertex shader performs a handedness flip by doing .y *= -1 on emitted vertices. To
|
||||||
|
// keep geomtry-space triangles clockwise after this transformation, the pipeline must be
|
||||||
|
// set to treat counter-clockwise triangles as front-facing. An alternative would be to
|
||||||
|
// fully embrace the vulkan coordinate system, including geometry - however this goes
|
||||||
|
// against most existing software and practices. This might bite us in the ass at some
|
||||||
|
// point in the future.
|
||||||
|
let pipeline = Arc::new(vp::GraphicsPipeline::start()
|
||||||
|
.vertex_input_single_buffer::<data::Vertex>()
|
||||||
|
.vertex_shader(vertex_shader.entry_point(), ())
|
||||||
|
.triangle_list()
|
||||||
|
.primitive_restart(false)
|
||||||
|
.viewports(vec![viewport])
|
||||||
|
.fragment_shader(fragment_shader.entry_point(), ())
|
||||||
|
.depth_clamp(false)
|
||||||
|
.polygon_mode_fill()
|
||||||
|
.line_width(1.0)
|
||||||
|
.cull_mode_back()
|
||||||
|
.front_face_counter_clockwise()
|
||||||
|
.blend_pass_through()
|
||||||
|
.render_pass(vf::Subpass::from(render_pass.clone(), 0).unwrap())
|
||||||
|
.build(device.clone())
|
||||||
|
.unwrap())
|
||||||
|
as Arc<VulkanoPipeline>;
|
||||||
|
|
||||||
|
let descriptor_set_pool = vdd::FixedSizeDescriptorSetsPool::new(pipeline.clone(), 0);
|
||||||
|
|
||||||
|
Forward {
|
||||||
|
device,
|
||||||
|
|
||||||
|
pipeline,
|
||||||
|
descriptor_set_pool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pipeline for Forward {
|
||||||
|
fn get_pipeline(&self) -> Arc<VulkanoPipeline> {
|
||||||
|
self.pipeline.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_descriptor_set(&mut self, ubo: data::UniformBufferObject) -> Arc<VulkanoDescriptorSet> {
|
||||||
|
let buffer = vb::CpuAccessibleBuffer::from_data(
|
||||||
|
self.device.clone(),
|
||||||
|
vb::BufferUsage::uniform_buffer_transfer_destination(),
|
||||||
|
ubo,
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
Arc::new(self.descriptor_set_pool.next()
|
||||||
|
.add_buffer(buffer).unwrap()
|
||||||
|
.build().unwrap())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
use log;
|
use log;
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
|
@ -9,81 +8,17 @@ use runfiles::Runfiles;
|
||||||
use vulkano::descriptor::descriptor as vdd;
|
use vulkano::descriptor::descriptor as vdd;
|
||||||
use vulkano::descriptor::pipeline_layout as vdp;
|
use vulkano::descriptor::pipeline_layout as vdp;
|
||||||
use vulkano::device as vd;
|
use vulkano::device as vd;
|
||||||
use vulkano::format::Format;
|
|
||||||
use vulkano::framebuffer as vf;
|
|
||||||
use vulkano::pipeline as vp;
|
|
||||||
use vulkano::pipeline::shader as vps;
|
use vulkano::pipeline::shader as vps;
|
||||||
|
|
||||||
pub fn pipeline_forward(
|
pub struct ShaderDefinition {
|
||||||
device: Arc<vd::Device>,
|
pub name: String,
|
||||||
swap_chain_extent: [u32; 2],
|
pub ty: vps::GraphicsShaderType,
|
||||||
render_pass: Arc<dyn vf::RenderPassAbstract + Send + Sync>,
|
pub inputs: Vec<vps::ShaderInterfaceDefEntry>,
|
||||||
) -> Arc<dyn vp::GraphicsPipelineAbstract + Send + Sync> {
|
pub outputs: Vec<vps::ShaderInterfaceDefEntry>,
|
||||||
let vertex = ShaderDefinition {
|
|
||||||
name: "forward_vert.spv".to_string(),
|
|
||||||
ty: vps::GraphicsShaderType::Vertex,
|
|
||||||
inputs: vec![
|
|
||||||
vps::ShaderInterfaceDefEntry { location: 0..1, format: Format::R32G32B32Sfloat, name: Some(Cow::Borrowed("pos")) },
|
|
||||||
vps::ShaderInterfaceDefEntry { location: 1..2, format: Format::R32G32B32Sfloat, name: Some(Cow::Borrowed("color")) },
|
|
||||||
],
|
|
||||||
outputs: vec![
|
|
||||||
vps::ShaderInterfaceDefEntry { location: 0..1, format: Format::R32G32B32Sfloat, name: Some(Cow::Borrowed("fragColor")) }
|
|
||||||
],
|
|
||||||
}.load_into(device.clone()).expect("could not load vertex shader");
|
|
||||||
|
|
||||||
let fragment = ShaderDefinition {
|
|
||||||
name: "forward_frag.spv".to_string(),
|
|
||||||
ty: vps::GraphicsShaderType::Fragment,
|
|
||||||
inputs: vec![
|
|
||||||
vps::ShaderInterfaceDefEntry { location: 0..1, format: Format::R32G32B32Sfloat, name: Some(Cow::Borrowed("fragColor")) }
|
|
||||||
],
|
|
||||||
outputs: vec![
|
|
||||||
vps::ShaderInterfaceDefEntry { location: 0..1, format: Format::R32G32B32A32Sfloat, name: Some(Cow::Borrowed("outColor")) }
|
|
||||||
],
|
|
||||||
}.load_into(device.clone()).expect("could not load fragment shader");
|
|
||||||
|
|
||||||
let dimensions = [swap_chain_extent[0] as f32, swap_chain_extent[1] as f32];
|
|
||||||
let viewport = vp::viewport::Viewport {
|
|
||||||
origin: [0.0, 0.0],
|
|
||||||
dimensions,
|
|
||||||
depth_range: 0.0 .. 1.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Counter-clockwise facing triangles - this is because geometry data is left-handed,
|
|
||||||
// and the vertex shader performs a handedness flip by doing .y *= -1 on emitted
|
|
||||||
// vertices. To keep geomtry-space triangles clockwise after this transformation,
|
|
||||||
// the pipeline must be set to treat counter-clockwise triangles as front-facing.
|
|
||||||
// An alternative would be to fully embrace the vulkan coordinate system, including geometry -
|
|
||||||
// however this goes against most existing software and practices.
|
|
||||||
// This might bite us in the ass at some point in the future.
|
|
||||||
Arc::new(vp::GraphicsPipeline::start()
|
|
||||||
.vertex_input_single_buffer::<super::data::Vertex>()
|
|
||||||
.vertex_shader(vertex.entry_point(), ())
|
|
||||||
.triangle_list()
|
|
||||||
.primitive_restart(false)
|
|
||||||
.viewports(vec![viewport])
|
|
||||||
.fragment_shader(fragment.entry_point(), ())
|
|
||||||
.depth_clamp(false)
|
|
||||||
.polygon_mode_fill()
|
|
||||||
.line_width(1.0)
|
|
||||||
.cull_mode_back()
|
|
||||||
.front_face_counter_clockwise()
|
|
||||||
.blend_pass_through()
|
|
||||||
.render_pass(vf::Subpass::from(render_pass.clone(), 0).unwrap())
|
|
||||||
.build(device.clone())
|
|
||||||
.unwrap()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ShaderDefinition {
|
|
||||||
name: String,
|
|
||||||
ty: vps::GraphicsShaderType,
|
|
||||||
inputs: Vec<vps::ShaderInterfaceDefEntry>,
|
|
||||||
outputs: Vec<vps::ShaderInterfaceDefEntry>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ShaderDefinition {
|
impl ShaderDefinition {
|
||||||
fn load_into(self, device: Arc<vd::Device>) -> Result<LoadedShader, String> {
|
pub fn load_into(self, device: Arc<vd::Device>) -> Result<LoadedShader, String> {
|
||||||
fn stringify(x: std::io::Error) -> String { format!("IO error: {}", x) }
|
fn stringify(x: std::io::Error) -> String { format!("IO error: {}", x) }
|
||||||
|
|
||||||
let r = Runfiles::create().map_err(stringify)?;
|
let r = Runfiles::create().map_err(stringify)?;
|
||||||
|
@ -106,7 +41,7 @@ impl ShaderDefinition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LoadedShader {
|
pub struct LoadedShader {
|
||||||
def: ShaderDefinition,
|
def: ShaderDefinition,
|
||||||
module: Arc<vps::ShaderModule>,
|
module: Arc<vps::ShaderModule>,
|
||||||
}
|
}
|
||||||
|
@ -143,7 +78,7 @@ impl LoadedShader {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive (Debug, Clone)]
|
#[derive (Debug, Clone)]
|
||||||
struct ShaderLayout(vdd::ShaderStages);
|
pub struct ShaderLayout(vdd::ShaderStages);
|
||||||
|
|
||||||
unsafe impl vdp::PipelineLayoutDesc for ShaderLayout {
|
unsafe impl vdp::PipelineLayoutDesc for ShaderLayout {
|
||||||
fn num_sets(&self) -> usize { 1 }
|
fn num_sets(&self) -> usize { 1 }
|
||||||
|
@ -177,7 +112,7 @@ unsafe impl vdp::PipelineLayoutDesc for ShaderLayout {
|
||||||
fn push_constants_range(&self, _num: usize) -> Option<vdp::PipelineLayoutDescPcRange> { None }
|
fn push_constants_range(&self, _num: usize) -> Option<vdp::PipelineLayoutDescPcRange> { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ShaderInterface {
|
pub struct ShaderInterface {
|
||||||
entries: Vec<vps::ShaderInterfaceDefEntry>,
|
entries: Vec<vps::ShaderInterfaceDefEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,15 +123,15 @@ impl<WT: 'static + Send + Sync> SwapchainBinding<WT> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn choose_swap_present_mode(available_present_modes: vs::SupportedPresentModes) -> vs::PresentMode {
|
fn choose_swap_present_mode(available_present_modes: vs::SupportedPresentModes) -> vs::PresentMode {
|
||||||
//if available_present_modes.mailbox {
|
if available_present_modes.mailbox {
|
||||||
// vs::PresentMode::Mailbox
|
vs::PresentMode::Mailbox
|
||||||
//} else if available_present_modes.immediate {
|
} else if available_present_modes.immediate {
|
||||||
// vs::PresentMode::Immediate
|
vs::PresentMode::Immediate
|
||||||
//} else {
|
} else {
|
||||||
// vs::PresentMode::Fifo
|
|
||||||
//}
|
|
||||||
vs::PresentMode::Fifo
|
vs::PresentMode::Fifo
|
||||||
}
|
}
|
||||||
|
//vs::PresentMode::Fifo
|
||||||
|
}
|
||||||
|
|
||||||
fn choose_swap_extent(capabilities: &vs::Capabilities) -> [u32; 2] {
|
fn choose_swap_extent(capabilities: &vs::Capabilities) -> [u32; 2] {
|
||||||
capabilities.current_extent.expect("could not get current extent")
|
capabilities.current_extent.expect("could not get current extent")
|
||||||
|
|
Loading…
Reference in New Issue