#![deny(unsafe_code)] use crate::error::*; use crate::graphics::permanent::PermanentGraphicsState; use crate::graphics::render_state::RenderState; use crate::graphics::util::init_buffer; use crate::graphics::window_dressing::WindowDressing; use crate::linear_algebra::{ Vec3, Vec4, Transformation }; use crate::model_loader::load_model; use crate::shader_data::{ Vertex, VertexPushBlock }; use std::f32::consts::{ TAU }; use vulkanalia::{ Device, Instance }; use vulkanalia::vk::{ self, DeviceV1_0 }; #[derive(Debug)] pub struct Model { pub vertex_buffer: vk::Buffer, vertex_buffer_memory: vk::DeviceMemory, pub index_buffer: vk::Buffer, index_buffer_memory: vk::DeviceMemory, pub index_count: usize, } impl Model { pub fn new(permanent: &PermanentGraphicsState, window_dressing: &WindowDressing) -> Result { let device = &permanent.device; let instance = &permanent.instance; let graphics_queue = &permanent.graphics_queue; let transient_command_pool = &window_dressing.transient_command_pool; let (vertices, indices) = load_model()?; let index_count = indices.len(); let (vertex_buffer, vertex_buffer_memory) = init_vertex_buffer(vertices, instance, device, graphics_queue, &transient_command_pool)?; let (index_buffer, index_buffer_memory) = init_index_buffer(indices, instance, device, graphics_queue, &transient_command_pool)?; Ok(Model { vertex_buffer, vertex_buffer_memory, index_buffer, index_buffer_memory, index_count, }) } #[allow(unsafe_code)] pub fn destroy(self, device: &Device) { unsafe { device.destroy_buffer(self.vertex_buffer, None) }; unsafe { device.free_memory(self.vertex_buffer_memory, None) }; unsafe { device.destroy_buffer(self.index_buffer, None) }; unsafe { device.free_memory(self.index_buffer_memory, None) }; } #[allow(unsafe_code)] pub fn render(&self, time: f32, device: &Device, render_state: &RenderState, command_buffer: &vk::CommandBuffer, descriptor_set: &vk::DescriptorSet) { unsafe { device.cmd_bind_vertex_buffers(*command_buffer, 0, &[self.vertex_buffer], &[0]) }; unsafe { device.cmd_bind_index_buffer(*command_buffer, self.index_buffer, 0, vk::IndexType::UINT32) }; unsafe { device.cmd_bind_descriptor_sets(*command_buffer, vk::PipelineBindPoint::GRAPHICS, render_state.pipeline_layout, 0, &[*descriptor_set], &[]) }; let scale = Vec3::new(1.0, 1.0, 1.0); let model = Transformation { rotation: Vec4::rotation_quaternion(&Vec3::new(0.0, 1.0, 0.0), time % TAU), translation: Vec3::new(0.0, 0.0, 0.0), }; let push_block = VertexPushBlock:: { scale, model }; let size = size_of::>(); let push_block_bytes = unsafe { std::slice::from_raw_parts(&push_block as *const VertexPushBlock as *const u8, size) }; unsafe { device.cmd_push_constants(*command_buffer, render_state.pipeline_layout, vk::ShaderStageFlags::VERTEX, 0, push_block_bytes) }; unsafe { device.cmd_draw_indexed(*command_buffer, self.index_count as u32, 1, 0, 0, 0) }; } } fn init_vertex_buffer(vertices: Vec>, instance: &Instance, device: &Device, queue: &vk::Queue, command_pool: &vk::CommandPool) -> Result<(vk::Buffer, vk::DeviceMemory)> { init_buffer(instance, device, queue, command_pool, vk::BufferUsageFlags::VERTEX_BUFFER, &vertices) } fn init_index_buffer(indices: Vec, instance: &Instance, device: &Device, queue: &vk::Queue, command_pool: &vk::CommandPool) -> Result<(vk::Buffer, vk::DeviceMemory)> { init_buffer(instance, device, queue, command_pool, vk::BufferUsageFlags::INDEX_BUFFER, &indices) }