diff --git a/build/debug.rdbg b/build/debug.rdbg index 42151f8..4ed4687 100644 Binary files a/build/debug.rdbg and b/build/debug.rdbg differ diff --git a/shaders/text.frag b/shaders/text.frag new file mode 100644 index 0000000..5b9db36 --- /dev/null +++ b/shaders/text.frag @@ -0,0 +1,26 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout(push_constant) uniform PushConstants { + mat4 model; +} push; + +layout(binding = 0) uniform ObjectUniformData { + mat4 view; + mat4 projection; + float time; + vec3 light_position; + vec3 light_directional_rotation; + vec3 camera_position; +} ubo; + +layout(binding = 1) uniform sampler2D diffuse_tex; + +layout(location = 0) in vec2 tex_coords; + +layout(location = 0) out vec4 out_color; + +void main() { + out_color = vec4(1., 1., 1., 1.); + // out_color = vec4(1., 1., 1., texture(diffuse_tex, tex_coords).r); +} \ No newline at end of file diff --git a/shaders/text.frag.spv b/shaders/text.frag.spv new file mode 100644 index 0000000..95731df Binary files /dev/null and b/shaders/text.frag.spv differ diff --git a/shaders/text.vert b/shaders/text.vert new file mode 100644 index 0000000..e934562 --- /dev/null +++ b/shaders/text.vert @@ -0,0 +1,33 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout(push_constant) uniform PushConstants { + mat4 model; +} push; + +layout(binding = 0) uniform ObjectUniformData { + mat4 view; + mat4 projection; + float time; + vec3 light_position; + vec3 light_directional_rotation; + vec3 camera_position; +} ubo; + +layout(location = 0) in vec3 position; +layout(location = 1) in vec2 uv; +layout(location = 2) in vec3 normal; + +layout(location = 0) out vec2 tex_coords; + +out gl_PerVertex { + vec4 gl_Position; +}; + +void main() { + // Vertex position in camera + gl_Position = ubo.projection * ubo.view * push.model * vec4(position, 1.0); + + // Just interpolate UV coords, no transformation needed + tex_coords = uv; +} \ No newline at end of file diff --git a/shaders/text.vert.spv b/shaders/text.vert.spv new file mode 100644 index 0000000..bf50b6d Binary files /dev/null and b/shaders/text.vert.spv differ diff --git a/src/game/mod.rs b/src/game/mod.rs index 5b9f868..8b089e8 100644 --- a/src/game/mod.rs +++ b/src/game/mod.rs @@ -10,9 +10,9 @@ use player::Player; use crate::{config::LogConfig, vulkan}; use crate::input::InputState; -use crate::vulkan::{Game, MeshHandle, TextureHandle, Vertex, VulkanRenderer}; +use crate::vulkan::{Game, MeshHandle, TextVertex, Vertex, VulkanRenderer}; use crate::vulkan::gameobject::{GameObject, GameObjectHandle, Updatable}; -use crate::vulkan::mesh::{self, CPUMesh}; +use crate::vulkan::mesh::{self, CPUMesh, CPUVertex}; use crate::vulkan::pipelines::vs::ty::ObjectUniformData; pub mod player; @@ -119,30 +119,30 @@ impl TestGame { let font = FontArc::try_from_slice(include_bytes!("../../models/OverpassRegular.ttf")).unwrap(); let mut glyph_brush = GlyphBrushBuilder::using_font(font).build(); - glyph_brush.queue(Section::default().add_text(Text::new("rRRRRRRRRRRRRRr"))); + glyph_brush.queue(Section::default().add_text(Text::new("penis lol"))); match glyph_brush.process_queued(|rect, text_data| { - renderer.upload_texture(text_data, rect.width(), rect.height(), Format::R8Srgb, renderer.device.clone()); + renderer.upload_texture(text_data, rect.width(), rect.height(), Format::R8Unorm, renderer.device.clone()); self.texture_index_counter += 1; }, |vertex_data| { - vec![ - Vertex { position: [vertex_data.pixel_coords.min.x, vertex_data.pixel_coords.min.y, 0.], uv: [vertex_data.tex_coords.min.x, vertex_data.tex_coords.min.y], normal: [0., 0., 1.], ..Default::default() }, - Vertex { position: [vertex_data.pixel_coords.min.x, vertex_data.pixel_coords.max.y, 0.], uv: [vertex_data.tex_coords.min.x, vertex_data.tex_coords.max.y], normal: [0., 0., 1.], ..Default::default() }, - ] + println!("vd: {:?}", vertex_data); + let result = vec![ + TextVertex { position: [vertex_data.pixel_coords.min.x, vertex_data.pixel_coords.min.y, 0.], uv: [vertex_data.tex_coords.min.x, vertex_data.tex_coords.min.y * 256. / 10.], normal: [0., 0., 1.] }, + TextVertex { position: [vertex_data.pixel_coords.min.x, vertex_data.pixel_coords.max.y, 0.], uv: [vertex_data.tex_coords.min.x, vertex_data.tex_coords.max.y * 256. / 10.], normal: [0., 0., 1.] }, + TextVertex { position: [vertex_data.pixel_coords.max.x, vertex_data.pixel_coords.min.y, 0.], uv: [vertex_data.tex_coords.max.x, vertex_data.tex_coords.min.y * 256. / 10.], normal: [0., 0., 1.] }, + TextVertex { position: [vertex_data.pixel_coords.max.x, vertex_data.pixel_coords.max.y, 0.], uv: [vertex_data.tex_coords.max.x, vertex_data.tex_coords.max.y * 256. / 10.], normal: [0., 0., 1.] }, + ]; + result }) { Ok(BrushAction::Draw(quads)) => { + let mut final_vertices = vec![]; - let mut final_indices = vec![]; - let mut height = 0.2; - let mut index_offset = 2; - final_vertices.push(Vertex { position: [0., 0., 0.], uv: [0., 0.], normal: [0., 0., 1.], ..Default::default() }); - final_vertices.push(Vertex { position: [0., height, 0.], uv: [0., 1.], normal: [0., 0., 1.], ..Default::default() }); + let mut final_indices: Vec = vec![]; + let mut index_offset = 0; for quad in quads { - final_vertices.append(&mut quad.clone()); - final_indices.append(&mut [0, 2, 3, 0, 3, 1].iter().map(|x| *x + index_offset - 2).collect()); + final_vertices.append(&mut quad.iter().map(|v| CPUVertex::VertexText(v.clone())).collect()); + final_indices.append(&mut [0, 2, 3, 0, 3, 1].iter().map(|x| *x + index_offset).collect()); index_offset += quad.len() as u32; } - println!("v: {:?}", final_vertices); - println!("i: {:?}", final_indices); let mesh = CPUMesh { vertices: final_vertices, indices: final_indices, @@ -156,9 +156,10 @@ impl TestGame { diffuse_handle: self.texture_index_counter - 1, normal_handle: None, original_path: None, + pipeline_index: 1 }; let mut game_object_handle = self.add_game_object(renderer, mesh_handle); - game_object_handle.get_game_object_mut(renderer).unwrap().scale = vec3(10., 10., 10.); + game_object_handle.get_game_object_mut(renderer).unwrap().scale = vec3(0.1, 0.1, 0.1); self.game_objects.push(game_object_handle); }, Ok(BrushAction::ReDraw) => {}, @@ -178,7 +179,7 @@ impl TestGame { let mut mesh_handles = Vec::new(); // Load file - let (meshes, document) = mesh::load_mesh(gltf_path, self.log_config.mesh_load_info).unwrap(); + let (meshes, document) = mesh::load_mesh::(gltf_path, self.log_config.mesh_load_info).unwrap(); for cpu_mesh in meshes.into_iter() { // Convert file texture id to game texture id @@ -191,7 +192,8 @@ impl TestGame { index: mesh_id, diffuse_handle: diffuse_id, normal_handle: Some(normal_id), - original_path: Some(gltf_path.to_string()) + original_path: Some(gltf_path.to_string()), + pipeline_index: 0 }; mesh_handles.push(mesh_handle); } @@ -211,7 +213,7 @@ impl TestGame { pub fn add_game_object(&mut self, renderer: &mut VulkanRenderer, mesh: MeshHandle) -> GameObjectHandle { let obj = GameObject::new(mesh); - let obj_handle = renderer.add_game_object(obj, 0); + let obj_handle = renderer.add_game_object(obj); self.game_objects.push(obj_handle); self.game_objects.last().unwrap().clone() } diff --git a/src/game/player.rs b/src/game/player.rs index 87ea9e1..4b0d490 100644 --- a/src/game/player.rs +++ b/src/game/player.rs @@ -122,7 +122,7 @@ pub fn vec4_from_pos(pos: [f32; 3]) -> Vector4 { vec4(pos[0], pos[1], pos[2], 1.0) } -pub fn intersection_distance(ray_origin: Vector3, ray_direction: Vector3, mesh: &Mesh, game_object: &GameObject) -> Option { +pub fn intersection_distance(ray_origin: Vector3, ray_direction: Vector3, mesh: &Mesh, game_object: &GameObject) -> Option { let index_lock = mesh.index_buffer.read().unwrap(); let vertex_lock = mesh.vertex_buffer.read().unwrap(); (0..mesh.index_buffer.len() / 3).map(|tri_idx| { diff --git a/src/vulkan/gameobject.rs b/src/vulkan/gameobject.rs index 77b21c0..5cb45a1 100644 --- a/src/vulkan/gameobject.rs +++ b/src/vulkan/gameobject.rs @@ -18,14 +18,15 @@ pub struct GameObject { pub scale: Vector3, pub children: Vec, pub descriptor_sets: Vec>, - pub is_selected: bool + pub is_selected: bool, + pub pipeline_index: usize, } impl GameObject { pub fn new(mesh: MeshHandle) -> GameObject { GameObject { mesh_index: mesh.index, texture_index: mesh.diffuse_handle, normal_map_index: mesh.normal_handle.unwrap_or(0), position: Vector3::new(0.0, 0.0, 0.0), rotation: Quaternion::new(1.0, 0.0, 0.0, 0.0), scale: Vector3::new(1.0, 1.0, 1.0), children: vec![], - descriptor_sets: vec![], is_selected: false } + descriptor_sets: vec![], is_selected: false, pipeline_index: mesh.pipeline_index } } pub fn _set_position(&mut self, x: f32, y: f32, z: f32) { diff --git a/src/vulkan/mesh.rs b/src/vulkan/mesh.rs index d31fc6a..9317b0e 100644 --- a/src/vulkan/mesh.rs +++ b/src/vulkan/mesh.rs @@ -6,6 +6,8 @@ use gltf::mesh::util::{ReadJoints, ReadNormals, ReadPositions, ReadTangents, Rea use crate::vulkan::mesh::LoadError::{GltfError, MeshDataMissing, NoIndices}; use crate::vulkan::Vertex; +use super::TextVertex; + #[derive(Debug)] pub enum LoadError { GltfError(gltf::Error), @@ -25,9 +27,15 @@ impl From for LoadError { } } +#[derive(Debug)] +pub enum CPUVertex { + Vertex3D(Vertex), + VertexText(TextVertex) +} + #[derive(Debug)] pub struct CPUMesh { - pub vertices: Vec, + pub vertices: Vec, pub indices: Vec, pub local_texture_index: Option, pub local_normal_map_index: Option, @@ -41,7 +49,7 @@ fn read_file(path: &str) -> Vec { glb_bytes } -pub fn load_mesh(mesh_path: &str, print_status: bool) -> Result<(Vec, Document), LoadError> { +pub fn load_mesh(mesh_path: &str, print_status: bool) -> Result<(Vec, Document), LoadError> { let mut start_time = None; let mut total_vertices = 0; let mut total_indices = 0; @@ -80,7 +88,7 @@ pub fn load_mesh(mesh_path: &str, print_status: bool) -> Result<(Vec, D reader.read_tangents(), reader.read_joints(0), reader.read_weights(0)); - let vertices = vertices_result?; + let vertices = vertices_result?.iter().map(|v| CPUVertex::Vertex3D(v.clone())).collect(); let cpu_mesh = CPUMesh { vertices, indices: indices.into_u32().collect(), diff --git a/src/vulkan/mod.rs b/src/vulkan/mod.rs index 003d2ec..611ce65 100644 --- a/src/vulkan/mod.rs +++ b/src/vulkan/mod.rs @@ -25,12 +25,14 @@ use winit::window::{Window, WindowBuilder}; use mesh::CPUMesh; use pipelines::{Drawcall}; use pipelines::line_vs::ty::LinePushConstants; -use pipelines::DefaultShader; +use pipelines::{DefaultShader, TextShader}; use pipelines::vs; use crate::config::RenderConfig; use crate::vulkan::gameobject::{GameObject, GameObjectHandle}; +use self::mesh::CPUVertex; + pub mod pipelines; pub mod gameobject; pub mod mesh; @@ -39,7 +41,7 @@ mod renderpass; mod framebuffers; const VALIDATION_LAYERS: &[&str] = &[ - "VK_LAYER_KHRONOS_validation" + "VK_LAYER_KHRONOS_validation", ]; #[derive(Default, Debug, Clone)] @@ -59,6 +61,14 @@ pub struct LinePoint { } vulkano::impl_vertex!(LinePoint, position); +#[derive(Default, Debug, Clone)] +pub struct TextVertex { + pub position: [f32; 3], + pub uv: [f32; 2], + pub normal: [f32; 3], +} +vulkano::impl_vertex!(TextVertex, position, uv, normal); + pub trait Game { /// Returns true if event should be ignored by the vulkan handler fn on_window_event(self: &mut Self, event: &Event<()>); @@ -66,8 +76,8 @@ pub trait Game { fn update(self: &mut Self, renderer: &mut VulkanRenderer) -> vs::ty::ObjectUniformData; } -pub struct Mesh { - pub vertex_buffer: Arc>, +pub struct Mesh { + pub vertex_buffer: Arc>, pub index_buffer: Arc>, pub original_path: Option, } @@ -77,7 +87,8 @@ pub struct MeshHandle { pub index: usize, pub diffuse_handle: TextureHandle, pub normal_handle: Option, - pub original_path: Option + pub original_path: Option, + pub pipeline_index: usize } pub(crate) type TextureHandle = usize; @@ -94,9 +105,9 @@ pub struct GameData { pub dimensions: [u32; 2], pub shutdown: bool, pub game_objects: Vec, - pub meshes: Vec, + pub meshes: Vec>, + pub meshes_text: Vec>, pub textures: Vec, - pub use_line_pipeline: bool, } pub(crate) type RendererDescriptorSets = dyn DescriptorSet + Send + Sync; @@ -115,7 +126,6 @@ pub struct VulkanRenderer { pub debug_callback: Option, pub previous_frame_end: Option>, pub uniform_buffers: Vec>>, - pub line_vertex_buffer: Arc>, pub render_config: RenderConfig } @@ -134,9 +144,9 @@ impl VulkanRenderer { line_vertices, dimensions: [0, 0], meshes: vec![], + meshes_text: vec![], game_objects: vec![], textures: vec![], - use_line_pipeline: true, }; // Create basic vulkan instance with layers and info @@ -239,12 +249,11 @@ impl VulkanRenderer { // Render pass let render_pass = renderpass::create_render_pass(device.clone(), &render_config, swapchain.format()); - - let line_vertex_buffer = CpuAccessibleBuffer::from_iter(device.clone(), BufferUsage::vertex_buffer(), false, data.line_vertices.iter().cloned()).unwrap(); + let render_pass_text = renderpass::create_render_pass(device.clone(), &render_config, swapchain.format()); let pipelines: Vec> = vec![ Box::new(DefaultShader::new(device.clone(), render_pass.clone())), - // Box::new(LineShader::new(device.clone(), render_pass.clone(), line_vertex_buffer.clone())), + Box::new(TextShader::new(device.clone(), render_pass_text.clone())), ]; // Dynamic viewports allow us to recreate just the viewport when the window is resized @@ -292,7 +301,6 @@ impl VulkanRenderer { surface, swapchain, render_pass, queue, recreate_swapchain: false, debug_callback, previous_frame_end, render_config, - line_vertex_buffer, }, events_loop) } @@ -307,8 +315,10 @@ impl VulkanRenderer { } // Draw meshes etc. + let mut index = 0; for pipeline in &self.pipelines { - pipeline.draw(&mut builder, fb_index, &self.game_data, &self.dynamic_state); + pipeline.draw(&mut builder, fb_index, self.game_data.game_objects.iter().filter(|go| go.pipeline_index == index).collect(), &self.game_data, &self.dynamic_state); + index += 1; } // General cleanup @@ -343,7 +353,7 @@ impl VulkanRenderer { self.pipelines = vec![ Box::new(DefaultShader::new(self.device.clone(), self.render_pass.clone())), - // Box::new(LineShader::new(self.device.clone(), self.render_pass.clone(), self.line_vertex_buffer.clone())), + Box::new(TextShader::new(self.device.clone(), self.render_pass.clone())), ]; self.swapchain = new_swapchain; @@ -420,11 +430,28 @@ impl VulkanRenderer { // collision_mesh.push_face((mesh.indices[i] as usize, mesh.indices[i + 1] as usize, mesh.indices[i + 2] as usize)); // } - let vertex_buffer = CpuAccessibleBuffer::from_iter(self.device.clone(), BufferUsage::vertex_buffer(), false, mesh.vertices.into_iter()).unwrap(); - let index_buffer = CpuAccessibleBuffer::from_iter(self.device.clone(), BufferUsage::index_buffer(), false, mesh.indices.into_iter()).unwrap(); + let index_buffer = CpuAccessibleBuffer::from_iter(self.device.clone(), BufferUsage::index_buffer(), false, mesh.indices.into_iter()).unwrap(); - self.game_data.meshes.push(Mesh { vertex_buffer, index_buffer, original_path }); - self.game_data.meshes.len() - 1 + match mesh.vertices.get(0).unwrap() { + CPUVertex::Vertex3D(_) => { + let verts: Vec = mesh.vertices.into_iter().filter_map(|v| match v { + CPUVertex::Vertex3D(vert) => Some(vert), + CPUVertex::VertexText(_) => None + }).collect(); + let vertex_buffer = CpuAccessibleBuffer::from_iter(self.device.clone(), BufferUsage::vertex_buffer(), false, verts.into_iter()).unwrap(); + self.game_data.meshes.push(Mesh { vertex_buffer, index_buffer, original_path }); + self.game_data.meshes.len() - 1 + }, + CPUVertex::VertexText(_) => { + let verts: Vec = mesh.vertices.into_iter().filter_map(|v| match v { + CPUVertex::Vertex3D(_) => None, + CPUVertex::VertexText(vert) => Some(vert) + }).collect(); + let vertex_buffer = CpuAccessibleBuffer::from_iter(self.device.clone(), BufferUsage::vertex_buffer(), false, verts.into_iter()).unwrap(); + self.game_data.meshes_text.push(Mesh { vertex_buffer, index_buffer, original_path }); + self.game_data.meshes_text.len() - 1 + }, + } } pub fn upload_texture(self: &mut Self, bytes: &[u8], width: u32, height: u32, format: Format, device: Arc) { @@ -438,7 +465,7 @@ impl VulkanRenderer { }; let layout = ImageLayout::ShaderReadOnlyOptimal; - let mip_maps = if format == Format::R8Srgb { MipmapsCount::One } else { MipmapsCount::Log2 }; + let mip_maps = if format == Format::R8Uint { MipmapsCount::One } else { MipmapsCount::Log2 }; let (image_view, initializer) = ImmutableImage::uninitialized( device.clone(), @@ -518,8 +545,8 @@ impl VulkanRenderer { self.game_data.textures.push(Texture { image: image_view, sampler }); } - 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); + pub fn add_game_object(self: &mut Self, mut game_object: GameObject) -> GameObjectHandle { + self.pipelines[game_object.pipeline_index].create_descriptor_set(&mut game_object, self); self.game_data.game_objects.push(game_object); GameObjectHandle { diff --git a/src/vulkan/pipelines.rs b/src/vulkan/pipelines.rs index 0271aeb..94b4878 100644 --- a/src/vulkan/pipelines.rs +++ b/src/vulkan/pipelines.rs @@ -1,6 +1,6 @@ use std::{convert::TryInto, io::{self, ErrorKind, Read, Write}, path::PathBuf, sync::Arc}; -use vulkano::{command_buffer::AutoCommandBufferBuilder, descriptor::{descriptor::ShaderStages, descriptor_set::PersistentDescriptorSet}, pipeline::shader::ShaderModule}; +use vulkano::{command_buffer::AutoCommandBufferBuilder, descriptor::{descriptor::ShaderStages, descriptor_set::PersistentDescriptorSet}, pipeline::shader::{ShaderModule}}; use vulkano::command_buffer::DynamicState; use vulkano::device::Device; use vulkano::framebuffer::RenderPassAbstract; @@ -9,7 +9,7 @@ use vulkano::pipeline::GraphicsPipeline; use vulkano::pipeline::GraphicsPipelineAbstract; use vulkano::pipeline::shader::GraphicsShaderType; -use crate::GameObject; +use crate::{GameObject, vulkan::TextVertex}; use crate::vulkan::{LinePoint, Vertex}; use crate::vulkan::GameData; use crate::VulkanRenderer; @@ -18,7 +18,7 @@ type RP = Arc; type GP = Arc; pub trait Drawcall { - fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_data: &GameData, dynamic_state: &DynamicState); + fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_objects: Vec<&GameObject>, game_data: &GameData, dynamic_state: &DynamicState); fn create_descriptor_set(self: &Self, game_object: &mut GameObject, renderer: &VulkanRenderer); fn recreate_pipeline(self: &mut Self, device: Arc, render_pass: RP); fn get_pipeline(self: &Self) -> &GP; @@ -136,12 +136,14 @@ impl DefaultShader { } impl Drawcall for DefaultShader { - fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_data: &GameData, dynamic_state: &DynamicState) { - for i in 0..game_data.game_objects.len() { - let game_object = &game_data.game_objects[i]; + fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_objects: Vec<&GameObject>, game_data: &GameData, dynamic_state: &DynamicState) { + 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(); + println!("default: {:?}", game_object.mesh_index); + builder.draw_indexed( self.pipeline.clone(), dynamic_state, @@ -230,7 +232,7 @@ impl LineShader { } impl Drawcall for LineShader { - fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, _fb_index: usize, game_data: &GameData, dynamic_state: &DynamicState) { + fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, _fb_index: usize, game_objects: Vec<&GameObject>, game_data: &GameData, dynamic_state: &DynamicState) { builder.draw(self.pipeline.clone(), &dynamic_state, vec![self.vertex_buffer.clone()], @@ -246,6 +248,124 @@ impl Drawcall for LineShader { self.pipeline = Self::create_pipeline(device, render_pass); } + fn get_pipeline(self: &Self) -> &GP { + &self.pipeline + } +} + +pub mod vs_text { + vulkano_shaders::shader!{ + ty: "vertex", + path: "shaders/text.vert" + } +} + +pub mod fs_text { + vulkano_shaders::shader!{ + ty: "fragment", + path: "shaders/text.frag" + } +} + +pub struct TextShader { + pipeline: GP, +} + +impl TextShader { + pub fn new(device: Arc, render_pass: RP) -> Self { + TextShader { + pipeline: Self::create_pipeline(device, render_pass) + } + } + + fn create_pipeline(device: Arc, render_pass: RP) -> GP { + let sub_pass = Subpass::from(render_pass.clone(), 0).unwrap(); + + #[cfg(debug_assertions)] + { + println!("Compiling shaders..."); + compile_shaders().unwrap(); + } + + 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/text.frag.spv"); + let fs_layout = fs::Layout(ShaderStages { + fragment: true, + ..ShaderStages::none() + }); + let fs_entry = fs_module.graphics_entry_point(entry_name_c, fs_text::MainInput, fs_text::MainOutput, fs_layout, GraphicsShaderType::Fragment); + + let vs_module = shader_module_from_file(device.clone(), "shaders/text.vert.spv"); + let vs_layout = vs::Layout(ShaderStages { + vertex: true, + ..ShaderStages::none() + }); + let vs_entry = vs_module.graphics_entry_point(entry_name_c, vs_text::MainInput, vs_text::MainOutput, vs_layout, GraphicsShaderType::Vertex); + + let gp = Arc::new(GraphicsPipeline::start() + .vertex_input_single_buffer::() + .vertex_shader(vs_entry, ()) + .triangle_list() + .viewports_dynamic_scissors_irrelevant(1) + .depth_stencil_simple_depth() + .fragment_shader(fs_entry, ()) + .blend_alpha_blending() + .cull_mode_back() + .render_pass(sub_pass.clone()) + .build(device.clone()) + .unwrap()); + + println!("layout: {:?}", vulkano::descriptor::PipelineLayoutAbstract::descriptor_set_layout(&gp, 0).unwrap().descriptors_count()); + gp + } + } +} + +impl Drawcall for TextShader { + fn draw(self: &Self, builder: &mut AutoCommandBufferBuilder, fb_index: usize, game_objects: Vec<&GameObject>, game_data: &GameData, dynamic_state: &DynamicState) { + 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(); + + println!("text: {:?}", game_object.mesh_index); + + 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(); + } + } + + fn create_descriptor_set(self: &Self, game_object: &mut GameObject, renderer: &VulkanRenderer) { + let descriptor_set_layout = self.get_pipeline().descriptor_set_layout(0).unwrap().clone(); + + game_object.descriptor_sets = 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 = &renderer.game_data.textures[game_object.texture_index]; + + 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() + .build().unwrap()); + + descriptor_set + }).collect(); + } + + fn recreate_pipeline(self: &mut Self, device: Arc, render_pass: RP) { + self.pipeline = Self::create_pipeline(device, render_pass); + } + fn get_pipeline(self: &Self) -> &GP { &self.pipeline }