diff --git a/Cargo.toml b/Cargo.toml index ac9a754..9588f42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,20 +6,20 @@ edition = "2018" default-run = "rust-engine" [dependencies] -vulkano-shaders = "0.20" -vulkano = "0.20" -vulkano-win = "0.20" -cgmath = "0.17.0" -winit = "0.24" -image = "0.23.6" -serde = "1.0.114" -serde_json = "1.0.59" -serde_derive = "1.0.114" -toml = "0.5.6" -gilrs = "0.7.4" -gltf = "0.15.2" +vulkano-shaders = "0.26" +vulkano = "0.26" +vulkano-win = "0.26" +cgmath = "0.18.0" +winit = "0.25" +image = "0.23" +serde = "1.0" +serde_json = "1.0" +serde_derive = "1.0" +toml = "0.5" +gilrs = "0.7" +gltf = "0.15" glyph_brush = "0.7" -winapi = "0.3.9" +winapi = "0.3" [profile.release] debug = 1 diff --git a/src/config.rs b/src/config.rs index 52fccc0..92cb1b3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,7 +1,8 @@ -use std::fs; +use std::{convert::TryInto, fs}; use serde_derive::{Deserialize, Serialize}; use toml; +use vulkano::image::SampleCount; #[derive(Debug, Serialize, Deserialize, Clone, Copy)] pub struct LogConfigInput { @@ -33,4 +34,8 @@ impl RenderConfig { pub fn from_file(path: &str) -> Self { toml::from_slice(&fs::read(path).expect("Failed to read render config!")).expect("Failed to parse render config!") } + + pub fn get_msaa(&self) -> Option { + if self.msaa_samples > 0 { self.msaa_samples.try_into().ok() } else { None } + } } \ No newline at end of file diff --git a/src/game/entities.rs b/src/game/entities.rs index b289c42..bb0b825 100644 --- a/src/game/entities.rs +++ b/src/game/entities.rs @@ -58,7 +58,7 @@ impl UiQuad { } impl Updatable for UiQuad { - fn update(&mut self, delta_time: f32, input: &InputState, game_state: &mut GameState, game_objects: &mut Vec, renderer: &mut VulkanRenderer) { + fn update(&mut self, _delta_time: f32, _input: &InputState, _game_state: &mut GameState, _game_objects: &mut Vec, _renderer: &mut VulkanRenderer) { } } \ No newline at end of file diff --git a/src/game/player.rs b/src/game/player.rs index eeb7c04..0a1ab3e 100644 --- a/src/game/player.rs +++ b/src/game/player.rs @@ -55,10 +55,6 @@ impl Camera { self.proj.y.y *= -1.0; self.ortho_proj = cgmath::ortho(0., width, 0., height, -1., 1.); - - // Upload - renderer.game_data.line_push_constants.view = self.view.into(); - renderer.game_data.line_push_constants.projection = self.proj.into(); } pub fn viewport_pos_to_ray_direction(&self, viewport_pos: Vector2, viewport_dimensions: [u32; 2]) -> Option> { @@ -135,9 +131,9 @@ pub fn intersection_distance(ray_origin: Vector3, ray_direction: Vector3 {}, Err(BrushError::TextureTooSmall { suggested }) => { - let size = Dimensions::Dim2d { width: suggested.0, height: suggested.1 }; + let size = ImageDimensions::Dim2d { width: suggested.0, height: suggested.1, array_layers: 1 }; debug_assert!(go.textures.len() == 1); renderer.resize_texture(go, go.textures[0], size); brush.resize_texture(suggested.0, suggested.1); @@ -70,7 +70,7 @@ pub fn update_text_texture(old_texture: Option, renderer: &mut Vu renderer.update_texture(tex_handle, text_data, [rect.width(), rect.height(), 1], [rect.min[0], rect.min[1], 0], renderer.device.clone()); None } else { - let tex = renderer.upload_texture(text_data, size, size, Format::R8Unorm, Filter::Nearest, SamplerAddressMode::ClampToEdge, renderer.device.clone()); + let tex = renderer.upload_texture(text_data, size, size, Format::R8_UNORM, Filter::Nearest, SamplerAddressMode::ClampToEdge, renderer.device.clone()); renderer.game_data.textures.push(tex.clone()); Some(renderer.game_data.textures.len() - 1) } diff --git a/src/vulkan/dds.rs b/src/vulkan/dds.rs index eac6576..c570724 100644 --- a/src/vulkan/dds.rs +++ b/src/vulkan/dds.rs @@ -25,12 +25,12 @@ pub fn upload_texture_from_file(path: &str, renderer: &mut VulkanRenderer) -> Re println!("Texture width: {}, height: {}, bytes: {}", tex_width, tex_height, tex_byte_count); let texture = if is_dxt1 { - renderer.upload_texture(&tex_bytes[128..], tex_width, tex_height, Format::BC1_RGBUnormBlock, Filter::Linear, SamplerAddressMode::Repeat, renderer.device.clone()) + renderer.upload_texture(&tex_bytes[128..], tex_width, tex_height, Format::BC1_RGB_UNORM_BLOCK, Filter::Linear, SamplerAddressMode::Repeat, renderer.device.clone()) } else if is_dx10 { let dxgi_type = u32::from_ne_bytes(tex_bytes[128..132].try_into()?); assert!(dxgi_type == 83); // BC5 Unorm Typeless - renderer.upload_texture(&tex_bytes[128+20..], tex_width, tex_height, Format::BC5UnormBlock, Filter::Linear, SamplerAddressMode::Repeat, renderer.device.clone()) + renderer.upload_texture(&tex_bytes[128+20..], tex_width, tex_height, Format::BC5_UNORM_BLOCK, Filter::Linear, SamplerAddressMode::Repeat, renderer.device.clone()) } else { panic!("Unknown texture type!"); }; @@ -40,8 +40,8 @@ pub fn upload_texture_from_file(path: &str, renderer: &mut VulkanRenderer) -> Re pub fn get_block_size(format: Format) -> Option { match format { - Format::BC1_RGBUnormBlock => Some(8), - Format::BC5UnormBlock => Some(16), + Format::BC1_RGB_UNORM_BLOCK => Some(8), + Format::BC5_UNORM_BLOCK => Some(16), _ => None } } \ No newline at end of file diff --git a/src/vulkan/framebuffers.rs b/src/vulkan/framebuffers.rs index 768b428..f76e237 100644 --- a/src/vulkan/framebuffers.rs +++ b/src/vulkan/framebuffers.rs @@ -1,11 +1,11 @@ use std::sync::Arc; -use vulkano::command_buffer::DynamicState; use vulkano::device::Device; use vulkano::format::Format; -use vulkano::framebuffer::{Framebuffer, FramebufferAbstract, RenderPassAbstract}; -use vulkano::image::{AttachmentImage, ImageUsage, SwapchainImage}; +use vulkano::image::view::ImageView; +use vulkano::image::{AttachmentImage, ImageUsage, SampleCount, SwapchainImage}; use vulkano::pipeline::viewport::Viewport; +use vulkano::render_pass::{Framebuffer, FramebufferAbstract, RenderPass}; use winit::window::Window; use vulkano::swapchain::Swapchain; @@ -13,29 +13,21 @@ use vulkano::swapchain::Swapchain; pub fn create_framebuffers(device: Arc, swapchain: &Arc>, images: &[Arc>], - msaa_sample_count: u32, - render_pass: Arc, - dynamic_state: &mut DynamicState) + msaa_sample_count: Option, + render_pass: Arc) -> Vec> { let dim_array = images[0].dimensions(); - let dim_array_f32 = [dim_array[0] as f32, dim_array[1] as f32]; - let viewport = Viewport { - origin: [0.0, 0.0], - dimensions: dim_array_f32, - depth_range: 0.0..1.0, - }; - dynamic_state.viewports = Some(vec!(viewport)); - - let depth_image = if msaa_sample_count > 0 { - AttachmentImage::multisampled_with_usage(device.clone(), dim_array, msaa_sample_count, Format::D16Unorm, ImageUsage { depth_stencil_attachment: true, ..ImageUsage::none() }).unwrap() + let depth_image = if let Some(sample_count) = msaa_sample_count { + AttachmentImage::multisampled_with_usage(device.clone(), dim_array, sample_count, Format::D16_UNORM, ImageUsage { depth_stencil_attachment: true, ..ImageUsage::none() }).unwrap() } else { - AttachmentImage::with_usage(device.clone(), dim_array, Format::D16Unorm, ImageUsage { depth_stencil_attachment: true, ..ImageUsage::none() }).unwrap() + AttachmentImage::with_usage(device.clone(), dim_array, Format::D16_UNORM, ImageUsage { depth_stencil_attachment: true, ..ImageUsage::none() }).unwrap() }; + let depth_image_view = ImageView::new(depth_image.clone()).unwrap(); - let msaa_buffers = if msaa_sample_count > 0 { - Some(create_msaa_buffers(device.clone(), dim_array, swapchain, msaa_sample_count)) + let msaa_buffers = if let Some(sample_count) = msaa_sample_count { + Some(create_msaa_buffers(device.clone(), dim_array, swapchain, sample_count)) } else { None }; @@ -44,18 +36,21 @@ pub fn create_framebuffers(device: Arc, for i in 0..images.len() { let image_buffer = &images[i]; + let view = ImageView::new(image_buffer.clone()).unwrap(); if let Some(msaa_buffers_exist) = &msaa_buffers { + let msaa_view = ImageView::new((&msaa_buffers_exist[i]).clone()).unwrap(); + framebuffers.push(Arc::new(Framebuffer::start(render_pass.clone()) - .add(image_buffer.clone()).unwrap() - .add((&msaa_buffers_exist[i]).clone()).unwrap() - .add(depth_image.clone()).unwrap() + .add(view).unwrap() + .add(msaa_view).unwrap() + .add(depth_image_view.clone()).unwrap() .build().unwrap() ) as Arc); } else { framebuffers.push(Arc::new(Framebuffer::start(render_pass.clone()) - .add(image_buffer.clone()).unwrap() - .add(depth_image.clone()).unwrap() + .add(view).unwrap() + .add(depth_image_view.clone()).unwrap() .build().unwrap() ) as Arc); } @@ -64,7 +59,7 @@ pub fn create_framebuffers(device: Arc, framebuffers } -fn create_msaa_buffers(device: Arc, dimensions: [u32; 2], swapchain: &Arc>, sample_count: u32) -> Vec> { +fn create_msaa_buffers(device: Arc, dimensions: [u32; 2], swapchain: &Arc>, sample_count: SampleCount) -> Vec> { let mut msaa_attachments = vec![]; for _ in 0..swapchain.num_images() { msaa_attachments.push(AttachmentImage::transient_multisampled(device.clone(), dimensions, sample_count, swapchain.format()).unwrap()); diff --git a/src/vulkan/gameobject.rs b/src/vulkan/gameobject.rs index 728fe04..3cb5298 100644 --- a/src/vulkan/gameobject.rs +++ b/src/vulkan/gameobject.rs @@ -1,13 +1,18 @@ use std::sync::Arc; use cgmath::{Deg, Euler, Matrix4, Quaternion, Vector3}; +use vulkano::descriptor_set::PersistentDescriptorSet; use crate::game::GameState; use crate::input::InputState; -use crate::vulkan::{RendererDescriptorSets, TextureHandle}; +use crate::vulkan::TextureHandle; use crate::vulkan::{MeshHandle, VulkanRenderer}; -use super::pipelines::vs; +use super::pipelines::{vs, vs_text}; + +pub trait PushConstant {} +impl PushConstant for vs::ty::PushConstants {} +impl PushConstant for vs_text::ty::PushConstants {} #[derive(Clone)] pub struct GameObject { @@ -17,7 +22,7 @@ pub struct GameObject { pub rotation: Quaternion, pub scale: Vector3, pub children: Vec, - pub descriptor_sets: Vec>>, + pub descriptor_sets: Vec>>, pub is_selected: bool, pub pipeline_index: usize, pub visible: bool, @@ -60,11 +65,11 @@ impl GameObject { self.rotation = self.rotation * Quaternion::from(Euler::new(Deg(x), Deg(y), Deg(z))); } - pub fn get_push_constants(&self) -> vs::ty::PushConstants { - vs::ty::PushConstants { + pub fn get_push_constants(&self) -> Box { + Box::new(vs::ty::PushConstants { model: self.get_model_matrix().into(), is_selected: if self.is_selected { 1 } else { 0 }, - } + }) } pub fn get_model_matrix(&self) -> Matrix4 { diff --git a/src/vulkan/mod.rs b/src/vulkan/mod.rs index 2e5e77d..8ad6bb4 100644 --- a/src/vulkan/mod.rs +++ b/src/vulkan/mod.rs @@ -3,14 +3,15 @@ use std::time::SystemTime; use cgmath::{Matrix4, SquareMatrix}; use dds::get_block_size; -use vulkano::{buffer::{BufferUsage, CpuAccessibleBuffer}, command_buffer::{CommandBuffer, SubpassContents}, image::{ImageAccess, ImageLayout, ImageUsage, MipmapsCount, immutable::SubImage}}; -use vulkano::command_buffer::{AutoCommandBuffer, AutoCommandBufferBuilder, DynamicState}; -use vulkano::descriptor::DescriptorSet; -use vulkano::device::{Device, DeviceExtensions, Queue}; +use vulkano::device::physical::PhysicalDevice; +use vulkano::pipeline::viewport::Viewport; +use vulkano::render_pass::{FramebufferAbstract, RenderPass}; +use vulkano::{buffer::{BufferUsage, CpuAccessibleBuffer}, command_buffer::SubpassContents, image::{ImageAccess, ImageLayout, ImageUsage, MipmapsCount, immutable::SubImage}}; +use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer, PrimaryCommandBuffer}; +use vulkano::device::{Device, DeviceExtensions, Features, Queue}; use vulkano::format::{ClearValue, Format}; -use vulkano::framebuffer::{RenderPassAbstract, FramebufferAbstract}; -use vulkano::image::{Dimensions, ImmutableImage}; -use vulkano::instance::{ApplicationInfo, Instance, InstanceExtensions, PhysicalDevice, Version}; +use vulkano::image::{ImageCreateFlags, ImageDimensions, ImmutableImage}; +use vulkano::instance::{ApplicationInfo, Instance, InstanceExtensions, Version}; use vulkano::instance::debug::{DebugCallback, MessageSeverity, MessageType}; use vulkano::sampler::{Filter, MipmapMode, Sampler, SamplerAddressMode}; use vulkano::swapchain::{AcquireError, FullscreenExclusive, PresentMode, Surface, SurfaceTransform, Swapchain, SwapchainCreationError}; @@ -20,13 +21,12 @@ use vulkano::sync; use vulkano_win::VkSurfaceBuild; use winit::event::{Event, WindowEvent}; use winit::event_loop::{ControlFlow, EventLoop}; -use winit::window::{Window, WindowBuilder}; use mesh::CPUMesh; use pipelines::{Drawcall}; -use pipelines::line_vs::ty::LinePushConstants; use pipelines::{DefaultShader, TextShader}; use pipelines::vs; +use winit::window::{Window, WindowBuilder}; use crate::config::RenderConfig; use crate::vulkan::gameobject::GameObject; @@ -100,14 +100,12 @@ pub struct MeshHandle { pub(crate) type TextureHandle = usize; #[derive(Debug, Clone)] pub struct Texture { - pub image: Arc>, + pub image: Arc, pub sampler: Arc } pub struct GameData { pub start_time: SystemTime, - pub line_vertices: Vec, - pub line_push_constants: LinePushConstants, pub recreate_pipeline: bool, pub dimensions: [u32; 2], pub shutdown: bool, @@ -121,38 +119,30 @@ pub struct GameData { pub performance_counter_index: usize, } -pub(crate) type RendererDescriptorSets = dyn DescriptorSet + Send + Sync; - pub struct VulkanRenderer { pub game_data: GameData, pub device: Arc, pub framebuffers: Vec>, - pub dynamic_state: DynamicState, pub pipelines: Vec>, pub surface: Arc>, pub swapchain: Arc>, - pub render_pass: Arc, + pub render_pass: Arc, pub queue: Arc, pub recreate_swapchain: bool, pub debug_callback: Option, pub previous_frame_end: Option>, pub uniform_buffers: Vec>>, - pub render_config: RenderConfig + pub render_config: RenderConfig, + pub viewport: Viewport } impl VulkanRenderer { - pub fn init(line_vertices: Vec, enable_validation_layers: bool, render_config: RenderConfig) -> (VulkanRenderer, EventLoop<()>) { + pub fn init(enable_validation_layers: bool, render_config: RenderConfig) -> (VulkanRenderer, EventLoop<()>) { // Create empty game data struct to be filled let mut data = GameData { - line_push_constants: LinePushConstants { - model: Matrix4::identity().into(), - view: Matrix4::identity().into(), - projection: Matrix4::identity().into(), - }, start_time: SystemTime::now(), recreate_pipeline: false, shutdown: false, - line_vertices, dimensions: [0, 0], meshes: vec![], meshes_text: vec![], @@ -190,9 +180,9 @@ impl VulkanRenderer { } }); - Instance::new(Some(&app_info), &extensions, VALIDATION_LAYERS.iter().cloned()).expect("failed to create Vulkan instance") + Instance::new(Some(&app_info), Version::V1_1, &extensions, VALIDATION_LAYERS.iter().cloned()).expect("failed to create Vulkan instance") } else { - Instance::new(Some(&app_info), &extensions, None).expect("failed to create Vulkan instance") + Instance::new(Some(&app_info), Version::V1_1, &extensions, None).expect("failed to create Vulkan instance") } }; @@ -224,13 +214,12 @@ impl VulkanRenderer { let layer_str = msg.layer_prefix; - println!("[{}][{}]: {}", type_str, layer_str, msg.description); + println!("[{}][{}]: {}", type_str, layer_str.unwrap_or(""), msg.description); }).ok(); } // TODO: Create device selector let physical = PhysicalDevice::enumerate(&instance).next().unwrap(); - println!("Using device: {} (type: {:?})", physical.name(), physical.ty()); let events_loop = EventLoop::new(); let surface = WindowBuilder::new().build_vk_surface(&events_loop, instance.clone()).unwrap(); @@ -242,7 +231,7 @@ impl VulkanRenderer { }).unwrap(); let device_ext = DeviceExtensions { khr_swapchain: true, ..DeviceExtensions::none() }; - let (device, mut queues) = Device::new(physical, physical.supported_features(), &device_ext, + let (device, mut queues) = Device::new(physical, &Features::none(), &device_ext, [(queue_family, 0.5)].iter().cloned()).unwrap(); let queue = queues.next().unwrap(); @@ -255,9 +244,27 @@ impl VulkanRenderer { let inner_size = window.inner_size(); data.dimensions = [inner_size.width, inner_size.height]; - Swapchain::new(device.clone(), surface.clone(), caps.min_image_count, format, - data.dimensions, 1, usage, &queue, SurfaceTransform::Identity, alpha, - PresentMode::Fifo, FullscreenExclusive::Default, true, color_space).unwrap() + Swapchain::start(device.clone(), surface.clone()) + .num_images(caps.min_image_count) + .format(format) + .dimensions(data.dimensions) + .layers(1) + .usage(usage) + .sharing_mode(&queue) + .transform(SurfaceTransform::Identity) + .composite_alpha(alpha) + .present_mode(PresentMode::Fifo) + .fullscreen_exclusive(FullscreenExclusive::Default) + .clipped(true) + .color_space(color_space) + .build().unwrap() + }; + + let size = images[0].dimensions().width_height(); + let viewport = Viewport { + origin: [0.0, 0.0], + dimensions: [size[0] as f32, size[1] as f32], + depth_range: 0.0..1.0, }; // Render pass @@ -269,15 +276,9 @@ impl VulkanRenderer { Box::new(TextShader::new(device.clone(), render_pass_text.clone())), ]; - // Dynamic viewports allow us to recreate just the viewport when the window is resized - // Otherwise we would have to recreate the whole pipeline. - let mut dynamic_state = DynamicState { line_width: None, viewports: None, scissors: None, compare_mask: None, write_mask: None, reference: None }; - - - // The render pass we created above only describes the layout of our framebuffers. Before we // can draw we also need to create the actual framebuffers. - let framebuffers = framebuffers::create_framebuffers(device.clone(), &swapchain, &images, render_config.msaa_samples, render_pass.clone(), &mut dynamic_state); + let framebuffers = framebuffers::create_framebuffers(device.clone(), &swapchain, &images, render_config.get_msaa(), render_pass.clone()); let mut uniform_buffers = Vec::new(); let uniform_buffer = vs::ty::ObjectUniformData { @@ -311,28 +312,30 @@ impl VulkanRenderer { let previous_frame_end = Some(Box::new(sync::now(device.clone())) as Box); (VulkanRenderer { game_data: data, device, framebuffers, - dynamic_state, pipelines, uniform_buffers, + pipelines, uniform_buffers, surface, swapchain, render_pass, queue, recreate_swapchain: false, debug_callback, previous_frame_end, - render_config, + render_config, viewport }, events_loop) } - fn create_command_buffer(self: &mut Self, fb_index: usize, uniform_buffer_data: vs::ty::ObjectUniformData, game_objects: &Vec) -> Arc { + fn create_command_buffer(self: &mut Self, fb_index: usize, uniform_buffer_data: vs::ty::ObjectUniformData, game_objects: &Vec) -> Arc { // General setup - let mut builder = AutoCommandBufferBuilder::primary_simultaneous_use(self.device.clone(), self.queue.family()).unwrap(); - builder.update_buffer(self.uniform_buffers[fb_index].clone(), uniform_buffer_data).unwrap(); + let mut builder = AutoCommandBufferBuilder::primary(self.device.clone(), self.queue.family(), CommandBufferUsage::OneTimeSubmit).unwrap(); + // builder.update_buffer(self.uniform_buffers[fb_index].clone(), uniform_buffer_data).unwrap(); if self.render_config.msaa_samples > 0 { builder.begin_render_pass(self.framebuffers[fb_index].clone(), SubpassContents::Inline, vec![ClearValue::None, ClearValue::Float([0.0, 0.0, 0.0, 1.0]), ClearValue::Depth(1.0)]).unwrap(); } else { builder.begin_render_pass(self.framebuffers[fb_index].clone(), SubpassContents::Inline, vec![ClearValue::Float([0.0, 0.0, 0.0, 1.0]), ClearValue::Depth(1.0)]).unwrap(); } + builder.set_viewport(0, [self.viewport.clone()]); + // Draw meshes etc. let mut index = 0; for pipeline in &self.pipelines { let objects = game_objects.iter().filter(|go| go.visible && go.pipeline_index == index).collect(); - pipeline.draw(&mut builder, fb_index, objects, &self.game_data, &self.dynamic_state); + pipeline.draw(&mut builder, fb_index, objects, &self.game_data); index += 1; } @@ -353,7 +356,7 @@ impl VulkanRenderer { let inner_size = window.inner_size(); self.game_data.dimensions = [inner_size.width, inner_size.height]; - let (new_swapchain, new_images) = match self.swapchain.recreate_with_dimensions(self.game_data.dimensions) { + let (new_swapchain, new_images) = match self.swapchain.recreate().dimensions(self.game_data.dimensions).build() { Ok(r) => r, // This error tends to happen when the user is manually resizing the window. // Simply restarting the loop is the easiest way to fix this issue. @@ -364,6 +367,14 @@ impl VulkanRenderer { Err(err) => panic!("{:?}", err), }; + let size = new_images[0].dimensions().width_height(); + + self.viewport = Viewport { + origin: [0.0, 0.0], + dimensions: [size[0] as f32, size[1] as f32], + depth_range: 0.0..1.0, + }; + self.render_pass = renderpass::create_render_pass(self.device.clone(), &self.render_config, new_swapchain.format()); self.pipelines = vec![ @@ -374,7 +385,7 @@ impl VulkanRenderer { self.swapchain = new_swapchain; // Because framebuffers contains an Arc on the old swapchain, we need to // recreate framebuffers as well. - self.framebuffers = framebuffers::create_framebuffers(self.device.clone(), &self.swapchain, &new_images, self.render_config.msaa_samples, self.render_pass.clone(), &mut self.dynamic_state); + self.framebuffers = framebuffers::create_framebuffers(self.device.clone(), &self.swapchain, &new_images, self.render_config.get_msaa(), self.render_pass.clone()); self.recreate_swapchain = false; } @@ -473,7 +484,7 @@ impl VulkanRenderer { } pub fn upload_texture(self: &mut Self, bytes: &[u8], width: u32, height: u32, format: Format, filter: Filter, wrap: SamplerAddressMode, device: Arc) -> Texture { - let dimensions = Dimensions::Dim2d { width, height }; + let dimensions = ImageDimensions::Dim2d { width, height, array_layers: 1 }; let usage = ImageUsage { transfer_destination: true, @@ -482,7 +493,7 @@ impl VulkanRenderer { ..ImageUsage::none() }; - let mip_maps = if format == Format::R8Uint { MipmapsCount::One } else { MipmapsCount::Log2 }; + let mip_maps = if format == Format::R8_UINT { MipmapsCount::One } else { MipmapsCount::Log2 }; let (image_view, initializer) = ImmutableImage::uninitialized( device.clone(), @@ -490,6 +501,7 @@ impl VulkanRenderer { format, mip_maps, usage, + ImageCreateFlags::default(), ImageLayout::ShaderReadOnlyOptimal, device.active_queue_families(), ).unwrap(); @@ -503,7 +515,7 @@ impl VulkanRenderer { ImageLayout::ShaderReadOnlyOptimal, ); - let mut cbb = AutoCommandBufferBuilder::new(device.clone(), self.queue.family()).unwrap(); + let mut cbb = AutoCommandBufferBuilder::primary(device.clone(), self.queue.family(), CommandBufferUsage::OneTimeSubmit).unwrap(); let mut offset = 0; @@ -523,7 +535,7 @@ impl VulkanRenderer { [0, 0, 0], mip_size, 0, - dimensions.array_layers_with_cube(), + dimensions.array_layers(), mip_index, ).unwrap(); }; @@ -531,7 +543,7 @@ impl VulkanRenderer { if let Some(block_byte_size) = block_bytes { for i in 0..image_view.mipmap_levels() { - let mip_size = dimensions.to_image_dimensions().mipmap_dimensions(i).unwrap().width_height_depth(); + let mip_size = dimensions.mipmap_dimensions(i).unwrap().width_height_depth(); let mip_byte_size = ( (u32::max(4, mip_size[0]) / 4) @@ -545,7 +557,7 @@ impl VulkanRenderer { } else { let mut texture_bytes: Vec = bytes.to_vec(); texture_bytes.resize((width * height) as usize, 0u8); - upload_bytes(&texture_bytes, 0, dimensions.to_image_dimensions().width_height_depth()); + upload_bytes(&texture_bytes, 0, dimensions.width_height_depth()); } let cb = cbb.build().unwrap(); @@ -576,7 +588,7 @@ impl VulkanRenderer { ImageLayout::ShaderReadOnlyOptimal, ); - let mut cbb = AutoCommandBufferBuilder::new(device.clone(), self.queue.family()).unwrap(); + let mut cbb = AutoCommandBufferBuilder::primary(device.clone(), self.queue.family(), CommandBufferUsage::OneTimeSubmit).unwrap(); let upload_source = CpuAccessibleBuffer::from_iter( device.clone(), @@ -602,7 +614,7 @@ impl VulkanRenderer { future.flush().unwrap(); } - pub fn resize_texture(&mut self, game_object: &mut GameObject, texture_handle: TextureHandle, new_size: Dimensions) { + pub fn resize_texture(&mut self, game_object: &mut GameObject, texture_handle: TextureHandle, new_size: ImageDimensions) { let mut texture = &mut self.game_data.textures[texture_handle]; let new_image_usage = ImageUsage { @@ -618,6 +630,7 @@ impl VulkanRenderer { texture.image.format(), texture.image.mipmap_levels(), new_image_usage, + ImageCreateFlags::default(), ImageLayout::ShaderReadOnlyOptimal, self.device.active_queue_families(), ).unwrap(); @@ -640,7 +653,7 @@ impl VulkanRenderer { ImageLayout::ShaderReadOnlyOptimal, ); - let mut cbb = AutoCommandBufferBuilder::new(self.device.clone(), self.queue.family()).unwrap(); + let mut cbb = AutoCommandBufferBuilder::primary(self.device.clone(), self.queue.family(), CommandBufferUsage::OneTimeSubmit).unwrap(); cbb.copy_image( old_sub_image.clone(), diff --git a/src/vulkan/pipelines.rs b/src/vulkan/pipelines.rs index 38ac76a..faf02d5 100644 --- a/src/vulkan/pipelines.rs +++ b/src/vulkan/pipelines.rs @@ -1,27 +1,22 @@ use std::{convert::TryInto, io::{self, ErrorKind, Read, Write}, path::PathBuf, sync::Arc}; -use vulkano::{command_buffer::AutoCommandBufferBuilder, descriptor::{DescriptorSet, descriptor::ShaderStages, descriptor_set::PersistentDescriptorSet, pipeline_layout::PipelineLayoutDesc}, pipeline::{shader::{ShaderModule}}}; -use vulkano::command_buffer::DynamicState; +use vulkano::{buffer::TypedBufferAccess, command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer}, descriptor_set::PersistentDescriptorSet, image::view::ImageView, pipeline::{PipelineBindPoint, shader::ShaderModule}, render_pass::{RenderPass, Subpass}}; use vulkano::device::Device; -use vulkano::framebuffer::RenderPassAbstract; -use vulkano::framebuffer::Subpass; use vulkano::pipeline::GraphicsPipeline; -use vulkano::pipeline::GraphicsPipelineAbstract; -use vulkano::pipeline::shader::GraphicsShaderType; -use crate::{GameObject, vulkan::{TextVertex}}; -use crate::vulkan::{LinePoint, Vertex}; +use crate::{GameObject, vulkan::TextVertex}; +use crate::vulkan::Vertex; use crate::vulkan::GameData; use crate::VulkanRenderer; use super::TextureHandle; -type RP = Arc; -type GP = Arc; -type DS = Arc; +type RP = Arc; +type GP = Arc; +type DS = Arc; pub trait Drawcall { - fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_objects: Vec<&GameObject>, game_data: &GameData, dynamic_state: &DynamicState); + fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_objects: Vec<&GameObject>, game_data: &GameData); fn create_descriptor_sets(self: &Self, textures: &Vec, renderer: &VulkanRenderer) -> Vec>; fn recreate_pipeline(self: &mut Self, device: Arc, render_pass: RP); fn get_pipeline(self: &Self) -> &GP; @@ -46,7 +41,7 @@ pub struct DefaultShader { pipeline: GP, } -fn shader_module_from_file(device: Arc, path: &str) -> Arc { +fn _shader_module_from_file(device: Arc, path: &str) -> Arc { let mut file = std::fs::File::open(path).unwrap(); let mut buffer = vec![]; file.read_to_end(&mut buffer).unwrap(); @@ -105,11 +100,12 @@ impl DefaultShader { } unsafe { + /* static ENTRY_NAME: [u8; 5usize] = [109u8, 97u8, 105u8, 110u8, 0]; let entry_name_c = std::ffi::CStr::from_ptr(ENTRY_NAME.as_ptr() as *const _); let fs_module = shader_module_from_file(device.clone(), "shaders/triangle.frag.spv"); - let fs_layout = fs::Layout(ShaderStages { + let fs_layout = fs::MainLayout(ShaderStages { fragment: true, ..ShaderStages::none() }); @@ -121,14 +117,17 @@ impl DefaultShader { ..ShaderStages::none() }); let vs_entry = vs_module.graphics_entry_point(entry_name_c, vs::MainInput, vs::MainOutput, vs_layout, GraphicsShaderType::Vertex); - + */ + let vs = vs::Shader::load(device.clone()).unwrap(); + let fs = fs::Shader::load(device.clone()).unwrap(); + Arc::new(GraphicsPipeline::start() .vertex_input_single_buffer::() - .vertex_shader(vs_entry, ()) + .vertex_shader(vs.main_entry_point(), ()) .triangle_list() .viewports_dynamic_scissors_irrelevant(1) .depth_stencil_simple_depth() - .fragment_shader(fs_entry, ()) + .fragment_shader(fs.main_entry_point(), ()) .blend_alpha_blending() .cull_mode_back() .render_pass(sub_pass.clone()) @@ -139,39 +138,39 @@ impl DefaultShader { } impl Drawcall for DefaultShader { - fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_objects: Vec<&GameObject>, game_data: &GameData, dynamic_state: &DynamicState) { + fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_objects: Vec<&GameObject>, game_data: &GameData) { for i in 0..game_objects.len() { let game_object = &game_objects[i]; let mesh = &game_data.meshes[game_object.mesh_index]; let push_constants = game_object.get_push_constants(); - builder.draw_indexed( - self.pipeline.clone(), - dynamic_state, - vec![mesh.vertex_buffer.clone()], - mesh.index_buffer.clone(), - game_object.descriptor_sets[fb_index].clone(), - push_constants).unwrap(); + builder + .bind_pipeline_graphics(self.pipeline.clone()) + .bind_descriptor_sets(PipelineBindPoint::Graphics, self.pipeline.layout().clone(), 0, game_object.descriptor_sets[fb_index].clone()) + .bind_vertex_buffers(0, mesh.vertex_buffer.clone()) + .bind_index_buffer(mesh.index_buffer.clone()) + .push_constants(self.pipeline.layout().clone(), 0, push_constants) + .draw_indexed(mesh.index_buffer.len() as u32, 1, 0, 0, 0).unwrap(); } } fn create_descriptor_sets(self: &Self, textures: &Vec, renderer: &VulkanRenderer) -> Vec> { - let descriptor_set_layout_0 = self.get_pipeline().descriptor_set_layout(0).unwrap().clone(); + let descriptor_set_layout_0 = self.get_pipeline().layout().descriptor_set_layouts().get(0).unwrap().clone(); renderer.uniform_buffers.iter().map(|uniform_buffer| { - let descriptor_set_0: Arc<(dyn vulkano::descriptor::DescriptorSet + std::marker::Send + std::marker::Sync + 'static)>; - debug_assert!(textures.len() == 2, "Expected diffuse and normal map for object shader!"); let diffuse = &renderer.game_data.textures[textures[0]]; + let diffuse_view = ImageView::new(diffuse.image.clone()).unwrap(); let normal_map = &renderer.game_data.textures[textures[1]]; + let normal_view = ImageView::new(normal_map.image.clone()).unwrap(); - descriptor_set_0 = Arc::new(PersistentDescriptorSet::start(descriptor_set_layout_0.clone()) + let mut builder = PersistentDescriptorSet::start(descriptor_set_layout_0.clone()); + builder .add_buffer(uniform_buffer.clone()).unwrap() - .add_sampled_image(diffuse.image.clone(), diffuse.sampler.clone()).unwrap() - .add_sampled_image(normal_map.image.clone(), normal_map.sampler.clone()).unwrap() - .build().unwrap()); + .add_sampled_image(diffuse_view, diffuse.sampler.clone()).unwrap() + .add_sampled_image(normal_view, normal_map.sampler.clone()).unwrap(); - vec![descriptor_set_0] + vec![Arc::new(builder.build().unwrap())] }).collect() } @@ -184,6 +183,7 @@ impl Drawcall for DefaultShader { } } +/* pub mod line_vs { vulkano_shaders::shader!{ ty: "vertex", @@ -231,9 +231,8 @@ impl LineShader { } impl Drawcall for LineShader { - fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, _fb_index: usize, _game_objects: Vec<&GameObject>, game_data: &GameData, dynamic_state: &DynamicState) { + fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, _fb_index: usize, _game_objects: Vec<&GameObject>, game_data: &GameData) { builder.draw(self.pipeline.clone(), - &dynamic_state, vec![self.vertex_buffer.clone()], (), game_data.line_push_constants.clone()).unwrap(); @@ -251,6 +250,7 @@ impl Drawcall for LineShader { &self.pipeline } } +*/ pub mod vs_text { vulkano_shaders::shader!{ @@ -287,6 +287,7 @@ impl TextShader { } unsafe { + /* static ENTRY_NAME: [u8; 5usize] = [109u8, 97u8, 105u8, 110u8, 0]; let entry_name_c = std::ffi::CStr::from_ptr(ENTRY_NAME.as_ptr() as *const _); @@ -303,23 +304,27 @@ impl TextShader { ..ShaderStages::none() }); let vs_entry = vs_module.graphics_entry_point(entry_name_c, vs_text::MainInput, vs_text::MainOutput, vs_layout, GraphicsShaderType::Vertex); + */ + + let vs = vs_text::Shader::load(device.clone()).unwrap(); + let fs = fs_text::Shader::load(device.clone()).unwrap(); let gp = Arc::new(GraphicsPipeline::start() .vertex_input_single_buffer::() - .vertex_shader(vs_entry, ()) + .vertex_shader(vs.main_entry_point(), ()) .triangle_list() .viewports_dynamic_scissors_irrelevant(1) .depth_stencil_simple_depth() - .fragment_shader(fs_entry, ()) + .fragment_shader(fs.main_entry_point(), ()) .blend_alpha_blending() .cull_mode_disabled() .render_pass(sub_pass.clone()) .build(device.clone()) .unwrap()); - println!("{:?}", gp.descriptor(0, 0).unwrap().ty); - println!("{:?}", gp.descriptor(0, 1).unwrap().ty); - println!("{:?}", gp.descriptor(0, 2).unwrap().ty); // TODO: Why does this exist? + // println!("{:?}", gp.descriptor(0, 0).unwrap().ty); + // println!("{:?}", gp.descriptor(0, 1).unwrap().ty); + // println!("{:?}", gp.descriptor(0, 2).unwrap().ty); // TODO: Why does this exist? gp } @@ -327,43 +332,37 @@ impl TextShader { } impl Drawcall for TextShader { - fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_objects: Vec<&GameObject>, game_data: &GameData, dynamic_state: &DynamicState) { + fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_objects: Vec<&GameObject>, game_data: &GameData) { for i in 0..game_objects.len() { let game_object = &game_objects[i]; let mesh = &game_data.meshes_text[game_object.mesh_index]; - let push_constants = game_object.get_push_constants(); - builder.draw_indexed( - self.pipeline.clone(), - dynamic_state, - vec![mesh.vertex_buffer.clone()], - mesh.index_buffer.clone(), - game_object.descriptor_sets[fb_index].clone(), - push_constants).unwrap(); + builder.bind_pipeline_graphics(self.pipeline.clone()) + .bind_descriptor_sets(PipelineBindPoint::Graphics, self.pipeline.layout().clone(), 0, game_object.descriptor_sets[fb_index].clone()) + .bind_vertex_buffers(0, mesh.vertex_buffer.clone()) + .bind_index_buffer(mesh.index_buffer.clone()) + .push_constants(self.pipeline.layout().clone(), 0, game_object.get_push_constants()) + .draw_indexed(mesh.index_buffer.len() as u32, 1, 0, 0, 0).unwrap(); } } fn create_descriptor_sets(self: &Self, textures: &Vec, renderer: &VulkanRenderer) -> Vec> { - let descriptor_set_layout = self.get_pipeline().descriptor_set_layout(0).unwrap().clone(); + let descriptor_set_layout = self.get_pipeline().layout().descriptor_set_layouts().get(0).unwrap().clone(); renderer.uniform_buffers.iter().map(|uniform_buffer| { - let descriptor_set: Arc<(dyn vulkano::descriptor::DescriptorSet + std::marker::Send + std::marker::Sync + 'static)>; - let builder = PersistentDescriptorSet::start(descriptor_set_layout.clone()); - let diffuse_index = match textures.len() { 0 => 0, 1 => textures[0], _ => panic!("Expected only diffuse map for text shader!"), }; let diffuse = &renderer.game_data.textures[diffuse_index]; + let diffuse_view = ImageView::new(diffuse.image.clone()).unwrap(); - descriptor_set = Arc::new(builder - .add_buffer(uniform_buffer.clone()).unwrap() - .add_sampled_image(diffuse.image.clone(), diffuse.sampler.clone()).unwrap() - .add_sampled_image(diffuse.image.clone(), diffuse.sampler.clone()).unwrap() // TODO: delet this - .build().unwrap()); + let mut builder = PersistentDescriptorSet::start(descriptor_set_layout.clone()); + builder.add_buffer(uniform_buffer.clone()).unwrap() + .add_sampled_image(diffuse_view.clone(), diffuse.sampler.clone()).unwrap(); - vec![descriptor_set] + vec![Arc::new(builder.build().unwrap())] }).collect() } diff --git a/src/vulkan/renderpass.rs b/src/vulkan/renderpass.rs index 073d5c4..ae3e3df 100644 --- a/src/vulkan/renderpass.rs +++ b/src/vulkan/renderpass.rs @@ -1,10 +1,8 @@ use crate::RenderConfig; use std::sync::Arc; -use vulkano::framebuffer::RenderPassAbstract; -use vulkano::format::Format; -use vulkano::device::Device; +use vulkano::{device::Device, format::Format, render_pass::RenderPass}; -pub fn create_render_pass(device: Arc, render_config: &RenderConfig, swapchain_format: Format) -> Arc { +pub fn create_render_pass(device: Arc, render_config: &RenderConfig, swapchain_format: Format) -> Arc { if render_config.msaa_samples > 0 { Arc::new(vulkano::single_pass_renderpass!( device.clone(), @@ -24,7 +22,7 @@ pub fn create_render_pass(device: Arc, render_config: &RenderConfig, swa depth: { load: Clear, store: Store, - format: Format::D16Unorm, + format: Format::D16_UNORM, samples: render_config.msaa_samples, initial_layout: ImageLayout::Undefined, final_layout: ImageLayout::DepthStencilAttachmentOptimal, @@ -49,7 +47,7 @@ pub fn create_render_pass(device: Arc, render_config: &RenderConfig, swa depth: { load: Clear, store: Store, - format: Format::D16Unorm, + format: Format::D16_UNORM, samples: 1, initial_layout: ImageLayout::Undefined, final_layout: ImageLayout::DepthStencilAttachmentOptimal,