Browse Source

some shit

master
Alison Watson 11 months ago
parent
commit
031f395421
  1. 1
      Cargo.lock
  2. 2
      Cargo.toml
  3. 7
      bl/main.rs
  4. 3
      fw/data/deflate.rs
  5. 2
      fw/data/image.rs
  6. 143
      fw/data/model.rs
  7. 2
      fw/hal/sdl.rs
  8. 2
      fw/hal/win.rs
  9. 2
      fw/lib.rs
  10. 2
      fw/meta.rs
  11. 72
      fw/render.rs
  12. 359
      fw/render/_image.rs
  13. 61
      fw/render/_sampler.rs
  14. 10
      fw/render/shader.rs
  15. 4
      fw/types.rs
  16. 2
      fw/types/ffi.rs
  17. 53
      fw/types/io.rs
  18. 10
      fw/types/iter.rs

1
Cargo.lock generated

@ -49,6 +49,7 @@ dependencies = [
"easy-cast",
"glam",
"half",
"log",
"naga",
"serde",
"smallvec",

2
Cargo.toml

@ -34,8 +34,10 @@ thiserror = "~1.0"
# i/o:
# - serde for config / description files
# - toml for config / description files
# - log for, uh, logging
serde = { version = "~1.0", features = ["derive"] }
toml = "~0.5"
log = "~0.4"
# math:
# - easy-cast for safer casting

7
bl/main.rs

@ -33,6 +33,11 @@ fn entry(conf: &fw::conf::Conf) -> Result<(), Box<dyn std::error::Error>> {
}
fn main() {
const LOG: fw::types::io::Log = fw::types::io::Log;
log::set_logger(&LOG).unwrap();
log::set_max_level(log::LevelFilter::Trace);
let conf = fw::conf::Conf::read("blonkus.toml").unwrap_or_else(|err| {
match err {
| fw::conf::Err::NoFile => {
@ -44,6 +49,8 @@ fn main() {
fw::conf::Conf::default()
});
log::info!("begin the begin");
entry(&conf).unwrap();
}

3
fw/data/deflate.rs

@ -2,8 +2,7 @@
use crate::{
data::read,
ffi,
types::{stkvec, Cast, StkVec},
types::{ffi, stkvec, Cast, StkVec},
};
use std::cmp::Ordering;

2
fw/data/image.rs

@ -2,7 +2,7 @@
use crate::{
data::{color::Rgba8888, read, vfs},
iter::MaybeRev,
types::iter::MaybeRev,
};
use std::io::{self, Read};

143
fw/data/model.rs

@ -2,12 +2,12 @@
use crate::{
data::{read, vertex::Vertex},
ffi,
math::*,
types::{Cast, StkStr},
types::{ffi, Cast, StkStr},
};
use std::{
collections::HashMap,
convert::TryFrom,
io::{self, Read, Seek, SeekFrom},
ops::Range,
str::Utf8Error,
@ -75,61 +75,74 @@ pub struct Model {
num_frms: usize,
}
const FMT_I8: u32 = 0;
const FMT_U8: u32 = 1;
const FMT_I16: u32 = 2;
const FMT_U16: u32 = 3;
const FMT_I32: u32 = 4;
const FMT_U32: u32 = 5;
const FMT_F16: u32 = 6;
const FMT_F32: u32 = 7;
const FMT_F64: u32 = 8;
const fn fmt_check(fm: u32) -> Result<(), Err> {
match fm {
| FMT_I8 | FMT_U8 | FMT_I16 | FMT_U16 | FMT_I32 | FMT_U32 | FMT_F16
| FMT_F32 | FMT_F64 => Ok(()),
| _ => Err(Err::VaFormat),
}
#[derive(Copy, Clone)]
enum Fmt {
I8,
U8,
I16,
U16,
I32,
U32,
F16,
F32,
F64,
}
fn fmt_size(fm: u32) -> usize {
match fm {
| FMT_I8 | FMT_U8 => 1,
| FMT_I16 | FMT_U16 | FMT_F16 => 2,
| FMT_I32 | FMT_U32 | FMT_F32 => 4,
| FMT_F64 => 8,
| _ => unsafe { std::hint::unreachable_unchecked() },
impl TryFrom<u32> for Fmt {
type Error = Err;
fn try_from(v: u32) -> Result<Self, Self::Error> {
match v {
| 0 => Ok(Self::I8),
| 1 => Ok(Self::U8),
| 2 => Ok(Self::I16),
| 3 => Ok(Self::U16),
| 4 => Ok(Self::I32),
| 5 => Ok(Self::U32),
| 6 => Ok(Self::F16),
| 7 => Ok(Self::F32),
| 8 => Ok(Self::F64),
| _ => Err(Err::VaFormat),
}
}
}
fn fmt_read_abs(fm: u32, vec: &[u8], pos: usize) -> f32 {
match fm {
| FMT_I8 => read::i8x(vec, pos).into(),
| FMT_U8 => read::u8x(vec, pos).into(),
| FMT_I16 => read::i16le(vec, pos).into(),
| FMT_U16 => read::u16le(vec, pos).into(),
| FMT_I32 => read::i32le(vec, pos).cast(),
| FMT_U32 => read::u32le(vec, pos).cast(),
| FMT_F16 => read::f16le(vec, pos).to_f32(),
| FMT_F32 => read::f32le(vec, pos),
| FMT_F64 => read::f64le(vec, pos) as f32,
| _ => unsafe { std::hint::unreachable_unchecked() },
impl Fmt {
const fn size(self) -> usize {
match self {
| Self::I8 | Self::U8 => 1,
| Self::I16 | Self::U16 | Self::F16 => 2,
| Self::I32 | Self::U32 | Self::F32 => 4,
| Self::F64 => 8,
}
}
}
fn fmt_read_nrm(fm: u32, vec: &[u8], pos: usize) -> f32 {
match fm {
| FMT_I8 => f32::from(read::i8x(vec, pos)).abs() / 128.0,
| FMT_U8 => f32::from(read::u8x(vec, pos)) / 255.0,
| FMT_I16 => f32::from(read::i16le(vec, pos)).abs() / 32768.0,
| FMT_U16 => f32::from(read::u16le(vec, pos)) / 65535.0,
| FMT_I32 => (f64::from(read::i32le(vec, pos)) / 2147483648.0) as f32,
| FMT_U32 => (f64::from(read::u32le(vec, pos)) / 4294967295.0) as f32,
| FMT_F16 => f32::clamp(read::f16le(vec, pos).to_f32(), 0.0, 1.0),
| FMT_F32 => f32::clamp(read::f32le(vec, pos), 0.0, 1.0),
| FMT_F64 => f32::clamp(read::f64le(vec, pos) as f32, 0.0, 1.0),
| _ => unsafe { std::hint::unreachable_unchecked() },
fn read_abs(self, v: &[u8], p: usize) -> f32 {
match self {
| Self::I8 => read::i8x(v, p).into(),
| Self::U8 => read::u8x(v, p).into(),
| Self::I16 => read::i16le(v, p).into(),
| Self::U16 => read::u16le(v, p).into(),
| Self::I32 => read::i32le(v, p).cast(),
| Self::U32 => read::u32le(v, p).cast(),
| Self::F16 => read::f16le(v, p).to_f32(),
| Self::F32 => read::f32le(v, p),
| Self::F64 => read::f64le(v, p) as f32,
}
}
fn read_nrm(self, v: &[u8], p: usize) -> f32 {
match self {
| Self::I8 => f32::from(read::i8x(v, p)).abs() / 128.0,
| Self::U8 => f32::from(read::u8x(v, p)) / 255.0,
| Self::I16 => f32::from(read::i16le(v, p)).abs() / 32768.0,
| Self::U16 => f32::from(read::u16le(v, p)) / 65535.0,
| Self::I32 => (f64::from(read::i32le(v, p)) / 2147483648.0) as f32,
| Self::U32 => (f64::from(read::u32le(v, p)) / 4294967295.0) as f32,
| Self::F16 => f32::clamp(read::f16le(v, p).to_f32(), 0.0, 1.0),
| Self::F32 => f32::clamp(read::f32le(v, p), 0.0, 1.0),
| Self::F64 => f32::clamp(read::f64le(v, p) as f32, 0.0, 1.0),
}
}
}
@ -227,20 +240,18 @@ impl Model {
for array_def in read::hunk(rd, num_vinf * 20)?.chunks(20) {
let ty = read::u32le(array_def, 0);
//let fl = read::u32le(array_def, 4);
let fm = read::u32le(array_def, 8);
let fm = Fmt::try_from(read::u32le(array_def, 8))?;
let sz = read::u32le(array_def, 12) as usize;
let of = read::u32le(array_def, 16).into();
fmt_check(fm)?;
let obj_size = fm.size();
let obj_blks = obj_size * sz;
rd.seek(SeekFrom::Start(of))?;
let obj_size = fmt_size(fm);
let obj_blks = obj_size * sz;
let hunk = read::hunk(rd, obj_blks * num_vert)?;
let v2 = |v: &mut Vec<Vec3>, rd: fn(u32, &[u8], usize) -> f32| {
let v2 = |v: &mut Vec<Vec3>, rd: fn(Fmt, &[u8], usize) -> f32| {
if sz != 2 {
Err(Err::VaFormat)
} else {
@ -253,7 +264,7 @@ impl Model {
}
};
let v3 = |v: &mut Vec<Vec3>, rd: fn(u32, &[u8], usize) -> f32| {
let v3 = |v: &mut Vec<Vec3>, rd: fn(Fmt, &[u8], usize) -> f32| {
if sz != 3 {
Err(Err::VaFormat)
} else {
@ -267,7 +278,7 @@ impl Model {
}
};
let v4 = |v: &mut Vec<Vec4>, rd: fn(u32, &[u8], usize) -> f32| {
let v4 = |v: &mut Vec<Vec4>, rd: fn(Fmt, &[u8], usize) -> f32| {
if sz != 4 {
Err(Err::VaFormat)
} else {
@ -283,13 +294,13 @@ impl Model {
};
match ty {
| 0 => v3(&mut pos_v, fmt_read_abs)?,
| 1 => v2(&mut tex_v, fmt_read_abs)?,
| 2 => v3(&mut nrm_v, fmt_read_abs)?,
| 3 => v4(&mut tan_v, fmt_read_abs)?,
| 4 => v4(&mut idx_v, fmt_read_abs)?,
| 5 => v4(&mut wgt_v, fmt_read_nrm)?,
| 6 => v4(&mut clr_v, fmt_read_nrm)?,
| 0 => v3(&mut pos_v, Fmt::read_abs)?,
| 1 => v2(&mut tex_v, Fmt::read_abs)?,
| 2 => v3(&mut nrm_v, Fmt::read_abs)?,
| 3 => v4(&mut tan_v, Fmt::read_abs)?,
| 4 => v4(&mut idx_v, Fmt::read_abs)?,
| 5 => v4(&mut wgt_v, Fmt::read_nrm)?,
| 6 => v4(&mut clr_v, Fmt::read_nrm)?,
| _ => return Err(Err::VaType),
}
}
@ -297,7 +308,7 @@ impl Model {
// zip the vertex info
let mut vert_dat = Vec::with_capacity(num_vert);
for (pos, tex, nrm, tan, idx, wgt, clr) in crate::iter::OpenZip((
for (pos, tex, nrm, tan, idx, wgt, clr) in crate::types::iter::OpenZip((
pos_v.into_iter(),
tex_v.into_iter(),
nrm_v.into_iter(),

2
fw/hal/sdl.rs

@ -1,6 +1,6 @@
use crate::{
ffi::{Bool, Nts},
opaque_struct,
types::ffi::{Bool, Nts},
};
use std::os::raw;

2
fw/hal/win.rs

@ -1,5 +1,5 @@
use super::*;
use crate::{ffi, types::Cast};
use crate::types::{ffi, Cast};
use ash::{version::InstanceV1_0, vk};
use std::marker::PhantomData;

2
fw/lib.rs

@ -19,9 +19,7 @@
pub mod conf;
pub mod data;
pub mod ffi;
pub mod hal;
pub mod iter;
pub mod math;
pub mod meta;
pub mod render;

2
fw/meta.rs

@ -11,7 +11,7 @@ macro_rules! meta_str {
"FFI version of [`meta::", stringify!($name),
"`][crate::meta::", stringify!($name), "]."
)]
pub const $name: crate::ffi::Nts = crate::c_str!($e);
pub const $name: crate::types::ffi::Nts = crate::c_str!($e);
)*
}
}

72
fw/render.rs

@ -13,9 +13,9 @@ use crate::{
c_str,
data::{self, uniforms::Uniforms, vertex::Vertex},
hal::win::Window,
types::{stkvec, Cast, Conv, StkVec},
types::{ffi::Nts, stkvec, Cast, Conv, StkVec},
};
use crate::{stkvec_r, vec_e, vec_r};
use crate::{stkvec_e, stkvec_r, vec_r};
use ash::{
extensions::khr,
version::{DeviceV1_0, EntryV1_0, InstanceV1_0},
@ -102,7 +102,7 @@ struct Buf {
struct Shader {
module: vk::ShaderModule,
stages: Vec<vk::ShaderStageFlags>,
stages: StkVec<[vk::ShaderStageFlags; 8]>,
}
struct Model {
@ -200,19 +200,19 @@ impl StaticData {
// set up queues
let qf = unsafe { get_qfs(&ins, &srf, surface, physical)? };
const QUEUE_PRIORITY: [f32; 1] = [1.0];
let queue_priority = 1.0;
let queue_create_info = [
vk::DeviceQueueCreateInfo {
queue_family_index: qf.gfx,
queue_count: 1,
p_queue_priorities: QUEUE_PRIORITY.as_ptr(),
p_queue_priorities: &queue_priority,
..Default::default()
},
vk::DeviceQueueCreateInfo {
queue_family_index: qf.srf,
queue_count: 1,
p_queue_priorities: QUEUE_PRIORITY.as_ptr(),
p_queue_priorities: &queue_priority,
..Default::default()
},
];
@ -246,6 +246,8 @@ impl StaticData {
// create the command pool
let create_info = vk::CommandPoolCreateInfo {
queue_family_index: qf.gfx,
flags: vk::CommandPoolCreateFlags::TRANSIENT
| vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER,
..Default::default()
};
@ -602,9 +604,9 @@ impl StaticData {
// create the uniform buffers
let ufm_bufs =
stkvec_r![<[_; 8]> unsafe { self.new_buf(&Buf::UFM) }; n_sc_imgs]?;
stkvec_r![8; unsafe { self.new_buf(&Buf::UFM) }; n_sc_imgs]?;
let bon_bufs =
stkvec_r![<[_; 8]> unsafe { self.new_buf(&Buf::BON) }; n_sc_imgs]?;
stkvec_r![8; unsafe { self.new_buf(&Buf::BON) }; n_sc_imgs]?;
// create the descriptor pool
let size_info = get_desc_pool_sizes(n_sc_imgs.cast());
@ -634,7 +636,7 @@ impl StaticData {
let mut write_descriptors =
StkVec::<[_; 24]>::with_capacity(desc_sets.len() * 3);
for (&dst_set, ufm, bon) in crate::iter::ClosedZip((
for (&dst_set, ufm, bon) in crate::types::iter::ClosedZip((
desc_sets.iter(),
ufm_bufs.iter(),
bon_bufs.iter(),
@ -668,7 +670,7 @@ impl StaticData {
},
];
for (&buf, &framebuffer, &set) in crate::iter::ClosedZip((
for (&buf, &framebuffer, &set) in crate::types::iter::ClosedZip((
cmd_bufs.iter(),
framebuffers.iter(),
desc_sets.iter(),
@ -816,6 +818,7 @@ impl Renderer {
unsafe fn draw_frame_raw(&mut self) -> Result<(), vk::Result> {
use crate::math::*;
// synchronize and set up this fence
let sem_img = self.st.sem_img[self.cur_c_frame];
let sem_ren = self.st.sem_ren[self.cur_c_frame];
let fen_frm = self.st.fen_frm[self.cur_c_frame];
@ -846,6 +849,7 @@ impl Renderer {
self.sc.sc_img_fn[image_index] = Some(fen_frm);
// write uniforms
/*
let time_1 = time_ms as f32 / 1_000.0;
@ -887,19 +891,20 @@ impl Renderer {
)?;
*/
let wait_sem = [sem_img];
let wait_stg = [vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT];
let sign_sem = [sem_ren];
let cmd_bufs = [self.sc.cmd_bufs[image_index]];
// write command buffer
let cmd_buf = self.sc.cmd_bufs[image_index];
// submit
let wait_stg = vk::PipelineStageFlags::COLOR_ATTACHMENT_OUTPUT;
let submit_info = [vk::SubmitInfo {
wait_semaphore_count: wait_sem.len().cast(),
p_wait_semaphores: wait_sem.as_ptr(),
p_wait_dst_stage_mask: wait_stg.as_ptr(),
command_buffer_count: cmd_bufs.len().cast(),
p_command_buffers: cmd_bufs.as_ptr(),
signal_semaphore_count: sign_sem.len().cast(),
p_signal_semaphores: sign_sem.as_ptr(),
wait_semaphore_count: 1,
p_wait_semaphores: &sem_img,
p_wait_dst_stage_mask: &wait_stg,
command_buffer_count: 1,
p_command_buffers: &cmd_buf,
signal_semaphore_count: 1,
p_signal_semaphores: &sem_ren,
..Default::default()
}];
@ -908,15 +913,15 @@ impl Renderer {
self.st.dev.queue_submit(self.st.queue_gfx, &submit_info, fen_frm)?;
}
let swapchains = [self.sc.swapchain];
let image_indices = [image_index.cast()];
// present to swapchain
let image_index_present = image_index.cast();
let present_info = vk::PresentInfoKHR {
wait_semaphore_count: sign_sem.len().cast(),
p_wait_semaphores: sign_sem.as_ptr(),
swapchain_count: swapchains.len().cast(),
p_swapchains: swapchains.as_ptr(),
p_image_indices: image_indices.as_ptr(),
wait_semaphore_count: 1,
p_wait_semaphores: &sem_ren,
swapchain_count: 1,
p_swapchains: &self.sc.swapchain,
p_image_indices: &image_index_present,
..Default::default()
};
@ -1058,10 +1063,10 @@ unsafe fn new_framebuffer(
/// Ensures that certain properties are available for a given runtime
/// set of properties.
unsafe fn ensure_properties<T, F>(
props: &[T], names: &[crate::ffi::Nts], func: F,
props: &[T], names: &[Nts], func: F,
) -> Result<(), Err>
where
F: Fn(&T) -> crate::ffi::Nts,
F: Fn(&T) -> Nts,
{
for name in names {
unsafe {
@ -1079,8 +1084,7 @@ where
/// Enables extensions for device creation.
unsafe fn enable_device_extensions(
ins: &ash::Instance, physical: vk::PhysicalDevice,
extensions: &[crate::ffi::Nts],
ins: &ash::Instance, physical: vk::PhysicalDevice, extensions: &[Nts],
) -> Result<vk::DeviceCreateInfo, Err> {
if !extensions.is_empty() {
unsafe {
@ -1098,7 +1102,7 @@ unsafe fn enable_device_extensions(
/// Enables layers for instance creation.
unsafe fn enable_instance_layers(
ent: &ash::Entry, layers: &[crate::ffi::Nts],
ent: &ash::Entry, layers: &[Nts],
) -> Result<vk::InstanceCreateInfo, Err> {
if !layers.is_empty() {
unsafe {
@ -1206,7 +1210,7 @@ const fn get_desc_pool_sizes(n_sc_imgs: u32) -> [vk::DescriptorPoolSize; 2] {
fn get_write_descriptors(
dst_set: vk::DescriptorSet, ufm_buf_info: &vk::DescriptorBufferInfo,
bon_buf_info: &vk::DescriptorBufferInfo, /*, smp_img_info: vk::DescriptorImageInfo*/
bon_buf_info: &vk::DescriptorBufferInfo, /*smp_img_info: vk::DescriptorImageInfo*/
) -> [vk::WriteDescriptorSet; 2] {
[
vk::WriteDescriptorSet {

359
fw/render/_image.rs

@ -1,359 +0,0 @@
use crate::{
data::image::MipImage,
render::{
misc::dev_size_of, Buffer, CommandPool, Device, ErrAllocMem, GetDevice,
Swapchain,
},
};
use ash::{version::DeviceV1_0, vk};
use std::rc::Rc;
enum LayoutStage {
Xfer,
Dpth,
Frag,
}
pub struct ImageInfo {
pub extents: Vec<vk::Extent3D>,
pub imtype: vk::ImageType,
pub ivtype: vk::ImageViewType,
pub aspect: vk::ImageAspectFlags,
pub format: vk::Format,
pub usagef: vk::ImageUsageFlags,
}
pub struct OwnedImage {
handle: vk::Image,
info: ImageInfo,
pub swapchain: Rc<Swapchain>,
}
pub struct IndepImage {
handle: vk::Image,
memory: vk::DeviceMemory,
info: ImageInfo,
pub device: Rc<Device>,
}
pub enum Image {
Owned(OwnedImage),
Indep(IndepImage),
}
impl GetDevice for OwnedImage {
fn get_device(&self) -> &Rc<Device> {
self.swapchain.get_device()
}
}
impl GetDevice for IndepImage {
fn get_device(&self) -> &Rc<Device> {
&self.device
}
}
impl GetDevice for Image {
fn get_device(&self) -> &Rc<Device> {
match self {
| Self::Owned(image) => image.get_device(),
| Self::Indep(image) => image.get_device(),
}
}
}
impl OwnedImage {
pub fn own(swapchain: Rc<Swapchain>, handle: vk::Image) -> Self {
let info = ImageInfo {
extents: vec![vk::Extent3D {
width: swapchain.extent.width,
height: swapchain.extent.height,
depth: 1,
}],
aspect: vk::ImageAspectFlags::COLOR,
imtype: vk::ImageType::TYPE_2D,
ivtype: vk::ImageViewType::TYPE_2D,
format: swapchain.format,
usagef: vk::ImageUsageFlags::COLOR_ATTACHMENT,
};
Self { handle, info, swapchain }
}
}
impl ImageInfo {
fn create_info(&self) -> vk::ImageCreateInfo {
vk::ImageCreateInfo {
image_type: self.imtype,
format: self.format,
extent: self.extents[0],
mip_levels: self.extents.len() as u32,
array_layers: 1,
samples: vk::SampleCountFlags::TYPE_1,
tiling: vk::ImageTiling::OPTIMAL,
usage: self.usagef,
sharing_mode: vk::SharingMode::EXCLUSIVE,
initial_layout: vk::ImageLayout::UNDEFINED,
..Default::default()
}
}
}
impl IndepImage {
pub fn create(
cmd_pool: &CommandPool, mip: &MipImage,
) -> Result<Self, ErrAllocMem> {
let device = cmd_pool.get_device().clone();
let extents = mip
.data()
.iter()
.map(|level| vk::Extent3D {
width: level.w() as u32,
height: level.h() as u32,
depth: 1,
})
.collect();
let info = ImageInfo {
extents,
aspect: vk::ImageAspectFlags::COLOR,
imtype: vk::ImageType::TYPE_2D,
ivtype: vk::ImageViewType::TYPE_2D,
format: vk::Format::R8G8B8A8_UNORM,
usagef: vk::ImageUsageFlags::TRANSFER_DST
| vk::ImageUsageFlags::SAMPLED,
};
let create_info = info.create_info();
unsafe {
let handle = device.create_image(&create_info, None)?;
let memory = device.alloc_mem(
device.get_image_memory_requirements(handle),
vk::MemoryPropertyFlags::DEVICE_LOCAL,
)?;
device.bind_image_memory(handle, memory, 0)?;
let img = Self { handle, memory, info, device };
img.layout_barrier(cmd_pool, LayoutStage::Xfer)?;
img.copy_mips_to_image(cmd_pool, mip)?;
img.layout_barrier(cmd_pool, LayoutStage::Frag)?;
Ok(img)
}
}
pub fn create_depth(
cmd_pool: &CommandPool, width: u32, height: u32,
) -> Result<Self, ErrAllocMem> {
let device = cmd_pool.get_device().clone();
let info = ImageInfo {
extents: vec![vk::Extent3D { width, height, depth: 1 }],
aspect: vk::ImageAspectFlags::DEPTH | vk::ImageAspectFlags::STENCIL,
imtype: vk::ImageType::TYPE_2D,
ivtype: vk::ImageViewType::TYPE_2D,
format: vk::Format::D32_SFLOAT_S8_UINT,
usagef: vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT,
};
let create_info = info.create_info();
unsafe {
let handle = device.create_image(&create_info, None)?;
let memory = device.alloc_mem(
device.get_image_memory_requirements(handle),
vk::MemoryPropertyFlags::DEVICE_LOCAL,
)?;
device.bind_image_memory(handle, memory, 0)?;
let img = Self { handle, memory, info, device };
img.layout_barrier(cmd_pool, LayoutStage::Dpth)?;
Ok(img)
}
}
fn layout_barrier(
&self, cmd_pool: &CommandPool, layout_stage: LayoutStage,
) -> Result<(), vk::Result> {
let (
old_layout,
new_layout,
src_access_mask,
dst_access_mask,
src_stage,
dst_stage,
) = match layout_stage {
| LayoutStage::Xfer => (
vk::ImageLayout::UNDEFINED,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
vk::AccessFlags::empty(),
vk::AccessFlags::TRANSFER_WRITE,
vk::PipelineStageFlags::TOP_OF_PIPE,
vk::PipelineStageFlags::TRANSFER,
),
| LayoutStage::Dpth => (
vk::ImageLayout::UNDEFINED,
vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
vk::AccessFlags::empty(),
vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
| vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE,
vk::PipelineStageFlags::TOP_OF_PIPE,
vk::PipelineStageFlags::EARLY_FRAGMENT_TESTS,
),
| LayoutStage::Frag => (
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
vk::ImageLayout::SHADER_READ_ONLY_OPTIMAL,
vk::AccessFlags::TRANSFER_WRITE,
vk::AccessFlags::SHADER_READ,
vk::PipelineStageFlags::TRANSFER,
vk::PipelineStageFlags::FRAGMENT_SHADER,
),
};
unsafe {
cmd_pool.with_transient_buffer(|cbuf| {
let barriers = [vk::ImageMemoryBarrier {
src_access_mask,
dst_access_mask,
old_layout,
new_layout,
src_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
dst_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
image: **self,
subresource_range: vk::ImageSubresourceRange {
aspect_mask: self.info.aspect,
base_mip_level: 0,
level_count: self.info.extents.len() as u32,
base_array_layer: 0,
layer_count: 1,
},
..Default::default()
}];
self.get_device().cmd_pipeline_barrier(
cbuf,
src_stage,
dst_stage,
vk::DependencyFlags::empty(),
&[],
&[],
&barriers,
);
Ok(())
})?;
}
Ok(())
}
fn copy_mips_to_image(
&self, cmd_pool: &CommandPool, mip: &MipImage,
) -> Result<(), ErrAllocMem> {
let buffer =
Buffer::create_image(cmd_pool.get_device().clone(), mip.data())?;
unsafe {
cmd_pool.with_transient_buffer(|cbuf| {
let mut image_copies = Vec::with_capacity(mip.levels());
let mut buffer_offset = 0;
for (mip_level, (&image_extent, img)) in
self.info.extents.iter().zip(mip.data()).enumerate()
{
image_copies.push(vk::BufferImageCopy {
buffer_offset,
buffer_row_length: 0,
buffer_image_height: 0,
image_subresource: vk::ImageSubresourceLayers {
aspect_mask: self.info.aspect,
mip_level: mip_level as u32,
base_array_layer: 0,
layer_count: 1,
},
image_offset: vk::Offset3D { x: 0, y: 0, z: 0 },
image_extent,
});
buffer_offset += dev_size_of(img.data());
}
self.get_device().cmd_copy_buffer_to_image(
cbuf,
**buffer,
**self,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&image_copies,
);
Ok(())
})?;
}
Ok(())
}
}
impl Image {
pub fn from_owned(img: OwnedImage) -> Rc<Self> {
Rc::new(Self::Owned(img))
}
pub fn from_indep(img: IndepImage) -> Rc<Self> {
Rc::new(Self::Indep(img))
}
pub const fn info(&self) -> &ImageInfo {
match self {
| Self::Owned(image) => &image.info,
| Self::Indep(image) => &image.info,
}
}
}
impl Drop for IndepImage {
fn drop(&mut self) {
unsafe {
self.get_device().destroy_image(self.handle, None);
self.get_device().free_memory(self.memory, None);
}
}
}
impl std::ops::Deref for OwnedImage {
type Target = vk::Image;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
impl std::ops::Deref for IndepImage {
type Target = vk::Image;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
impl std::ops::Deref for Image {
type Target = vk::Image;
fn deref(&self) -> &Self::Target {
match self {
| Self::Owned(image) => &image.handle,
| Self::Indep(image) => &image.handle,
}
}
}
// EOF

61
fw/render/_sampler.rs

@ -1,61 +0,0 @@
use crate::render::{Conf, Device, GetDevice};
use ash::{version::DeviceV1_0, vk};
use std::rc::Rc;
pub struct Sampler {
handle: vk::Sampler,
pub device: Rc<Device>,
}
impl GetDevice for Sampler {
fn get_device(&self) -> &Rc<Device> {
&self.device
}
}
impl Sampler {
pub fn create(
device: Rc<Device>, conf: &Conf,
) -> Result<Rc<Self>, vk::Result> {
let create_info = vk::SamplerCreateInfo {
mag_filter: vk::Filter::NEAREST,
min_filter: vk::Filter::LINEAR,
mipmap_mode: vk::SamplerMipmapMode::LINEAR,
address_mode_u: vk::SamplerAddressMode::MIRRORED_REPEAT,
address_mode_v: vk::SamplerAddressMode::MIRRORED_REPEAT,
address_mode_w: vk::SamplerAddressMode::CLAMP_TO_BORDER,
mip_lod_bias: conf.mip_bias,
anisotropy_enable: vk::TRUE,
max_anisotropy: 16.0,
compare_enable: vk::FALSE,
compare_op: vk::CompareOp::ALWAYS,
min_lod: 0.0,
max_lod: 16.0,
border_color: vk::BorderColor::INT_OPAQUE_BLACK,
unnormalized_coordinates: vk::FALSE,
..Default::default()
};
let handle = unsafe { device.create_sampler(&create_info, None)? };
Ok(Rc::new(Self { handle, device }))
}
}
impl Drop for Sampler {
fn drop(&mut self) {
unsafe {
self.get_device().destroy_sampler(self.handle, None);
}
}
}
impl std::ops::Deref for Sampler {
type Target = vk::Sampler;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
// EOF

10
fw/render/shader.rs

@ -1,8 +1,8 @@
use super::*;
use crate::data::shader::ShaderStage;
fn read_stages(s: ShaderStage) -> Vec<vk::ShaderStageFlags> {
let mut r = Vec::new();
fn read_stages(s: ShaderStage) -> StkVec<[vk::ShaderStageFlags; 8]> {
let mut r = StkVec::new();
if s.contains(ShaderStage::COMPUTE) {
r.push(vk::ShaderStageFlags::COMPUTE);
}
@ -36,8 +36,10 @@ impl Shader {
}
}
pub(super) fn stage_infos(&self) -> Vec<vk::PipelineShaderStageCreateInfo> {
vec_e![&self.stages, |&stage| vk::PipelineShaderStageCreateInfo {
pub(super) fn stage_infos(
&self,
) -> StkVec<[vk::PipelineShaderStageCreateInfo; 8]> {
stkvec_e![&self.stages, |&stage| vk::PipelineShaderStageCreateInfo {
stage,
module: self.module,
p_name: c_str!("main"),

4
fw/types.rs

@ -1,5 +1,9 @@
//! General-use types.
pub mod ffi;
pub mod io;
pub mod iter;
pub use easy_cast::{Cast, CastFloat, Conv, ConvFloat};
pub use smallvec::smallvec as stkvec;

2
fw/ffi.rs → fw/types/ffi.rs

@ -9,7 +9,7 @@ use std::{
macro_rules! c_str {
($s:expr) => {{
const S: &'static str = std::concat!($s, "\0");
S.as_ptr() as $crate::ffi::Nts
S.as_ptr() as $crate::types::ffi::Nts
}};
}

53
fw/types/io.rs

@ -0,0 +1,53 @@
//! Input/output utilities.
use std::io::Write;
/// Conditionally [`std::io::Stdout`] or [`std::io::Stderr`].
pub enum StdWrite {
Out(std::io::Stdout),
Err(std::io::Stderr),
}
impl Write for StdWrite {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
match self {
| Self::Out(o) => o.write(buf),
| Self::Err(o) => o.write(buf),
}
}
fn flush(&mut self) -> std::io::Result<()> {
match self {
| Self::Out(o) => o.flush(),
| Self::Err(o) => o.flush(),
}
}
}
/// Logging facade.
pub struct Log;
impl log::Log for Log {
fn enabled(&self, md: &log::Metadata<'_>) -> bool {
md.level() <= log::max_level() && !md.target().starts_with("naga::")
}
fn log(&self, re: &log::Record<'_>) {
if self.enabled(re.metadata()) {
let mut o = if re.level() <= log::Level::Warn {
StdWrite::Out(std::io::stdout())
} else {
StdWrite::Err(std::io::stderr())
};
let _ =
writeln!(o, "[{:^5}] {}: {}", re.level(), re.target(), re.args());
}
}
fn flush(&self) {
let _ = std::io::stdout().flush();
let _ = std::io::stderr().flush();
}
}
// EOF

10
fw/iter.rs → fw/types/iter.rs

@ -22,12 +22,18 @@ macro_rules! vec_e {
#[macro_export]
macro_rules! stkvec_r {
(<$t:ty> $it:expr, $xp:expr) => {$crate::coll![<Result<StkVec<$t>, _>> $it, $xp]};
(<$t:ty> $xp:expr; $sz:expr) => {$crate::coll![<Result<StkVec<$t>, _>> $xp; $sz]};
($s:expr; $it:expr, $xp:expr) => {$crate::coll![<Result<StkVec<[_; $s]>, _>> $it, $xp]};
($s:expr; $xp:expr; $sz:expr) => {$crate::coll![<Result<StkVec<[_; $s]>, _>> $xp; $sz]};
($it:expr, $xp:expr) => {$crate::coll![<Result<StkVec<_>, _>> $it, $xp]};
($xp:expr; $sz:expr) => {$crate::coll![<Result<StkVec<_>, _>> $xp; $sz]};
}
#[macro_export]
macro_rules! stkvec_e {
($it:expr, $xp:expr) => {$crate::coll![<StkVec<_>> $it, $xp]};
($xp:expr; $sz:expr) => {$crate::coll![<StkVec<_>> $xp; $sz]};
}
macro_rules! zips {
($i:ident) => {
None
Loading…
Cancel
Save