Browse Source

changes to uniform and vertex assignments, add test code for skeletal meshes

master
Alison Watson 5 months ago
parent
commit
4def7f6f7b
18 changed files with 441 additions and 200 deletions
  1. +1
    -1
      glsl/main.frag
  2. +26
    -8
      glsl/main.vert
  3. +1
    -0
      source/framework/data.rs
  4. +178
    -28
      source/framework/data/model.rs
  5. +14
    -0
      source/framework/data/read.rs
  6. +10
    -0
      source/framework/data/uniforms.rs
  7. +2
    -37
      source/framework/data/vertex.rs
  8. +2
    -7
      source/framework/render.rs
  9. +5
    -6
      source/framework/render/buffer.rs
  10. +3
    -5
      source/framework/render/descriptorlayout.rs
  11. +59
    -46
      source/framework/render/descriptorpool.rs
  12. +1
    -1
      source/framework/render/image.rs
  13. +88
    -0
      source/framework/render/misc.rs
  14. +13
    -0
      source/framework/render/model.rs
  15. +6
    -7
      source/framework/render/pipeline.rs
  16. +0
    -11
      source/framework/render/sampler.rs
  17. +0
    -24
      source/framework/render/uniforms.rs
  18. +32
    -19
      source/main_test/entry.rs

+ 1
- 1
glsl/main.frag View File

@@ -3,7 +3,7 @@ layout(location = 1) in vec4 vertex_color;

layout(location = 0) out vec4 frag_color;

layout(binding = 1) uniform sampler2D u_sampler;
layout(binding = 2) uniform sampler2D u_sampler;

void main() {
frag_color = texture(u_sampler, vertex_texcoord.xy);


+ 26
- 8
glsl/main.vert View File

@@ -1,24 +1,42 @@
layout(location = 0) in vec3 in_position;
layout(location = 1) in vec3 in_texcoord;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in vec4 in_color;
layout(location = 3) in vec4 in_blendindices;
layout(location = 4) in vec4 in_blendweights;
layout(location = 5) in vec4 in_color;

layout(location = 0) out vec3 vertex_texcoord;
layout(location = 1) out vec4 vertex_color;

layout(binding = 0) uniform Uniforms {
mat4 obj;
mat4 cam;
mat4 prj;
mat4 object;
mat4 camera;
mat4 projec;
} uniforms;

layout(binding = 1) uniform BoneMatrices {
mat4 matrices[128];
} bones;

void main() {
gl_Position =
uniforms.prj *
uniforms.cam *
uniforms.obj *
/*
mat4 vertex_matrix =
bones.matrices[int(in_blendindices.x)] * in_blendweights.x +
bones.matrices[int(in_blendindices.y)] * in_blendweights.y +
bones.matrices[int(in_blendindices.z)] * in_blendweights.z +
bones.matrices[int(in_blendindices.w)] * in_blendweights.w;
*/

vec4 position =
//vertex_matrix *
vec4(in_position, 1.0);

gl_Position =
uniforms.projec *
uniforms.camera *
uniforms.object *
position;

vertex_texcoord = in_texcoord;
vertex_color = in_color;
}


+ 1
- 0
source/framework/data.rs View File

@@ -4,6 +4,7 @@ pub mod image;
pub mod model;
pub mod read;
pub mod text;
pub mod uniforms;
pub mod vertex;
pub mod vfs;



+ 178
- 28
source/framework/data/model.rs View File

@@ -2,10 +2,11 @@ use crate::{
data::{read, vertex::Vertex},
ffi,
};
use glam::{Vec3A, Vec4};
use glam::{Mat4, Quat, Vec3, Vec3A, Vec4};
use smol_str::SmolStr;
use std::{
collections::HashMap,
convert::TryInto,
io::{self, Read, Seek, SeekFrom},
ops::Range,
str::Utf8Error,
@@ -32,6 +33,8 @@ struct VertexZipper {
pos_v: std::vec::IntoIter<Vec3A>,
tex_v: std::vec::IntoIter<Vec3A>,
nrm_v: std::vec::IntoIter<Vec3A>,
idx_v: std::vec::IntoIter<Vec4>,
wgt_v: std::vec::IntoIter<Vec4>,
clr_v: std::vec::IntoIter<Vec4>,
}

@@ -41,26 +44,56 @@ pub struct Mesh {
idx: Range<usize>,
}

pub struct Joint {
//nam: SmolStr,
par: Option<usize>,
mat: Mat4,
}

pub struct Pose {
par: Option<usize>,
msk: u32,
ofs: [f32; 10],
scl: [f32; 10],
}

/// Data to be uploaded to the GPU. Separate from Model so that it may
/// be dropped after upload.
pub struct ModelData {
pub vtx: Vec<Vertex>,
pub idx: Vec<u32>,
}

/// Run-time model data. Anything necessary for passing commands to
/// the GPU.
pub struct Model {
meshes: HashMap<SmolStr, Mesh>,
num_frmc: usize,
frames: Vec<u16>,
joints: Vec<Joint>,
poses: Vec<Pose>,
}

impl Iterator for VertexZipper {
type Item = (Option<Vec3A>, Option<Vec3A>, Option<Vec3A>, Option<Vec4>);
type Item = (
Option<Vec3A>,
Option<Vec3A>,
Option<Vec3A>,
Option<Vec4>,
Option<Vec4>,
Option<Vec4>,
);

fn next(&mut self) -> Option<Self::Item> {
match (
self.pos_v.next(),
self.tex_v.next(),
self.nrm_v.next(),
self.idx_v.next(),
self.wgt_v.next(),
self.clr_v.next(),
) {
(None, None, None, None) => None,
(None, None, None, None, None, None) => None,
tuple => Some(tuple),
}
}
@@ -97,14 +130,14 @@ impl Mesh {
}

impl Model {
pub fn read<R>(rd: &mut R) -> Result<(Self, ModelData), ErrModelRead>
pub fn read<R>(rd: &mut R) -> Result<(Self, ModelData), Err>
where
R: Read + Seek,
{
fn from_stab(stab: &[u8], sbeg: usize) -> Result<&str, ErrModelRead> {
let sbeg = stab.get(sbeg..).ok_or(ErrModelRead::TextOffset)?;
fn from_stab(stab: &[u8], sbeg: usize) -> Result<&str, Err> {
let sbeg = stab.get(sbeg..).ok_or(Err::TextOffset)?;
let send = ffi::end_of_cstr(sbeg);
let sbeg = sbeg.get(..send).ok_or(ErrModelRead::TextOffset)?;
let sbeg = sbeg.get(..send).ok_or(Err::TextOffset)?;
Ok(std::str::from_utf8(sbeg)?)
}

@@ -112,7 +145,7 @@ impl Model {
rd.read_exact(&mut head)?;

if &head[0..20] != b"INTERQUAKEMODEL\0\x02\0\0\0" {
return Err(ErrModelRead::Magic);
return Err(Err::Magic);
}

let num_text = read::u32le_sz(&head, 28);
@@ -124,28 +157,27 @@ impl Model {
let ofs_vinf = read::u32le_64(&head, 52);
let num_tris = read::u32le_sz(&head, 56);
let ofs_tris = read::u32le_64(&head, 60);
/*
let ofs_adja = read::u32le_64(&head, 64);
let num_join = read::u32le_sz(&head, 68);
let ofs_join = read::u32le_64(&head, 72);
let num_pose = read::u32le_sz(&head, 76);
let ofs_pose = read::u32le_64(&head, 80);
let num_anim = read::u32le_sz(&head, 84);
let ofs_anim = read::u32le_64(&head, 88);
//let num_anim = read::u32le_sz(&head, 84);
//let ofs_anim = read::u32le_64(&head, 88);
let num_frms = read::u32le_sz(&head, 92);
let num_frmc = read::u32le_sz(&head, 96);
let ofs_frms = read::u32le_64(&head, 100);
let ofs_bnds = read::u32le_64(&head, 104);
let num_cmmt = read::u32le_sz(&head, 108);
let ofs_cmmt = read::u32le_64(&head, 112);
let num_exts = read::u32le_sz(&head, 116);
let ofs_exts = read::u32le_64(&head, 120);
*/
//let ofs_bnds = read::u32le_64(&head, 104);

if num_join != 0 && num_pose != 0 && num_pose != num_join {
return Err(Err::NumPoses);
}

// collect vertex info
let mut pos_v = Vec::with_capacity(num_vert);
let mut tex_v = Vec::with_capacity(num_vert);
let mut nrm_v = Vec::with_capacity(num_vert);
let mut idx_v = Vec::with_capacity(num_vert);
let mut wgt_v = Vec::with_capacity(num_vert);
let mut clr_v = Vec::with_capacity(num_vert);

rd.seek(SeekFrom::Start(ofs_vinf))?;
@@ -184,10 +216,22 @@ impl Model {
// ignore tangents for now
}
4 => {
// ignore blend indices for now
for idx in read::hunk(rd, 4 * num_vert)?.chunks(4) {
let idx0 = f32::from(idx[0]);
let idx1 = f32::from(idx[1]);
let idx2 = f32::from(idx[2]);
let idx3 = f32::from(idx[3]);
idx_v.push(Vec4::new(idx0, idx1, idx2, idx3));
}
}
5 => {
// ignore blend weights for now
for wgt in read::hunk(rd, 4 * num_vert)?.chunks(4) {
let wgt0 = f32::from(wgt[0]) / 255.0;
let wgt1 = f32::from(wgt[1]) / 255.0;
let wgt2 = f32::from(wgt[2]) / 255.0;
let wgt3 = f32::from(wgt[3]) / 255.0;
wgt_v.push(Vec4::new(wgt0, wgt1, wgt2, wgt3));
}
}
6 => {
for clr in read::hunk(rd, 4 * num_vert)?.chunks(4) {
@@ -198,7 +242,7 @@ impl Model {
clr_v.push(Vec4::new(r, g, b, a));
}
}
_ => return Err(ErrModelRead::UnknownType),
_ => return Err(Err::UnknownType),
}
}

@@ -207,17 +251,21 @@ impl Model {
pos_v: pos_v.into_iter(),
tex_v: tex_v.into_iter(),
nrm_v: nrm_v.into_iter(),
idx_v: idx_v.into_iter(),
wgt_v: wgt_v.into_iter(),
clr_v: clr_v.into_iter(),
};

let mut vert_dat = Vec::with_capacity(num_vert);

for (pos, tex, nrm, clr) in zipper {
let pos = pos.unwrap_or(Vec3A::new(0.0, 0.0, 0.0));
let tex = tex.unwrap_or(Vec3A::new(0.0, 0.0, 0.0));
let nrm = nrm.unwrap_or(Vec3A::new(0.0, 0.0, 0.0));
let clr = clr.unwrap_or(Vec4::new(1.0, 1.0, 1.0, 1.0));
vert_dat.push(Vertex { pos, tex, nrm, clr });
for (pos, tex, nrm, idx, wgt, clr) in zipper {
let pos = pos.unwrap_or_else(|| Vec3A::new(0.0, 0.0, 0.0));
let tex = tex.unwrap_or_else(|| Vec3A::new(0.0, 0.0, 0.0));
let nrm = nrm.unwrap_or_else(|| Vec3A::new(0.0, 0.0, 0.0));
let idx = idx.unwrap_or_else(|| Vec4::new(0.0, 0.0, 0.0, 0.0));
let wgt = wgt.unwrap_or_else(|| Vec4::new(0.0, 0.0, 0.0, 0.0));
let clr = clr.unwrap_or_else(|| Vec4::new(1.0, 1.0, 1.0, 1.0));
vert_dat.push(Vertex { pos, tex, nrm, idx, wgt, clr });
}

// collect index info
@@ -258,7 +306,109 @@ impl Model {
meshes.insert(nam, Mesh { mat, vtx, idx });
}

Ok((Self { meshes }, ModelData { vtx: vert_dat, idx: indx_dat }))
// collect joint info
let mut joints = Vec::with_capacity(num_join);

rd.seek(SeekFrom::Start(ofs_join))?;

for join in read::hunk(rd, num_join * 4 * 12)?.chunks(4 * 12) {
let trs = &mut [0.0; 10];
//let nam = read::u32le_sz(join, 0);
let par = read::u32le_sz(join, 4);
let trs = read::array(read::f32le_32, join, trs, 4, 8);

//let nam = SmolStr::new(from_stab(&stab, nam)?);
let par = if par & 0x8000_0000 != 0 { None } else { Some(par) };
let mat = Mat4::from_scale_rotation_translation(
Vec3::new(trs[0], trs[1], trs[2]),
Quat::from_xyzw(trs[3], trs[4], trs[5], trs[6]),
Vec3::new(trs[7], trs[8], trs[9]),
);

joints.push(Joint { /*nam,*/ par, mat });
}

// collect frames
let mut frames = Vec::with_capacity(num_frms * num_frmc);

rd.seek(SeekFrom::Start(ofs_frms))?;

for samp in read::hunk(rd, num_frms * num_frmc * 2)?.chunks(2) {
frames.push(read::u16le_16(samp, 0));
}

// collect pose info
let mut poses = Vec::with_capacity(num_pose);

rd.seek(SeekFrom::Start(ofs_pose))?;

for pose in read::hunk(rd, num_pose * 4 * 22)?.chunks(4 * 22) {
let ofs = &mut [0.0; 10];
let scl = &mut [0.0; 10];
let par = read::u32le_sz(pose, 0);
let msk = read::u32le_32(pose, 4);
let ofs = read::array(read::f32le_32, pose, ofs, 4, 8);
let scl = read::array(read::f32le_32, pose, scl, 4, 48);
let par = if par & 0x8000_0000 != 0 { None } else { Some(par) };

poses.push(Pose {
par,
msk,
ofs: ofs.try_into().unwrap(),
scl: scl.try_into().unwrap(),
});
}

Ok((
Self { meshes, num_frmc, frames, joints, poses },
ModelData { vtx: vert_dat, idx: indx_dat },
))
}

pub fn num_frames(&self) -> usize {
self.frames.len() / self.num_frmc
}

pub fn frame(&self, joint: usize, frame: usize) -> Option<Mat4> {
Some(self.joint_mat(joint)? * self.pose_mat(joint, frame)?)
}

pub fn pose_mat(&self, joint: usize, frame: usize) -> Option<Mat4> {
let pose = self.poses.get(joint)?;

let mut trs = [0.0; 10];

let mut frames = self.frames.iter().skip(frame * self.num_frmc);

for i in 0..10 {
if pose.msk & 1 << i != 0 {
let frame = f32::from(*frames.next()?);
trs[i] = pose.ofs[i] + frame * pose.scl[i];
}
}

let mut mat = Mat4::from_scale_rotation_translation(
Vec3::new(trs[0], trs[1], trs[2]),
Quat::from_xyzw(trs[3], trs[4], trs[5], trs[6]),
Vec3::new(trs[7], trs[8], trs[9]),
);

if let Some(parent) = pose.par {
mat = self.pose_mat(parent, frame)? * mat;
}

Some(mat)
}

fn joint_mat(&self, joint: usize) -> Option<Mat4> {
let jnt = self.joints.get(joint)?;
let mut mat = jnt.mat;

if let Some(parent) = jnt.par {
mat = self.joint_mat(parent)? * mat;
}

Some(mat)
}
}



+ 14
- 0
source/framework/data/read.rs View File

@@ -24,6 +24,20 @@ pub fn f32le_32(b: &[u8], p: usize) -> f32 {
f32::from_le_bytes([b[p], b[p + 1], b[p + 2], b[p + 3]])
}

pub fn array<'a, 'b, T>(
f: impl Fn(&[u8], usize) -> T,
b: &'a [u8],
v: &'b mut [T],
step: usize,
beg: usize,
) -> &'b [T] {
for (i, p) in (beg..beg + v.len() * step).step_by(step).enumerate() {
v[i] = f(b, p);
}

v
}

pub fn hunk(rd: &mut impl Read, size: usize) -> io::Result<Vec<u8>> {
let mut data = Vec::with_capacity(size);
unsafe {


+ 10
- 0
source/framework/data/uniforms.rs View File

@@ -0,0 +1,10 @@
use glam::Mat4;

#[repr(C)]
pub struct Uniforms {
pub object: Mat4,
pub camera: Mat4,
pub projec: Mat4,
}

// EOF

+ 2
- 37
source/framework/data/vertex.rs View File

@@ -1,4 +1,3 @@
use ash::vk;
use glam::{Vec3A, Vec4};

#[repr(C)]
@@ -6,43 +5,9 @@ pub struct Vertex {
pub pos: Vec3A,
pub tex: Vec3A,
pub nrm: Vec3A,
pub idx: Vec4,
pub wgt: Vec4,
pub clr: Vec4,
}

impl Vertex {
pub const BIND_DESC: [vk::VertexInputBindingDescription; 1] =
[vk::VertexInputBindingDescription {
binding: 0,
stride: std::mem::size_of::<Self>() as u32,
input_rate: vk::VertexInputRate::VERTEX,
}];

pub const ATTR_DESC: [vk::VertexInputAttributeDescription; 4] = [
vk::VertexInputAttributeDescription {
location: 0,
binding: 0,
format: vk::Format::R32G32B32_SFLOAT,
offset: 0,
},
vk::VertexInputAttributeDescription {
location: 1,
binding: 0,
format: vk::Format::R32G32B32_SFLOAT,
offset: 16,
},
vk::VertexInputAttributeDescription {
location: 2,
binding: 0,
format: vk::Format::R32G32B32_SFLOAT,
offset: 32,
},
vk::VertexInputAttributeDescription {
location: 3,
binding: 0,
format: vk::Format::R32G32B32A32_SFLOAT,
offset: 48,
},
];
}

// EOF

+ 2
- 7
source/framework/render.rs View File

@@ -21,7 +21,8 @@ mod shader;
mod spir;
mod surface;
mod swapchain;
mod uniforms;

pub mod misc;

pub use self::{
buffer::Buffer,
@@ -50,12 +51,6 @@ pub use self::{
spir::Spir,
surface::Surface,
swapchain::Swapchain,
uniforms::Uniforms,
};

/// Returns the size of `data` as a `vk::DeviceSize`.
pub(self) const fn dev_size_of<T>(data: &[T]) -> ash::vk::DeviceSize {
(std::mem::size_of::<T>() * data.len()) as ash::vk::DeviceSize
}

// EOF

+ 5
- 6
source/framework/render/buffer.rs View File

@@ -1,8 +1,6 @@
use crate::{
data::{self, vertex::Vertex},
render::{
dev_size_of, CommandPool, Device, ErrAllocMem, GetDevice, Uniforms,
},
render::{misc::dev_size_of, CommandPool, Device, ErrAllocMem, GetDevice},
};
use ash::{version::DeviceV1_0, vk};
use std::{ptr, rc::Rc};
@@ -132,9 +130,10 @@ impl Buffer {
}

/// Creates a uniform buffer.
pub fn create_uniform(device: Rc<Device>) -> Result<Rc<Self>, ErrAllocMem> {
let size = std::mem::size_of::<Uniforms>() as vk::DeviceSize;

pub fn create_uniform(
device: Rc<Device>,
size: vk::DeviceSize,
) -> Result<Rc<Self>, ErrAllocMem> {
let (handle, memory) = unsafe {
create_buffer(
&device,


+ 3
- 5
source/framework/render/descriptorlayout.rs View File

@@ -1,4 +1,4 @@
use crate::render::{Device, GetDevice, Sampler, Uniforms};
use crate::render::{misc, Device, GetDevice};
use ash::{version::DeviceV1_0, vk};
use std::rc::Rc;

@@ -16,11 +16,9 @@ impl GetDevice for DescriptorSetLayout {

impl DescriptorSetLayout {
pub fn create(device: Rc<Device>) -> Result<Rc<Self>, vk::Result> {
let descs = [Uniforms::BIND_DESC, Sampler::BIND_DESC];

let create_info = vk::DescriptorSetLayoutCreateInfo {
binding_count: descs.len() as u32,
p_bindings: descs.as_ptr(),
binding_count: misc::DSC_BIND_DESC.len() as u32,
p_bindings: misc::DSC_BIND_DESC.as_ptr(),
..Default::default()
};



+ 59
- 46
source/framework/render/descriptorpool.rs View File

@@ -1,6 +1,5 @@
use crate::render::{
Buffer, DescriptorSetLayout, Device, GetDevice, ImageView, Sampler,
Uniforms,
misc, Buffer, DescriptorSetLayout, Device, GetDevice, ImageView, Sampler,
};
use ash::{version::DeviceV1_0, vk};
use std::rc::Rc;
@@ -9,7 +8,7 @@ pub struct DescriptorPool {
handle: vk::DescriptorPool,

pub layout: Rc<DescriptorSetLayout>,
pub buffers: Vec<Rc<Buffer>>,
pub buffers: Vec<(Rc<Buffer>, Rc<Buffer>)>,
pub sets: Vec<vk::DescriptorSet>,
pub image_view: Rc<ImageView>,
pub sampler: Rc<Sampler>,
@@ -24,11 +23,15 @@ impl GetDevice for DescriptorPool {
impl DescriptorPool {
pub fn create(
layout: Rc<DescriptorSetLayout>,
buffers: Vec<Rc<Buffer>>,
buffers: Vec<(Rc<Buffer>, Rc<Buffer>)>,
image_view: Rc<ImageView>,
sampler: Rc<Sampler>,
) -> Result<Rc<Self>, vk::Result> {
let size_info = [
vk::DescriptorPoolSize {
ty: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: buffers.len() as u32,
},
vk::DescriptorPoolSize {
ty: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: buffers.len() as u32,
@@ -62,48 +65,58 @@ impl DescriptorPool {
let sets =
unsafe { layout.get_device().allocate_descriptor_sets(&alloc_info)? };

let write_infos = buffers
.iter()
.map(|buffer| {
(
vk::DescriptorBufferInfo {
buffer: ***buffer,
range: std::mem::size_of::<Uniforms>() as vk::DeviceSize,
..Default::default()
},
vk::DescriptorImageInfo {
sampler: **sampler,
image_view: **image_view,
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
},
)
})
.collect::<Vec<_>>();

let write_descriptors = sets
.iter()
.zip(&write_infos)
.flat_map(|(dst_set, (buffer_info, image_info))| {
vec![
vk::WriteDescriptorSet {
dst_set: *dst_set,
dst_binding: Uniforms::BIND_IDEN,
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: 1,
p_buffer_info: &*buffer_info,
..Default::default()
},
vk::WriteDescriptorSet {
dst_set: *dst_set,
dst_binding: Sampler::BIND_IDEN,
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptor_count: 1,
p_image_info: &*image_info,
..Default::default()
},
]
})
.collect::<Vec<_>>();
let mut write_infos = Vec::with_capacity(buffers.len());

for (ufm_buf, bon_buf) in buffers.iter() {
write_infos.push((
vk::DescriptorBufferInfo {
buffer: ***ufm_buf,
range: misc::UFM_BIND_SIZE,
..Default::default()
},
vk::DescriptorBufferInfo {
buffer: ***bon_buf,
range: misc::BON_BIND_SIZE,
..Default::default()
},
vk::DescriptorImageInfo {
sampler: **sampler,
image_view: **image_view,
image_layout: vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
},
));
}

let mut write_descriptors = Vec::with_capacity(sets.len() * 3);

for (dst_set, infos) in sets.iter().zip(&write_infos) {
write_descriptors.push(vk::WriteDescriptorSet {
dst_set: *dst_set,
dst_binding: misc::UFM_BIND_IDEN,
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: 1,
p_buffer_info: &infos.0,
..Default::default()
});

write_descriptors.push(vk::WriteDescriptorSet {
dst_set: *dst_set,
dst_binding: misc::BON_BIND_IDEN,
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: 1,
p_buffer_info: &infos.1,
..Default::default()
});

write_descriptors.push(vk::WriteDescriptorSet {
dst_set: *dst_set,
dst_binding: misc::SMP_BIND_IDEN,
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptor_count: 1,
p_image_info: &infos.2,
..Default::default()
});
}

unsafe {
layout.get_device().update_descriptor_sets(&write_descriptors, &[]);


+ 1
- 1
source/framework/render/image.rs View File

@@ -1,7 +1,7 @@
use crate::{
data::image::MipImage,
render::{
dev_size_of, Buffer, CommandPool, Device, ErrAllocMem, GetDevice,
misc::dev_size_of, Buffer, CommandPool, Device, ErrAllocMem, GetDevice,
Swapchain,
},
};


+ 88
- 0
source/framework/render/misc.rs View File

@@ -0,0 +1,88 @@
use crate::data::{uniforms::Uniforms, vertex::Vertex};
use ash::vk;
use glam::Mat4;
use std::mem::size_of;

/// Returns the size of `data` as a `vk::DeviceSize`.
pub const fn dev_size_of<T>(data: &[T]) -> ash::vk::DeviceSize {
(size_of::<T>() * data.len()) as ash::vk::DeviceSize
}

pub const UFM_BIND_SIZE: vk::DeviceSize = size_of::<Uniforms>() as _;
pub const BON_BIND_SIZE: vk::DeviceSize = size_of::<[Mat4; 128]>() as _;

pub const UFM_BIND_IDEN: u32 = 0;
pub const BON_BIND_IDEN: u32 = 1;
pub const SMP_BIND_IDEN: u32 = 2;

pub const DSC_BIND_DESC: [vk::DescriptorSetLayoutBinding; 3] = [
vk::DescriptorSetLayoutBinding {
binding: UFM_BIND_IDEN,
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: 1,
stage_flags: vk::ShaderStageFlags::VERTEX,
p_immutable_samplers: std::ptr::null(),
},
vk::DescriptorSetLayoutBinding {
binding: BON_BIND_IDEN,
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: 1,
stage_flags: vk::ShaderStageFlags::VERTEX,
p_immutable_samplers: std::ptr::null(),
},
vk::DescriptorSetLayoutBinding {
binding: SMP_BIND_IDEN,
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptor_count: 1,
stage_flags: vk::ShaderStageFlags::FRAGMENT,
p_immutable_samplers: std::ptr::null(),
},
];

pub const VTX_BIND_DESC: [vk::VertexInputBindingDescription; 1] =
[vk::VertexInputBindingDescription {
binding: 0,
stride: size_of::<Vertex>() as u32,
input_rate: vk::VertexInputRate::VERTEX,
}];

pub const VTX_ATTR_DESC: [vk::VertexInputAttributeDescription; 6] = [
vk::VertexInputAttributeDescription {
location: 0,
binding: 0,
format: vk::Format::R32G32B32_SFLOAT,
offset: 0,
},
vk::VertexInputAttributeDescription {
location: 1,
binding: 0,
format: vk::Format::R32G32B32_SFLOAT,
offset: 16,
},
vk::VertexInputAttributeDescription {
location: 2,
binding: 0,
format: vk::Format::R32G32B32_SFLOAT,
offset: 32,
},
vk::VertexInputAttributeDescription {
location: 3,
binding: 0,
format: vk::Format::R32G32B32A32_SFLOAT,
offset: 48,
},
vk::VertexInputAttributeDescription {
location: 4,
binding: 0,
format: vk::Format::R32G32B32A32_SFLOAT,
offset: 64,
},
vk::VertexInputAttributeDescription {
location: 5,
binding: 0,
format: vk::Format::R32G32B32A32_SFLOAT,
offset: 80,
},
];

// EOF

+ 13
- 0
source/framework/render/model.rs View File

@@ -3,6 +3,7 @@ use crate::{
render::{Buffer, CommandPool, Device, ErrAllocMem, GetDevice},
};
use ash::{version::DeviceV1_0, vk};
use glam::Mat4;
use std::rc::Rc;

#[derive(Error, Debug)]
@@ -74,6 +75,18 @@ impl Model {
Err(ErrModelDraw::NoMesh(mesh.to_owned()))
}
}

pub fn frame_matrices(&self, frame: usize) -> [Mat4; 128] {
let mut matrices = [Mat4::identity(); 128];
let mut joint = 0;

while let Some(mat) = self.model.frame(joint, frame) {
matrices[joint] = mat;
joint += 1;
}

matrices
}
}

// EOF

+ 6
- 7
source/framework/render/pipeline.rs View File

@@ -1,6 +1,5 @@
use crate::{
data::vertex::Vertex,
render::{Device, GetDevice, PipelineLayout, RenderPass, ShaderModule},
use crate::render::{
misc, Device, GetDevice, PipelineLayout, RenderPass, ShaderModule,
};
use ash::{version::DeviceV1_0, vk};
use std::rc::Rc;
@@ -87,10 +86,10 @@ impl Pipeline {
];

let vertex_input_state = vk::PipelineVertexInputStateCreateInfo {
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(),
vertex_binding_description_count: misc::VTX_BIND_DESC.len() as u32,
p_vertex_binding_descriptions: misc::VTX_BIND_DESC.as_ptr(),
vertex_attribute_description_count: misc::VTX_ATTR_DESC.len() as u32,
p_vertex_attribute_descriptions: misc::VTX_ATTR_DESC.as_ptr(),
..Default::default()
};



+ 0
- 11
source/framework/render/sampler.rs View File

@@ -15,17 +15,6 @@ impl GetDevice for Sampler {
}

impl Sampler {
pub const BIND_IDEN: u32 = 1;

pub const BIND_DESC: vk::DescriptorSetLayoutBinding =
vk::DescriptorSetLayoutBinding {
binding: Self::BIND_IDEN,
descriptor_type: vk::DescriptorType::COMBINED_IMAGE_SAMPLER,
descriptor_count: 1,
stage_flags: vk::ShaderStageFlags::FRAGMENT,
p_immutable_samplers: std::ptr::null(),
};

pub fn create(
device: Rc<Device>,
conf: &Conf,


+ 0
- 24
source/framework/render/uniforms.rs View File

@@ -1,24 +0,0 @@
use ash::vk;
use glam::Mat4;

#[repr(C)]
pub struct Uniforms {
pub object: Mat4,
pub camera: Mat4,
pub projection: Mat4,
}

impl Uniforms {
pub const BIND_IDEN: u32 = 0;

pub const BIND_DESC: vk::DescriptorSetLayoutBinding =
vk::DescriptorSetLayoutBinding {
binding: Self::BIND_IDEN,
descriptor_type: vk::DescriptorType::UNIFORM_BUFFER,
descriptor_count: 1,
stage_flags: vk::ShaderStageFlags::VERTEX,
p_immutable_samplers: std::ptr::null(),
};
}

// EOF

+ 32
- 19
source/main_test/entry.rs View File

@@ -4,11 +4,11 @@ use blonkus_fw::{
data::{self, vfs},
hal, lg, log, meta,
render::{
self, Buffer, CommandBuffers, CommandPool, DescriptorPool,
self, misc, Buffer, CommandBuffers, CommandPool, DescriptorPool,
DescriptorSetLayout, Device, ErrAllocMem, Fence, Framebuffer, GetDevice,
Image, ImageView, IndepImage, Instance, Model, PhysicalDevice, Pipeline,
PipelineLayout, Queue, QueueFamilyInfo, RenderPass, Sampler, Semaphore,
ShaderModule, Spir, Surface, Swapchain, Uniforms,
ShaderModule, Spir, Surface, Swapchain,
},
};
use glam::{Mat4, Quat, Vec3, Vec4};
@@ -52,6 +52,8 @@ impl GetDevice for SwapchainData<'_, '_> {

impl<'a> SwapchainData<'a, '_> {
fn create(sc_info: SwapchainInfo<'a>) -> Result<Self, ErrAllocMem> {
let device = sc_info.get_device();

let swapchain = Swapchain::create(
sc_info.queue_graphics.clone(),
sc_info.queue_surface.clone(),
@@ -74,7 +76,7 @@ impl<'a> SwapchainData<'a, '_> {
let depth_view = ImageView::create(depth_buffer.clone())?;

let render_pass = RenderPass::create(
sc_info.get_device().clone(),
device.clone(),
swapchain.format,
depth_buffer.info().format,
)?;
@@ -96,8 +98,13 @@ impl<'a> SwapchainData<'a, '_> {

let ufm_buffers = framebuffers
.iter()
.map(|_| Buffer::create_uniform(sc_info.get_device().clone()))
.collect::<Result<_, _>>()?;
.map(|_| {
Ok((
Buffer::create_uniform(device.clone(), misc::UFM_BIND_SIZE)?,
Buffer::create_uniform(device.clone(), misc::BON_BIND_SIZE)?,
))
})
.collect::<Result<Vec<(Rc<Buffer>, Rc<Buffer>)>, ErrAllocMem>>()?;

let descriptor_pool = DescriptorPool::create(
sc_info.layout.descriptor.clone(),
@@ -132,7 +139,7 @@ impl<'a> SwapchainData<'a, '_> {
let begin_info = vk::CommandBufferBeginInfo::default();

unsafe {
sc_info.get_device().begin_command_buffer(buf, &begin_info)?;
device.begin_command_buffer(buf, &begin_info)?;

let clear_values = [
vk::ClearValue {
@@ -160,19 +167,19 @@ impl<'a> SwapchainData<'a, '_> {
..Default::default()
};

sc_info.get_device().cmd_begin_render_pass(
device.cmd_begin_render_pass(
buf,
&begin_info,
vk::SubpassContents::INLINE,
);

sc_info.get_device().cmd_bind_pipeline(
device.cmd_bind_pipeline(
buf,
vk::PipelineBindPoint::GRAPHICS,
**pipeline,
);

sc_info.get_device().cmd_bind_descriptor_sets(
device.cmd_bind_descriptor_sets(
buf,
vk::PipelineBindPoint::GRAPHICS,
**sc_info.layout,
@@ -184,9 +191,9 @@ impl<'a> SwapchainData<'a, '_> {
// TODO
sc_info.model.draw(buf, "mesh0").unwrap();

sc_info.get_device().cmd_end_render_pass(buf);
device.cmd_end_render_pass(buf);

sc_info.get_device().end_command_buffer(buf)?;
device.end_command_buffer(buf)?;
}
}

@@ -238,21 +245,21 @@ fn draw_frame<'b>(

let time_1 = time_ms as f32 / 1_000.0;

let pos = Vec3::new(0.0, f32::sin(time_1 / 2.0) * 8.0, 0.0);
let pos = Vec3::new(0.0, /*f32::sin(time_1 / 2.0) * 0.5*/ 2.0, 0.0);

let object = Mat4::from_scale_rotation_translation(
Vec3::new(0.025, 0.025, 0.025),
Quat::from_rotation_z(PI * 2.0 * time_1 / 10.0),
Quat::from_rotation_z(PI/*PI * 2.0 * time_1 / 10.0*/),
pos,
);

let camera = Mat4::look_at_rh(
Vec3::new(1.0, 1.0, 1.0),
Vec3::new(1.0, 1.0, 2.0),
pos,
Vec3::new(0.0, 0.0, 1.0),
);

let projection = Mat4::perspective_rh_gl(
let projec = Mat4::perspective_rh_gl(
PI * 2.0 / 4.0,
sc_data.swapchain.extent.width as f32
/ sc_data.swapchain.extent.height as f32,
@@ -265,9 +272,13 @@ fn draw_frame<'b>(
Vec4::new(0.0, 0.0, 0.0, 1.0),
);

let uniforms = Uniforms { object, camera, projection };
let uniforms = data::uniforms::Uniforms { object, camera, projec };

sc_data.descriptor_pool.buffers[image_index].write_data(&[uniforms])?;
let (ufm_buf, bon_buf) = &sc_data.descriptor_pool.buffers[image_index];
ufm_buf.write_data(&[uniforms])?;
bon_buf.write_data(
&sc_data.info.model.frame_matrices((time_ms / 500 % 30) as usize),
)?;

let wait_semaphores = [**image_avail_s];
let wait_stages = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
@@ -379,7 +390,9 @@ pub fn run(
let cmd_pool = CommandPool::create(queue_graphics.clone())?;

let img = {
let arc = vfs::Arc::read_tar(&mut vfs.get("combine.texture")?.data())?;
let arc = vfs::Arc::read_tar(
&mut vfs.get("scientist/hltex000.texture")?.data(),
)?;
let img = data::image::MipImage::read(&*arc)?;
Image::from_indep(IndepImage::create(&cmd_pool, &img)?)
};
@@ -389,7 +402,7 @@ pub fn run(
let img_sampler = Sampler::create(device.clone(), &conf.render)?;

let model = data::model::Model::read(&mut Cursor::new(
vfs.get("combine.iqm")?.data(),
vfs.get("scientist/scientist.iqm")?.data(),
))?;
let model = Model::create(&cmd_pool, model.0, model.1)?;



Loading…
Cancel
Save