refactor: renderable
parent
8b82aeac1c
commit
86e5d03a91
|
@ -6,9 +6,11 @@ rust_binary(
|
|||
srcs = [
|
||||
"src/main.rs",
|
||||
"src/render/mod.rs",
|
||||
"src/render/renderable.rs",
|
||||
"src/render/vulkan/mod.rs",
|
||||
"src/render/vulkan/binding.rs",
|
||||
"src/render/vulkan/data.rs",
|
||||
"src/render/vulkan/pipeline.rs",
|
||||
"src/render/vulkan/qfi.rs",
|
||||
"src/render/vulkan/shaders.rs",
|
||||
"src/render/vulkan/swapchains.rs",
|
||||
|
|
|
@ -1,12 +1,35 @@
|
|||
use log;
|
||||
use env_logger;
|
||||
use std::sync::Arc;
|
||||
|
||||
use cgmath as cgm;
|
||||
|
||||
mod render;
|
||||
mod util;
|
||||
|
||||
use render::vulkan::data;
|
||||
use render::renderable::Renderable;
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
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();
|
||||
renderer.set_render_data(vec![demo.data().unwrap()]);
|
||||
renderer.main_loop();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ use vulkano_win::VkSurfaceBuild;
|
|||
use vulkano::instance as vi;
|
||||
use vulkano::swapchain as vs;
|
||||
|
||||
mod vulkan;
|
||||
pub mod vulkan;
|
||||
pub mod renderable;
|
||||
|
||||
const WIDTH: u32 = 800;
|
||||
const HEIGHT: u32 = 600;
|
||||
|
@ -20,6 +21,8 @@ const HEIGHT: u32 = 600;
|
|||
pub struct Renderer {
|
||||
instance: vulkan::Instance<winit::Window>,
|
||||
events_loop: EventsLoop,
|
||||
|
||||
render_data: Vec<renderable::Data>,
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
|
@ -31,9 +34,14 @@ impl Renderer {
|
|||
Self {
|
||||
instance,
|
||||
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>>) {
|
||||
let events_loop = EventsLoop::new();
|
||||
let surface = WindowBuilder::new()
|
||||
|
@ -45,7 +53,7 @@ impl Renderer {
|
|||
}
|
||||
|
||||
fn draw_frame(&mut self) {
|
||||
self.instance.flip();
|
||||
self.instance.flip(self.render_data.clone());
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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)]
|
||||
pub struct UniformBufferObject {
|
||||
pub model: cgm::Matrix4<f32>,
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::time;
|
||||
use log;
|
||||
|
||||
use cgmath as cgm;
|
||||
use cgmath::prelude::SquareMatrix;
|
||||
use vulkano::buffer as vb;
|
||||
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::pipeline as vp;
|
||||
use vulkano::swapchain as vs;
|
||||
use vulkano::sync::{FenceSignalFuture, GpuFuture};
|
||||
|
||||
mod binding;
|
||||
mod data;
|
||||
pub mod data;
|
||||
mod pipeline;
|
||||
mod qfi;
|
||||
mod shaders;
|
||||
mod swapchains;
|
||||
mod qfi;
|
||||
|
||||
use crate::render::renderable;
|
||||
|
||||
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>>,
|
||||
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,
|
||||
previous_frame_end: Option<Box<FlipFuture<WT>>>,
|
||||
fps_counter: crate::util::counter::Counter,
|
||||
|
@ -66,10 +64,8 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
|
|||
|
||||
surface_binding: None,
|
||||
swapchain_binding: None,
|
||||
command_buffers: vec![],
|
||||
uniform_buffers: vec![],
|
||||
descriptor_sets: vec![],
|
||||
|
||||
pipeline: None,
|
||||
previous_frame_end: None,
|
||||
armed: false,
|
||||
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 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.armed = true;
|
||||
}
|
||||
|
||||
|
||||
// (╯°□°)╯︵ ┻━┻
|
||||
pub fn flip(&mut self) {
|
||||
pub fn flip(
|
||||
&mut self,
|
||||
render_data: Vec<renderable::Data>,
|
||||
) {
|
||||
match &self.previous_frame_end {
|
||||
None => (),
|
||||
Some(future) => future.wait(None).unwrap(),
|
||||
|
@ -148,7 +129,9 @@ impl<WT: 'static + Send + Sync> Instance<WT> {
|
|||
},
|
||||
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 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] {
|
||||
let dimensions_u32 = self.swapchain_binding().chain.dimensions();
|
||||
[dimensions_u32[0] as f32, dimensions_u32[1] as f32]
|
||||
}
|
||||
|
||||
fn build_uniform_buffer(&self) -> data::UniformBufferObject {
|
||||
let elapsed = 40.0 as f32;
|
||||
fn make_command_buffer(
|
||||
&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 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(
|
||||
cgm::Point3::new(2.0, 2.0, 2.0),
|
||||
cgm::Point3::new(0.0, 0.0, 0.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)),
|
||||
dimensions[0] as f32 / dimensions[1] as f32,
|
||||
dimensions[0] / dimensions[1],
|
||||
0.1,
|
||||
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) {
|
||||
let mut buffers = Vec::new();
|
||||
|
||||
let uniform_buffer = self.build_uniform_buffer();
|
||||
for _ in 0..self.swapchain_binding().images.len() {
|
||||
let buffer = vb::CpuAccessibleBuffer::from_data(
|
||||
self.surface_binding().device.clone(),
|
||||
vb::BufferUsage::uniform_buffer_transfer_destination(),
|
||||
uniform_buffer,
|
||||
for d in render_data {
|
||||
let (vbuffer, future) = vb::immutable::ImmutableBuffer::from_iter(
|
||||
d.vertices.iter().cloned(),
|
||||
vb::BufferUsage::vertex_buffer(),
|
||||
self.surface_binding().graphics_queue.clone(),
|
||||
).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(
|
||||
&mut self,
|
||||
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();
|
||||
Arc::new(c.end_render_pass().unwrap()
|
||||
.build().unwrap())
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 std::borrow::Cow;
|
||||
use std::ffi::CStr;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
|
@ -9,81 +8,17 @@ use runfiles::Runfiles;
|
|||
use vulkano::descriptor::descriptor as vdd;
|
||||
use vulkano::descriptor::pipeline_layout as vdp;
|
||||
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;
|
||||
|
||||
pub fn pipeline_forward(
|
||||
device: Arc<vd::Device>,
|
||||
swap_chain_extent: [u32; 2],
|
||||
render_pass: Arc<dyn vf::RenderPassAbstract + Send + Sync>,
|
||||
) -> Arc<dyn vp::GraphicsPipelineAbstract + Send + Sync> {
|
||||
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>,
|
||||
pub struct ShaderDefinition {
|
||||
pub name: String,
|
||||
pub ty: vps::GraphicsShaderType,
|
||||
pub inputs: Vec<vps::ShaderInterfaceDefEntry>,
|
||||
pub outputs: Vec<vps::ShaderInterfaceDefEntry>,
|
||||
}
|
||||
|
||||
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) }
|
||||
|
||||
let r = Runfiles::create().map_err(stringify)?;
|
||||
|
@ -106,7 +41,7 @@ impl ShaderDefinition {
|
|||
}
|
||||
}
|
||||
|
||||
struct LoadedShader {
|
||||
pub struct LoadedShader {
|
||||
def: ShaderDefinition,
|
||||
module: Arc<vps::ShaderModule>,
|
||||
}
|
||||
|
@ -143,7 +78,7 @@ impl LoadedShader {
|
|||
}
|
||||
|
||||
#[derive (Debug, Clone)]
|
||||
struct ShaderLayout(vdd::ShaderStages);
|
||||
pub struct ShaderLayout(vdd::ShaderStages);
|
||||
|
||||
unsafe impl vdp::PipelineLayoutDesc for ShaderLayout {
|
||||
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 }
|
||||
}
|
||||
|
||||
struct ShaderInterface {
|
||||
pub struct ShaderInterface {
|
||||
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 {
|
||||
//if available_present_modes.mailbox {
|
||||
// vs::PresentMode::Mailbox
|
||||
//} else if available_present_modes.immediate {
|
||||
// vs::PresentMode::Immediate
|
||||
//} else {
|
||||
// vs::PresentMode::Fifo
|
||||
//}
|
||||
if available_present_modes.mailbox {
|
||||
vs::PresentMode::Mailbox
|
||||
} else if available_present_modes.immediate {
|
||||
vs::PresentMode::Immediate
|
||||
} else {
|
||||
vs::PresentMode::Fifo
|
||||
}
|
||||
//vs::PresentMode::Fifo
|
||||
}
|
||||
|
||||
fn choose_swap_extent(capabilities: &vs::Capabilities) -> [u32; 2] {
|
||||
capabilities.current_extent.expect("could not get current extent")
|
||||
|
|
Loading…
Reference in New Issue