Allow for more pipelines

This commit is contained in:
2020-11-27 08:35:27 +01:00
parent 9b6a81ae93
commit 483645dcc5
3 changed files with 232 additions and 151 deletions

View File

@@ -1,3 +1,5 @@
use crate::pipelines::{Drawcall, LineShader};
use crate::pipelines::DefaultShader;
use std::sync::Arc;
use std::time::SystemTime;
@@ -6,16 +8,13 @@ use image::{ImageBuffer, ImageFormat, Rgb, Rgba};
use image::buffer::ConvertBuffer;
use vulkano::{command_buffer::CommandBuffer, buffer::{BufferUsage, CpuAccessibleBuffer}, image::{ImageLayout, MipmapsCount}};
use vulkano::command_buffer::{AutoCommandBuffer, AutoCommandBufferBuilder, DynamicState};
use vulkano::descriptor::descriptor_set::PersistentDescriptorSet;
use vulkano::descriptor::DescriptorSet;
use vulkano::device::{Device, DeviceExtensions, Queue};
use vulkano::format::{ClearValue, Format};
use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, RenderPassAbstract, Subpass};
use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, RenderPassAbstract};
use vulkano::image::{AttachmentImage, Dimensions, ImageUsage, ImmutableImage, SwapchainImage, ImageViewAccess};
use vulkano::instance::{ApplicationInfo, Instance, InstanceExtensions, PhysicalDevice, Version};
use vulkano::instance::debug::{DebugCallback, MessageSeverity, MessageType};
use vulkano::memory::pool::{PotentialDedicatedAllocation, StdMemoryPoolAlloc};
use vulkano::pipeline::{GraphicsPipeline, GraphicsPipelineAbstract};
use vulkano::pipeline::viewport::Viewport;
use vulkano::sampler::{Filter, MipmapMode, Sampler, SamplerAddressMode};
use vulkano::swapchain::{AcquireError, ColorSpace, FullscreenExclusive, PresentMode, Surface, SurfaceTransform, Swapchain, SwapchainCreationError};
@@ -27,10 +26,11 @@ use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::{Window, WindowBuilder};
use line_vs::ty::LinePushConstants;
use vs::ty::PushConstants;
use crate::pipelines::{line_vs::ty::LinePushConstants};
use crate::pipelines::vs::ty::PushConstants;
use crate::gameobject::{GameObject, GameObjectHandle};
use crate::pipelines::vs;
use crate::{gameobject::{GameObject, GameObjectHandle}};
use crate::mesh::CPUMesh;
use crate::config::RenderConfig;
@@ -63,8 +63,8 @@ pub trait Game {
}
pub struct Mesh {
vertex_buffer: Arc<CpuAccessibleBuffer<[Vertex]>>,
index_buffer: Arc<CpuAccessibleBuffer<[u32]>>,
pub vertex_buffer: Arc<CpuAccessibleBuffer<[Vertex]>>,
pub index_buffer: Arc<CpuAccessibleBuffer<[u32]>>,
}
#[derive(Debug, Copy, Clone)]
@@ -98,9 +98,7 @@ pub struct VulkanRenderer {
pub framebuffers: Vec<Arc<dyn FramebufferAbstract + Send + Sync>>,
pub sampler: Arc<Sampler>,
pub dynamic_state: DynamicState,
pub pipeline: Arc<dyn GraphicsPipelineAbstract + Send + Sync>,
pub line_pipeline: Arc<dyn GraphicsPipelineAbstract + Send + Sync>,
pub line_vertex_buffer: Arc<CpuAccessibleBuffer<[LinePoint], PotentialDedicatedAllocation<StdMemoryPoolAlloc>>>,
pub pipelines: Vec<Box<dyn Drawcall>>,
pub surface: Arc<Surface<Window>>,
pub swapchain: Arc<Swapchain<Window>>,
pub render_pass: Arc<dyn RenderPassAbstract + Send + Sync>,
@@ -233,9 +231,6 @@ impl VulkanRenderer {
PresentMode::Fifo, FullscreenExclusive::Default, true, ColorSpace::SrgbNonLinear).unwrap()
};
// what is host_cached
let line_vertex_buffer = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::vertex_buffer(), false, data.line_vertices.iter().cloned()).unwrap();
// Render pass
let render_pass = Arc::new(vulkano::single_pass_renderpass!(
device.clone(),
@@ -272,10 +267,12 @@ impl VulkanRenderer {
MipmapMode::Nearest, SamplerAddressMode::Repeat, SamplerAddressMode::Repeat,
SamplerAddressMode::Repeat, 0.0, 1.0, 0.0, 0.0).unwrap();
let pipeline: Arc<dyn GraphicsPipelineAbstract + Send + Sync> =
create_pipeline::<Vertex>(device.clone(), render_pass.clone(), false).unwrap();
let line_pipeline: Arc<dyn GraphicsPipelineAbstract + Send + Sync> =
create_pipeline::<LinePoint>(device.clone(), render_pass.clone(), true).unwrap();
let line_vertex_buffer = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::vertex_buffer(), false, data.line_vertices.iter().cloned()).unwrap();
let pipelines: Vec<Box<dyn Drawcall>> = vec![
Box::new(DefaultShader::new(device.clone(), render_pass.clone())),
Box::new(LineShader::new(device.clone(), render_pass.clone(), line_vertex_buffer)),
];
let default_tex = {
let image = image::load_from_memory_with_format(include_bytes!("../models/missing-texture.jpg"),
@@ -337,8 +334,8 @@ impl VulkanRenderer {
let previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box<dyn GpuFuture>);
(VulkanRenderer { game_data: data, device, framebuffers, sampler,
dynamic_state, pipeline, line_pipeline, uniform_buffers,
surface, swapchain, render_pass, queue, line_vertex_buffer,
dynamic_state, pipelines, uniform_buffers,
surface, swapchain, render_pass, queue,
recreate_swapchain: false, debug_callback, previous_frame_end,
msaa_sample_count: render_config.msaa_samples
}, events_loop)
@@ -350,26 +347,11 @@ impl VulkanRenderer {
builder.update_buffer(self.uniform_buffers[fb_index].clone(), uniform_buffer_data).unwrap();
builder.begin_render_pass(self.framebuffers[fb_index].clone(), false, vec![ClearValue::None, ClearValue::Float([0.0, 0.0, 0.0, 1.0]), ClearValue::Depth(1.0)]).unwrap();
// Load and draw meshes etc.
for i in 0..self.game_data.game_objects.len() {
let game_object = &self.game_data.game_objects[i];
let mesh = &self.game_data.meshes[game_object.mesh_index];
self.game_data.push_constants.model = game_object.get_model_matrix().into();
builder.draw_indexed(
self.pipeline.clone(),
&self.dynamic_state,
vec![mesh.vertex_buffer.clone()],
mesh.index_buffer.clone(),
game_object.descriptor_sets[fb_index].clone(),
self.game_data.push_constants.clone()).unwrap();
// Draw meshes etc.
for pipeline in &self.pipelines {
pipeline.draw(&mut builder, fb_index, &self.game_data, &self.dynamic_state);
}
// Draw line grid
if self.game_data.use_line_pipeline {
builder.draw(self.line_pipeline.clone(), &self.dynamic_state, vec![self.line_vertex_buffer.clone()], (), self.game_data.line_push_constants.clone()).unwrap();
}
// General cleanup
builder.end_render_pass().unwrap();
Arc::new(builder.build().unwrap())
@@ -416,12 +398,9 @@ impl VulkanRenderer {
// recreate pipeline if requested
if self.game_data.recreate_pipeline {
if let Some(pipeline_ok) = create_pipeline::<Vertex>(self.device.clone(), self.render_pass.clone(), false) {
self.pipeline = pipeline_ok;
println!("Updated pipeline.");
} else {
println!("Failed to update pipeline.");
}
let device = self.device.clone();
let render_pass = self.render_pass.clone();
self.pipelines.iter_mut().for_each(|pipeline| pipeline.recreate_pipeline(device.clone(), render_pass.clone()));
self.game_data.recreate_pipeline = false;
}
@@ -523,27 +502,27 @@ impl VulkanRenderer {
).unwrap();
// Generate mipmaps
let mut mip_width = image_view.dimensions().width() as i32;
let mut mip_height = image_view.dimensions().height() as i32;
// let mut mip_width = image_view.dimensions().width() as i32;
// let mut mip_height = image_view.dimensions().height() as i32;
for i in 0..image_view.mipmap_levels() {
command_buffer_builder.blit_image(
image_view.clone(),
[0; 3],
[mip_width, mip_height, 1],
0,
i,
image_view.clone(),
[0; 3],
[mip_width / 2, mip_height / 2, 1],
0,
i + 1,
dimensions.array_layers_with_cube(),
Filter::Linear).unwrap();
// for i in 0..image_view.mipmap_levels() {
// command_buffer_builder.blit_image(
// image_view.clone(),
// [0; 3],
// [mip_width, mip_height, 1],
// 0,
// i,
// image_view.clone(),
// [0; 3],
// [mip_width / 2, mip_height / 2, 1],
// 0,
// i + 1,
// dimensions.array_layers_with_cube(),
// Filter::Linear).unwrap();
if mip_width > 1 { mip_width = mip_width / 2; }
if mip_height > 1 { mip_height = mip_height / 2; }
}
// if mip_width > 1 { mip_width = mip_width / 2; }
// if mip_height > 1 { mip_height = mip_height / 2; }
// }
let command_buffer = command_buffer_builder.build().unwrap();
let command_buffer_future = command_buffer.execute(self.queue.clone()).unwrap();
@@ -552,22 +531,8 @@ impl VulkanRenderer {
self.game_data.textures.push(image_view);
}
pub fn add_game_object(self: &mut Self, mut game_object: GameObject) -> GameObjectHandle {
let descriptor_set_layout = self.pipeline.descriptor_set_layout(0).unwrap().clone();
println!("Diff: {:?}, Norm: {:?}", game_object.texture_index, game_object.normal_map_index);
let descriptor_sets = self.uniform_buffers.iter().map(|uniform_buffer| {
let builder = PersistentDescriptorSet::start(descriptor_set_layout.clone());
let result: Arc<RendererDescriptorSets> = Arc::new(builder
.add_buffer(uniform_buffer.clone()).unwrap()
.add_sampled_image(self.game_data.textures[game_object.texture_index].clone(), self.sampler.clone()).unwrap()
.add_sampled_image(self.game_data.textures[game_object.normal_map_index].clone(), self.sampler.clone()).unwrap()
.build().unwrap());
result
}).collect();
game_object.descriptor_sets = descriptor_sets;
pub fn add_game_object(self: &mut Self, mut game_object: GameObject, pipeline_index: usize) -> GameObjectHandle {
self.pipelines[pipeline_index].create_descriptor_set(&mut game_object, self);
self.game_data.game_objects.push(game_object);
GameObjectHandle {
@@ -621,71 +586,4 @@ fn window_size_dependent_setup(device: Arc<Device>, images: &[Arc<SwapchainImage
}
framebuffers
}
pub mod vs {
vulkano_shaders::shader!{
ty: "vertex",
path: "shaders/triangle.vert"
}
}
pub mod line_vs {
vulkano_shaders::shader!{
ty: "vertex",
path: "shaders/line.vert"
}
}
pub mod fs {
vulkano_shaders::shader! {
ty: "fragment",
path: "shaders/triangle.frag"
}
}
pub mod line_fs {
vulkano_shaders::shader! {
ty: "fragment",
path: "shaders/line.frag"
}
}
fn create_pipeline<V: vulkano::pipeline::vertex::Vertex>(device: Arc<Device>, render_pass: Arc<dyn RenderPassAbstract + Send + Sync>, is_line: bool) -> Option<Arc<dyn GraphicsPipelineAbstract + Send + Sync>> {
let sub_pass = Subpass::from(render_pass.clone(), 0).unwrap();
let pipeline;
if is_line {
let vertex_shader = line_vs::Shader::load(device.clone()).unwrap();
let fragment_shader = line_fs::Shader::load(device.clone()).unwrap();
pipeline = Arc::new(GraphicsPipeline::start()
.vertex_input_single_buffer::<V>()
.vertex_shader(vertex_shader.main_entry_point(), ())
.line_list()
.viewports_dynamic_scissors_irrelevant(1)
.depth_stencil_simple_depth()
.fragment_shader(fragment_shader.main_entry_point(), ())
.render_pass(sub_pass.clone())
.build(device.clone())
.unwrap());
} else {
let vertex_shader = vs::Shader::load(device.clone()).unwrap();
let fragment_shader = fs::Shader::load(device.clone()).unwrap();
pipeline = Arc::new(GraphicsPipeline::start()
.vertex_input_single_buffer::<V>()
.vertex_shader(vertex_shader.main_entry_point(), ())
.triangle_list()
.viewports_dynamic_scissors_irrelevant(1)
.depth_stencil_simple_depth()
.fragment_shader(fragment_shader.main_entry_point(), ())
.blend_alpha_blending()
.cull_mode_back()
.render_pass(sub_pass.clone())
.build(device.clone())
.unwrap());
}
return Some(pipeline);
}
}