@@ -3,8 +3,18 @@ layout(location = 1) in vec3 in_color; | |||
layout(location = 0) out vec3 frag_color; | |||
layout(binding = 0) uniform Uniforms { | |||
mat4 object; | |||
mat4 camera; | |||
mat4 projection; | |||
} uniforms; | |||
void main() { | |||
gl_Position = vec4(in_position, 0.0, 1.0); | |||
gl_Position = | |||
uniforms.projection * | |||
uniforms.camera * | |||
uniforms.object * | |||
vec4(in_position, 0.0, 1.0); | |||
frag_color = in_color; | |||
} | |||
@@ -12,7 +12,7 @@ use crate::{ | |||
}; | |||
use ash::{version::DeviceV1_0, vk}; | |||
use cgmath::{Vector2, Vector3}; | |||
use cgmath::{prelude::*, Matrix4, Point3, Rad, Vector2, Vector3}; | |||
use std::rc::Rc; | |||
struct Pipelines { | |||
@@ -20,9 +20,10 @@ struct Pipelines { | |||
} | |||
struct SwapchainData<'a> { | |||
swapchain: Rc<Swapchain>, | |||
image_f: Vec<Option<&'a Fence>>, | |||
cmd_pool: Rc<CommandPool>, | |||
swapchain: Rc<Swapchain>, | |||
image_f: Vec<Option<&'a Fence>>, | |||
descriptor_pool: Rc<DescriptorPool>, | |||
cmd_pool: Rc<CommandPool>, | |||
} | |||
impl Pipelines { | |||
@@ -45,7 +46,7 @@ impl SwapchainData<'_> { | |||
queue_graphics: &Queue, | |||
queue_surface: &Queue, | |||
conf: &render::Conf, | |||
) -> Result<Self, vk::Result> { | |||
) -> Result<Self, ErrBufferCreate> { | |||
let swapchain = Swapchain::create( | |||
device.clone(), | |||
&phys_device, | |||
@@ -70,7 +71,7 @@ impl SwapchainData<'_> { | |||
PipelineCreateInfo::info_basic( | |||
shader_vert, | |||
shader_frag, | |||
layout, | |||
layout.clone(), | |||
render_pass.clone(), | |||
swapchain.extent, | |||
), | |||
@@ -86,35 +87,53 @@ impl SwapchainData<'_> { | |||
swapchain.extent, | |||
)?; | |||
let uniform_buffers = | |||
framebuffers | |||
.iter() | |||
.map(|_| Buffer::create_uniform(device.clone(), phys_device)) | |||
.collect::<Result<_, _>>()?; | |||
let descriptor_pool = DescriptorPool::create( | |||
device.clone(), | |||
uniform_buffers, | |||
layout.descriptor.clone(), | |||
)?; | |||
let cmd_pool = CommandPool::create_graphics( | |||
device, | |||
queue_graphics.index, | |||
&framebuffers, | |||
render_pass, | |||
swapchain.extent, | |||
|cmd| { | |||
|cmd, framebuffer_num| { | |||
cmd.bind_pipeline(pipelines.main.clone()); | |||
cmd.bind_vertex_buffer(vertex_buffer.clone()); | |||
cmd.bind_index_buffer(index_buffer.clone()); | |||
cmd.bind_descriptor_pool( | |||
descriptor_pool.clone(), | |||
layout.clone(), | |||
framebuffer_num, | |||
); | |||
cmd.draw(INDICES.len()); | |||
}, | |||
)?; | |||
Ok(Self { swapchain, image_f, cmd_pool }) | |||
Ok(Self { swapchain, image_f, descriptor_pool, cmd_pool }) | |||
} | |||
} | |||
fn draw_frame<'a>( | |||
sc_data: &mut SwapchainData<'a>, | |||
device: &Device, | |||
swapchain: &Swapchain, | |||
image_avail_s: &Semaphore, | |||
render_fini_s: &Semaphore, | |||
frame_f: &'a Fence, | |||
image_f: &mut [Option<&'a Fence>], | |||
cmd_buffers: &[vk::CommandBuffer], | |||
queue_graphics: &Queue, | |||
queue_surface: &Queue, | |||
time_ms: u128, | |||
) -> Result<(), vk::Result> { | |||
let cmd_buffers = sc_data.cmd_pool.buf_handles(); | |||
let fences = [**frame_f]; | |||
unsafe { | |||
@@ -125,7 +144,7 @@ fn draw_frame<'a>( | |||
device | |||
.swapchain_ext | |||
.acquire_next_image( | |||
**swapchain, | |||
**sc_data.swapchain, | |||
u64::max_value(), | |||
**image_avail_s, | |||
vk::Fence::null(), | |||
@@ -133,14 +152,40 @@ fn draw_frame<'a>( | |||
.0 as usize | |||
}; | |||
if let Some(fence) = image_f[image_index] { | |||
if let Some(fence) = sc_data.image_f[image_index] { | |||
let fences = [**fence]; | |||
unsafe { | |||
device.wait_for_fences(&fences, true, u64::max_value())?; | |||
} | |||
} | |||
image_f[image_index] = Some(frame_f); | |||
sc_data.image_f[image_index] = Some(frame_f); | |||
let uniforms = Uniforms { | |||
object: | |||
Matrix4::from_angle_z(Rad::full_turn() * time_ms as f32 / 10_000.0), | |||
camera: Matrix4::look_at( | |||
Point3::new(2.0, 2.0, 2.0), | |||
Point3::new(0.0, 0.0, 0.0), | |||
Vector3::new(0.0, 0.0, 1.0), | |||
), | |||
projection: | |||
cgmath::perspective( | |||
Rad::turn_div_4(), | |||
sc_data.swapchain.extent.width as f32 / | |||
sc_data.swapchain.extent.height as f32, | |||
0.01, | |||
100_000.0, | |||
) * | |||
Matrix4::new( | |||
1.0, 0.0, 0.0, 0.0, | |||
0.0, -1.0, 0.0, 0.0, | |||
0.0, 0.0, 1.0, 0.0, | |||
0.0, 0.0, 0.0, 1.0, | |||
), | |||
}; | |||
sc_data.descriptor_pool.buffers[image_index].write_data(&[uniforms])?; | |||
let wait_semaphores = [**image_avail_s]; | |||
let wait_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT]; | |||
@@ -167,7 +212,7 @@ fn draw_frame<'a>( | |||
device.queue_submit(**queue_graphics, &submit_info, **frame_f)?; | |||
} | |||
let swapchains = [**swapchain]; | |||
let swapchains = [**sc_data.swapchain]; | |||
let image_indices = [image_index as u32]; | |||
let present_info = vk::PresentInfoKHR { | |||
@@ -198,6 +243,8 @@ fn fallback_main( | |||
conf: &conf::Conf, | |||
lg: &log::Log, | |||
) -> Result<(), Box<dyn std::error::Error>> { | |||
let start_time = std::time::Instant::now(); | |||
/* | |||
let main = { | |||
use std::io::prelude::*; | |||
@@ -257,7 +304,8 @@ fn fallback_main( | |||
let frame_f = Fence::create_all(device.clone(), concur_frames)?; | |||
let layout = PipelineLayout::create(device.clone())?; | |||
let desc_layout = DescriptorSetLayout::create(device.clone())?; | |||
let layout = PipelineLayout::create(desc_layout)?; | |||
let spir_vert = Spir::read(MAIN_VERT); | |||
let spir_frag = Spir::read(MAIN_FRAG); | |||
@@ -289,15 +337,14 @@ fn fallback_main( | |||
} | |||
let frame = draw_frame( | |||
&mut sc_data, | |||
&device, | |||
&sc_data.swapchain, | |||
&image_avail_s[cur_c_frame], | |||
&render_fini_s[cur_c_frame], | |||
&frame_f[cur_c_frame], | |||
&mut sc_data.image_f, | |||
sc_data.cmd_pool.buf_handles(), | |||
&queue_graphics, | |||
&queue_surface, | |||
start_time.elapsed().as_millis(), | |||
); | |||
match frame { | |||
@@ -1,6 +1,8 @@ | |||
mod buffer; | |||
mod cmd; | |||
mod conf; | |||
mod descriptorlayout; | |||
mod descriptorpool; | |||
mod device; | |||
mod fence; | |||
mod framebuffer; | |||
@@ -17,12 +19,15 @@ mod shader; | |||
mod spir; | |||
mod surface; | |||
mod swapchain; | |||
mod uniforms; | |||
mod vertex; | |||
pub use self::{ | |||
buffer::Buffer, | |||
buffer::{Buffer, ErrBufferCreate}, | |||
cmd::{CommandBuffer, CommandPool}, | |||
conf::{Conf, PresentMode}, | |||
descriptorlayout::DescriptorSetLayout, | |||
descriptorpool::{DescriptorPool, DescriptorSet}, | |||
device::{Device, ErrDeviceCreate, ErrPhysicalDeviceGet, PhysicalDevice}, | |||
fence::Fence, | |||
framebuffer::Framebuffer, | |||
@@ -40,6 +45,7 @@ pub use self::{ | |||
surface::Surface, | |||
swapchain::Swapchain, | |||
vertex::Vertex, | |||
uniforms::Uniforms, | |||
}; | |||
// EOF |
@@ -1,4 +1,6 @@ | |||
use crate::render::{CommandPool, Device, PhysicalDevice, Queue, Vertex}; | |||
use crate::render::{ | |||
CommandPool, Device, PhysicalDevice, Queue, Uniforms, Vertex, | |||
}; | |||
use ash::{ | |||
version::{DeviceV1_0, InstanceV1_0}, | |||
vk, | |||
@@ -78,127 +80,156 @@ unsafe fn create_buffer( | |||
Ok((handle, memory)) | |||
} | |||
unsafe fn copy_buffer( | |||
src_handle: vk::Buffer, | |||
dst_handle: vk::Buffer, | |||
size: vk::DeviceSize, | |||
device: Rc<Device>, | |||
xfer_queue: &Queue, | |||
) -> Result<(), vk::Result> { | |||
let pool = CommandPool::create_transfer( | |||
device.clone(), | |||
xfer_queue.index, | |||
|cmd| cmd.transfer(src_handle, dst_handle, size), | |||
)?; | |||
let submit_buffers = pool.buf_handles(); | |||
let submit_info = [ | |||
vk::SubmitInfo { | |||
command_buffer_count: submit_buffers.len() as u32, | |||
p_command_buffers: submit_buffers.as_ptr(), | |||
..Default::default() | |||
} | |||
]; | |||
device.queue_submit( | |||
**xfer_queue, | |||
&submit_info, | |||
vk::Fence::null(), | |||
)?; | |||
device.queue_wait_idle(**xfer_queue) | |||
/// Returns the size of `data` as a `vk::DeviceSize`. | |||
fn dev_size_of<T>(data: &[T]) -> vk::DeviceSize { | |||
(std::mem::size_of::<T>() * data.len()) as vk::DeviceSize | |||
} | |||
impl Buffer { | |||
/// Creates a vertex buffer. | |||
pub fn create_vertex( | |||
device: Rc<Device>, | |||
phys_device: &PhysicalDevice, | |||
vertices: &[Vertex], | |||
xfer_queue: &Queue, | |||
queue: &Queue, | |||
) -> Result<Rc<Self>, ErrBufferCreate> { | |||
let size = std::mem::size_of::<Vertex>() * vertices.len(); | |||
let size = size as vk::DeviceSize; | |||
let size = dev_size_of(vertices); | |||
let (handle, memory) = unsafe { | |||
let (src_handle, src_memory) = create_buffer( | |||
unsafe { | |||
let (handle, memory) = create_buffer( | |||
&device, | |||
phys_device, | |||
size, | |||
vk::BufferUsageFlags::TRANSFER_SRC, | |||
vk::MemoryPropertyFlags::HOST_VISIBLE | | |||
vk::MemoryPropertyFlags::HOST_COHERENT, | |||
vk::BufferUsageFlags::TRANSFER_DST | | |||
vk::BufferUsageFlags::VERTEX_BUFFER, | |||
vk::MemoryPropertyFlags::DEVICE_LOCAL, | |||
)?; | |||
let mem_flg = vk::MemoryMapFlags::empty(); | |||
let mem_map = device.map_memory(src_memory, 0, size, mem_flg)?; | |||
(mem_map as *mut Vertex).copy_from(vertices.as_ptr(), vertices.len()); | |||
device.unmap_memory(src_memory); | |||
let dst = Self { handle, memory, device }; | |||
let (dst_handle, dst_memory) = create_buffer( | |||
dst.xfer_data(queue, phys_device, vertices)?; | |||
Ok(Rc::new(dst)) | |||
} | |||
} | |||
/// Creates an index buffer. | |||
pub fn create_index( | |||
device: Rc<Device>, | |||
phys_device: &PhysicalDevice, | |||
indices: &[u16], | |||
queue: &Queue, | |||
) -> Result<Rc<Self>, ErrBufferCreate> { | |||
let size = dev_size_of(indices); | |||
unsafe { | |||
let (handle, memory) = create_buffer( | |||
&device, | |||
phys_device, | |||
size, | |||
vk::BufferUsageFlags::TRANSFER_DST | | |||
vk::BufferUsageFlags::VERTEX_BUFFER, | |||
vk::BufferUsageFlags::INDEX_BUFFER, | |||
vk::MemoryPropertyFlags::DEVICE_LOCAL, | |||
)?; | |||
copy_buffer(src_handle, dst_handle, size, device.clone(), xfer_queue)?; | |||
// TODO: express with Drop | |||
device.free_memory(src_memory, None); | |||
device.destroy_buffer(src_handle, None); | |||
let dst = Self { handle, memory, device }; | |||
(dst_handle, dst_memory) | |||
}; | |||
dst.xfer_data(queue, phys_device, indices)?; | |||
Ok(Rc::new(Self { handle, device, memory })) | |||
Ok(Rc::new(dst)) | |||
} | |||
} | |||
pub fn create_index( | |||
/// Creates a uniform buffer. | |||
pub fn create_uniform( | |||
device: Rc<Device>, | |||
phys_device: &PhysicalDevice, | |||
indices: &[u16], | |||
xfer_queue: &Queue, | |||
) -> Result<Rc<Self>, ErrBufferCreate> { | |||
let size = std::mem::size_of::<u16>() * indices.len(); | |||
let size = size as vk::DeviceSize; | |||
let (handle, memory) = unsafe { | |||
let (src_handle, src_memory) = create_buffer( | |||
create_buffer( | |||
&device, | |||
phys_device, | |||
size, | |||
vk::BufferUsageFlags::TRANSFER_SRC, | |||
std::mem::size_of::<Uniforms>() as vk::DeviceSize, | |||
vk::BufferUsageFlags::UNIFORM_BUFFER, | |||
vk::MemoryPropertyFlags::HOST_VISIBLE | | |||
vk::MemoryPropertyFlags::HOST_COHERENT, | |||
)?; | |||
)? | |||
}; | |||
let mem_flg = vk::MemoryMapFlags::empty(); | |||
let mem_map = device.map_memory(src_memory, 0, size, mem_flg)?; | |||
(mem_map as *mut u16).copy_from(indices.as_ptr(), indices.len()); | |||
device.unmap_memory(src_memory); | |||
Ok(Rc::new(Self { handle, memory, device })) | |||
} | |||
let (dst_handle, dst_memory) = create_buffer( | |||
&device, | |||
/// Copies the contents of `src` to `self` using a transient pool. | |||
unsafe fn copy_buffer( | |||
&self, | |||
src: &Self, | |||
size: vk::DeviceSize, | |||
queue: &Queue, | |||
) -> Result<(), vk::Result> { | |||
let pool = CommandPool::create_transfer( | |||
self.device.clone(), | |||
queue.index, | |||
|cmd| cmd.transfer(src.handle, self.handle, size), | |||
)?; | |||
let submit_buffers = pool.buf_handles(); | |||
let submit_info = [ | |||
vk::SubmitInfo { | |||
command_buffer_count: submit_buffers.len() as u32, | |||
p_command_buffers: submit_buffers.as_ptr(), | |||
..Default::default() | |||
} | |||
]; | |||
self.device.queue_submit(**queue, &submit_info, vk::Fence::null())?; | |||
self.device.queue_wait_idle(**queue) | |||
} | |||
/// Transfers `data` from the client to the server. | |||
pub fn xfer_data<T>( | |||
&self, | |||
queue: &Queue, | |||
phys_device: &PhysicalDevice, | |||
data: &[T], | |||
) -> Result<(), ErrBufferCreate> { | |||
let size = dev_size_of(data); | |||
unsafe { | |||
let (handle, memory) = create_buffer( | |||
&self.device, | |||
phys_device, | |||
size, | |||
vk::BufferUsageFlags::TRANSFER_DST | | |||
vk::BufferUsageFlags::INDEX_BUFFER, | |||
vk::MemoryPropertyFlags::DEVICE_LOCAL, | |||
vk::BufferUsageFlags::TRANSFER_SRC, | |||
vk::MemoryPropertyFlags::HOST_VISIBLE | | |||
vk::MemoryPropertyFlags::HOST_COHERENT, | |||
)?; | |||
copy_buffer(src_handle, dst_handle, size, device.clone(), xfer_queue)?; | |||
let src = Self { handle, memory, device: self.device.clone() }; | |||
// TODO: express with Drop | |||
device.free_memory(src_memory, None); | |||
device.destroy_buffer(src_handle, None); | |||
src.write_data(data)?; | |||
(dst_handle, dst_memory) | |||
}; | |||
self.copy_buffer(&src, size, queue)?; | |||
} | |||
Ok(()) | |||
} | |||
/// Writes `data` to `self`. | |||
pub fn write_data<T>(&self, data: &[T]) -> Result<(), vk::Result> { | |||
let size = dev_size_of(data); | |||
unsafe { | |||
let flg = vk::MemoryMapFlags::empty(); | |||
let map = self.device.map_memory(self.memory, 0, size, flg)?; | |||
(map as *mut T).copy_from(data.as_ptr(), data.len()); | |||
self.device.unmap_memory(self.memory); | |||
} | |||
Ok(Rc::new(Self { handle, device, memory })) | |||
Ok(()) | |||
} | |||
} | |||
@@ -1,4 +1,7 @@ | |||
use crate::render::{Buffer, Device, Framebuffer, Pipeline, RenderPass}; | |||
use crate::render::{ | |||
Buffer, DescriptorPool, Device, Framebuffer, Pipeline, PipelineLayout, | |||
RenderPass, | |||
}; | |||
use ash::{version::DeviceV1_0, vk}; | |||
use std::rc::Rc; | |||
@@ -16,12 +19,13 @@ pub struct CommandPool { | |||
pub struct CommandBuffer { | |||
handle: vk::CommandBuffer, | |||
device: Rc<Device>, | |||
render_pass: Option<Rc<RenderPass>>, | |||
framebuffer: Option<Rc<Framebuffer>>, | |||
pipeline: Option<Rc<Pipeline>>, | |||
vertex_buffer: Option<Rc<Buffer>>, | |||
index_buffer: Option<Rc<Buffer>>, | |||
device: Rc<Device>, | |||
render_pass: Option<Rc<RenderPass>>, | |||
framebuffer: Option<Rc<Framebuffer>>, | |||
pipeline: Option<Rc<Pipeline>>, | |||
vertex_buffer: Option<Rc<Buffer>>, | |||
index_buffer: Option<Rc<Buffer>>, | |||
descriptor_pool: Option<Rc<DescriptorPool>>, | |||
} | |||
impl CommandPool { | |||
@@ -31,7 +35,7 @@ impl CommandPool { | |||
framebuffers: &[Rc<Framebuffer>], | |||
render_pass: Rc<RenderPass>, | |||
extent: vk::Extent2D, | |||
f: impl Fn(&mut CommandBuffer) + Copy, | |||
f: impl Fn(&mut CommandBuffer, usize) + Copy, | |||
) -> Result<Rc<Self>, vk::Result> { | |||
let (handle, buffers) = unsafe { | |||
Self::create_inner( | |||
@@ -46,14 +50,15 @@ impl CommandPool { | |||
buffers | |||
.iter() | |||
.zip(framebuffers.iter()) | |||
.map(|(&handle, framebuffer)| { | |||
.enumerate() | |||
.map(|(framebuffer_num, (&handle, framebuffer))| { | |||
Ok(CommandBuffer::create_graphics( | |||
handle, | |||
device.clone(), | |||
render_pass.clone(), | |||
framebuffer.clone(), | |||
extent, | |||
f, | |||
|cmd| f(cmd, framebuffer_num), | |||
)?) | |||
}) | |||
.collect::<Result<Vec<_>, vk::Result>>()?; | |||
@@ -166,6 +171,26 @@ impl CommandBuffer { | |||
} | |||
} | |||
pub fn bind_descriptor_pool( | |||
&mut self, | |||
descriptor_pool: Rc<DescriptorPool>, | |||
pipeline_layout: Rc<PipelineLayout>, | |||
which: usize, | |||
) { | |||
unsafe { | |||
self.device.cmd_bind_descriptor_sets( | |||
self.handle, | |||
vk::PipelineBindPoint::GRAPHICS, | |||
**pipeline_layout, | |||
0, | |||
&[*descriptor_pool.sets[which]], | |||
&[], | |||
); | |||
self.descriptor_pool = Some(descriptor_pool); | |||
} | |||
} | |||
pub fn draw(&self, num: usize) { | |||
unsafe { | |||
self.device.cmd_draw_indexed(self.handle, num as u32, 1, 0, 0, 0); | |||
@@ -221,11 +246,12 @@ impl CommandBuffer { | |||
let mut this = Self { | |||
handle, | |||
device, | |||
render_pass: Some(render_pass), | |||
framebuffer: Some(framebuffer), | |||
pipeline: None, | |||
vertex_buffer: None, | |||
index_buffer: None, | |||
render_pass: Some(render_pass), | |||
framebuffer: Some(framebuffer), | |||
pipeline: None, | |||
vertex_buffer: None, | |||
index_buffer: None, | |||
descriptor_pool: None, | |||
}; | |||
unsafe { | |||
@@ -260,11 +286,12 @@ impl CommandBuffer { | |||
let mut this = Self { | |||
handle, | |||
device, | |||
render_pass: None, | |||
framebuffer: None, | |||
pipeline: None, | |||
vertex_buffer: None, | |||
index_buffer: None, | |||
render_pass: None, | |||
framebuffer: None, | |||
pipeline: None, | |||
vertex_buffer: None, | |||
index_buffer: None, | |||
descriptor_pool: None, | |||
}; | |||
unsafe { | |||
@@ -0,0 +1,39 @@ | |||
use crate::render::{Device, Uniforms}; | |||
use ash::{version::DeviceV1_0, vk}; | |||
use std::rc::Rc; | |||
pub struct DescriptorSetLayout { | |||
handle: vk::DescriptorSetLayout, | |||
pub device: Rc<Device>, | |||
} | |||
impl DescriptorSetLayout { | |||
pub fn create(device: Rc<Device>) -> Result<Rc<Self>, vk::Result> { | |||
let create_info = vk::DescriptorSetLayoutCreateInfo { | |||
binding_count: Uniforms::BIND_DESC.len() as u32, | |||
p_bindings: Uniforms::BIND_DESC.as_ptr(), | |||
..Default::default() | |||
}; | |||
let handle = | |||
unsafe { device.create_descriptor_set_layout(&create_info, None)? }; | |||
Ok(Rc::new(Self { handle, device })) | |||
} | |||
} | |||
impl Drop for DescriptorSetLayout { | |||
fn drop(&mut self) { | |||
unsafe { | |||
self.device.destroy_descriptor_set_layout(self.handle, None); | |||
} | |||
} | |||
} | |||
impl std::ops::Deref for DescriptorSetLayout { | |||
type Target = vk::DescriptorSetLayout; | |||
fn deref(&self) -> &Self::Target { | |||
&self.handle | |||
} | |||
} | |||
// EOF |
@@ -0,0 +1,115 @@ | |||
use crate::render::{Buffer, DescriptorSetLayout, Device, Uniforms}; | |||
use ash::{version::DeviceV1_0, vk}; | |||
use std::rc::Rc; | |||
pub struct DescriptorSet { | |||
handle: vk::DescriptorSet, | |||
} | |||
pub struct DescriptorPool { | |||
handle: vk::DescriptorPool, | |||
pub device: Rc<Device>, | |||
pub buffers: Vec<Rc<Buffer>>, | |||
pub sets: Vec<DescriptorSet>, | |||
} | |||
impl DescriptorPool { | |||
pub fn create( | |||
device: Rc<Device>, | |||
buffers: Vec<Rc<Buffer>>, | |||
layout: Rc<DescriptorSetLayout>, | |||
) -> Result<Rc<Self>, vk::Result> { | |||
let size_info = [ | |||
vk::DescriptorPoolSize { | |||
ty: vk::DescriptorType::UNIFORM_BUFFER, | |||
descriptor_count: buffers.len() as u32, | |||
..Default::default() | |||
} | |||
]; | |||
let create_info = vk::DescriptorPoolCreateInfo { | |||
pool_size_count: size_info.len() as u32, | |||
p_pool_sizes: size_info.as_ptr(), | |||
max_sets: buffers.len() as u32, | |||
..Default::default() | |||
}; | |||
let handle = | |||
unsafe { device.create_descriptor_pool(&create_info, None)? }; | |||
let set_layouts = vec![**layout; buffers.len()]; | |||
let alloc_info = vk::DescriptorSetAllocateInfo { | |||
descriptor_pool: handle, | |||
descriptor_set_count: set_layouts.len() as u32, | |||
p_set_layouts: set_layouts.as_ptr(), | |||
..Default::default() | |||
}; | |||
let sets = unsafe { | |||
device | |||
.allocate_descriptor_sets(&alloc_info)? | |||
.iter() | |||
.map(|&handle| DescriptorSet { handle }) | |||
.collect::<Vec<_>>() | |||
}; | |||
let buffer_infos = | |||
buffers | |||
.iter() | |||
.map(|buffer| { | |||
vk::DescriptorBufferInfo { | |||
buffer: ***buffer, | |||
range: std::mem::size_of::<Uniforms>() as vk::DeviceSize, | |||
..Default::default() | |||
} | |||
}) | |||
.collect::<Vec<_>>(); | |||
let write_descriptors = | |||
sets | |||
.iter() | |||
.zip(&buffer_infos) | |||
.map(|(dst_set, buffer_info)| { | |||
vk::WriteDescriptorSet { | |||
dst_set: **dst_set, | |||
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER, | |||
descriptor_count: 1, | |||
p_buffer_info: &*buffer_info, | |||
..Default::default() | |||
} | |||
}) | |||
.collect::<Vec<_>>(); | |||
unsafe { | |||
device.update_descriptor_sets(&write_descriptors, &[]); | |||
} | |||
Ok(Rc::new(Self { handle, device, buffers, sets })) | |||
} | |||
} | |||
impl Drop for DescriptorPool { | |||
fn drop(&mut self) { | |||
unsafe { | |||
self.device.destroy_descriptor_pool(self.handle, None); | |||
} | |||
} | |||
} | |||
impl std::ops::Deref for DescriptorSet { | |||
type Target = vk::DescriptorSet; | |||
fn deref(&self) -> &Self::Target { | |||
&self.handle | |||
} | |||
} | |||
impl std::ops::Deref for DescriptorPool { | |||
type Target = vk::DescriptorPool; | |||
fn deref(&self) -> &Self::Target { | |||
&self.handle | |||
} | |||
} | |||
// EOF |
@@ -33,8 +33,6 @@ impl PipelineCreateInfo { | |||
render_pass: Rc<RenderPass>, | |||
extent: vk::Extent2D, | |||
) -> Self { | |||
let bind_desc = &Vertex::BIND_DESCR; | |||
let attr_desc = &Vertex::ATTR_DESCR; | |||
Self { | |||
layout, | |||
render_pass, | |||
@@ -54,10 +52,10 @@ impl PipelineCreateInfo { | |||
}, | |||
], | |||
vertex_input_state: vk::PipelineVertexInputStateCreateInfo { | |||
vertex_binding_description_count: bind_desc.len() as u32, | |||
p_vertex_binding_descriptions: bind_desc.as_ptr(), | |||
vertex_attribute_description_count: attr_desc.len() as u32, | |||
p_vertex_attribute_descriptions: attr_desc.as_ptr(), | |||
vertex_binding_description_count: Vertex::BIND_DESC.len() as u32, | |||
p_vertex_binding_descriptions: Vertex::BIND_DESC.as_ptr(), | |||
vertex_attribute_description_count: Vertex::ATTR_DESC.len() as u32, | |||
p_vertex_attribute_descriptions: Vertex::ATTR_DESC.as_ptr(), | |||
..Default::default() | |||
}, | |||
input_assembly_state: vk::PipelineInputAssemblyStateCreateInfo { | |||
@@ -82,7 +80,7 @@ impl PipelineCreateInfo { | |||
polygon_mode: vk::PolygonMode::FILL, | |||
line_width: 1.0, | |||
cull_mode: vk::CullModeFlags::BACK, | |||
front_face: vk::FrontFace::CLOCKWISE, | |||
front_face: vk::FrontFace::COUNTER_CLOCKWISE, | |||
..Default::default() | |||
}, | |||
multisample_state: vk::PipelineMultisampleStateCreateInfo { | |||
@@ -1,27 +1,37 @@ | |||
use crate::render::Device; | |||
use crate::render::DescriptorSetLayout; | |||
use ash::{version::DeviceV1_0, vk}; | |||
use std::rc::Rc; | |||
pub struct PipelineLayout { | |||
handle: vk::PipelineLayout, | |||
pub device: Rc<Device>, | |||
pub descriptor: Rc<DescriptorSetLayout>, | |||
} | |||
impl PipelineLayout { | |||
pub fn create(device: Rc<Device>) -> Result<Rc<Self>, vk::Result> { | |||
let create_info = vk::PipelineLayoutCreateInfo::default(); | |||
pub fn create( | |||
descriptor: Rc<DescriptorSetLayout>, | |||
) -> Result<Rc<Self>, vk::Result> { | |||
let set_layouts = [ **descriptor ]; | |||
let handle = | |||
unsafe { device.create_pipeline_layout(&create_info, None)? }; | |||
Ok(Rc::new(Self { handle, device })) | |||
let create_info = vk::PipelineLayoutCreateInfo { | |||
set_layout_count: set_layouts.len() as u32, | |||
p_set_layouts: set_layouts.as_ptr(), | |||
..Default::default() | |||
}; | |||
let handle = unsafe { | |||
descriptor.device.create_pipeline_layout(&create_info, None)? | |||
}; | |||
Ok(Rc::new(Self { handle, descriptor })) | |||
} | |||
} | |||
impl Drop for PipelineLayout { | |||
fn drop(&mut self) { | |||
unsafe { | |||
self.device.destroy_pipeline_layout(self.handle, None); | |||
self.descriptor.device.destroy_pipeline_layout(self.handle, None); | |||
} | |||
} | |||
} | |||
@@ -0,0 +1,23 @@ | |||
use ash::vk; | |||
use cgmath::Matrix4; | |||
#[repr(C, align(16))] | |||
pub struct Uniforms { | |||
pub object: Matrix4<f32>, | |||
pub camera: Matrix4<f32>, | |||
pub projection: Matrix4<f32>, | |||
} | |||
impl Uniforms { | |||
pub const BIND_DESC: [vk::DescriptorSetLayoutBinding; 1] = [ | |||
vk::DescriptorSetLayoutBinding { | |||
binding: 0, | |||
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER, | |||
descriptor_count: 1, | |||
stage_flags: vk::ShaderStageFlags::VERTEX, | |||
p_immutable_samplers: std::ptr::null(), | |||
} | |||
]; | |||
} | |||
// EOF |
@@ -8,7 +8,7 @@ pub struct Vertex { | |||
} | |||
impl Vertex { | |||
pub const BIND_DESCR: [vk::VertexInputBindingDescription; 1] = [ | |||
pub const BIND_DESC: [vk::VertexInputBindingDescription; 1] = [ | |||
vk::VertexInputBindingDescription { | |||
binding: 0, | |||
stride: std::mem::size_of::<Self>() as u32, | |||
@@ -16,7 +16,7 @@ impl Vertex { | |||
} | |||
]; | |||
pub const ATTR_DESCR: [vk::VertexInputAttributeDescription; 2] = [ | |||
pub const ATTR_DESC: [vk::VertexInputAttributeDescription; 2] = [ | |||
vk::VertexInputAttributeDescription { | |||
location: 0, | |||
binding: 0, | |||