2023-01-14 12:03:01 +00:00
|
|
|
use crate::prelude::*;
|
|
|
|
|
|
|
|
use anyhow::{Context, Result};
|
|
|
|
|
|
|
|
use std::fs::File;
|
|
|
|
use std::io::Read;
|
2024-03-24 20:29:47 +00:00
|
|
|
use std::marker::PhantomData;
|
2023-01-14 12:03:01 +00:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
2024-03-24 20:29:47 +00:00
|
|
|
pub mod shader_type {
|
|
|
|
mod sealed {
|
|
|
|
pub trait Sealed {}
|
|
|
|
impl Sealed for super::Vertex {}
|
|
|
|
impl Sealed for super::Fragment {}
|
|
|
|
impl Sealed for super::Geometry {}
|
|
|
|
impl Sealed for super::TesselationControl {}
|
|
|
|
impl Sealed for super::TesselationEvaluation {}
|
|
|
|
impl Sealed for super::Compute {}
|
|
|
|
impl Sealed for super::RayGeneration {}
|
|
|
|
impl Sealed for super::ClosestHit {}
|
|
|
|
impl Sealed for super::Miss {}
|
|
|
|
impl Sealed for super::AnyHit {}
|
|
|
|
impl Sealed for super::Intersection {}
|
2023-01-27 16:42:04 +00:00
|
|
|
}
|
2023-01-27 09:12:59 +00:00
|
|
|
|
2024-03-24 20:29:47 +00:00
|
|
|
pub trait ShaderType: sealed::Sealed {}
|
|
|
|
|
|
|
|
pub struct Vertex;
|
|
|
|
impl ShaderType for Vertex {}
|
|
|
|
|
|
|
|
pub struct Fragment;
|
|
|
|
impl ShaderType for Fragment {}
|
|
|
|
|
|
|
|
pub struct Geometry;
|
|
|
|
impl ShaderType for Geometry {}
|
|
|
|
|
|
|
|
pub struct TesselationControl;
|
|
|
|
impl ShaderType for TesselationControl {}
|
|
|
|
|
|
|
|
pub struct TesselationEvaluation;
|
|
|
|
impl ShaderType for TesselationEvaluation {}
|
|
|
|
|
|
|
|
pub struct Compute;
|
|
|
|
impl ShaderType for Compute {}
|
|
|
|
|
|
|
|
pub struct RayGeneration;
|
|
|
|
impl ShaderType for RayGeneration {}
|
|
|
|
|
|
|
|
pub struct ClosestHit;
|
|
|
|
impl ShaderType for ClosestHit {}
|
|
|
|
|
|
|
|
pub struct Miss;
|
|
|
|
impl ShaderType for Miss {}
|
|
|
|
|
|
|
|
pub struct AnyHit;
|
|
|
|
impl ShaderType for AnyHit {}
|
|
|
|
|
|
|
|
pub struct Intersection;
|
|
|
|
impl ShaderType for Intersection {}
|
2023-01-14 12:03:01 +00:00
|
|
|
}
|
|
|
|
|
2023-02-01 13:32:30 +00:00
|
|
|
pub trait VertexInputDescription: ReprC + Sized {
|
2023-01-27 21:13:35 +00:00
|
|
|
fn bindings() -> Vec<VkVertexInputBindingDescription> {
|
|
|
|
vec![VkVertexInputBindingDescription {
|
|
|
|
binding: 0,
|
|
|
|
stride: std::mem::size_of::<Self>() as u32,
|
|
|
|
inputRate: VK_VERTEX_INPUT_RATE_VERTEX,
|
|
|
|
}]
|
|
|
|
}
|
|
|
|
|
2023-01-27 09:12:59 +00:00
|
|
|
fn attributes() -> Vec<VkVertexInputAttributeDescription>;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait PipelineStageInfo {
|
|
|
|
fn pipeline_stage_info(&self) -> VkPipelineShaderStageCreateInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_pipeline_stage_info {
|
|
|
|
($func:ident, $type:ident) => {
|
2024-03-24 20:29:47 +00:00
|
|
|
impl PipelineStageInfo for ShaderModule<$type> {
|
2023-01-27 09:12:59 +00:00
|
|
|
fn pipeline_stage_info(&self) -> VkPipelineShaderStageCreateInfo {
|
|
|
|
VkPipelineShaderStageCreateInfo::$func(self.shader_module)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-01-14 12:03:01 +00:00
|
|
|
#[derive(Debug)]
|
2024-03-24 20:29:47 +00:00
|
|
|
pub struct ShaderModule<ShaderModuleType: ShaderType> {
|
|
|
|
t: PhantomData<ShaderModuleType>,
|
2023-01-14 12:03:01 +00:00
|
|
|
device: Arc<Device>,
|
|
|
|
shader_module: VkShaderModule,
|
|
|
|
}
|
|
|
|
|
2024-03-24 20:29:47 +00:00
|
|
|
impl<ShaderModuleType: ShaderType> ShaderModule<ShaderModuleType> {
|
|
|
|
pub fn new(device: Arc<Device>, path: &str) -> Result<Arc<ShaderModule<ShaderModuleType>>> {
|
2023-01-14 12:03:01 +00:00
|
|
|
let code = Self::shader_code(path)?;
|
|
|
|
|
2023-01-27 09:12:59 +00:00
|
|
|
Self::from_slice(device, code.as_slice())
|
2023-01-14 12:03:01 +00:00
|
|
|
}
|
|
|
|
|
2024-03-24 20:29:47 +00:00
|
|
|
pub fn from_slice(
|
|
|
|
device: Arc<Device>,
|
|
|
|
code: &[u8],
|
|
|
|
) -> Result<Arc<ShaderModule<ShaderModuleType>>> {
|
2023-01-14 12:03:01 +00:00
|
|
|
let shader_module_ci =
|
|
|
|
VkShaderModuleCreateInfo::new(VK_SHADER_MODULE_CREATE_NULL_BIT, code);
|
|
|
|
|
|
|
|
let shader_module = device.create_shader_module(&shader_module_ci)?;
|
|
|
|
|
|
|
|
Ok(Arc::new(ShaderModule {
|
2024-03-24 20:29:47 +00:00
|
|
|
t: PhantomData,
|
2023-01-14 12:03:01 +00:00
|
|
|
device,
|
|
|
|
shader_module,
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn shader_code(path: &str) -> Result<Vec<u8>> {
|
|
|
|
let mut file = File::open(path).with_context({
|
|
|
|
let path = path.to_string();
|
|
|
|
|| path
|
|
|
|
})?;
|
|
|
|
|
|
|
|
let mut code: Vec<u8> = Vec::new();
|
|
|
|
|
|
|
|
file.read_to_end(&mut code)?;
|
|
|
|
|
|
|
|
Ok(code)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-24 20:29:47 +00:00
|
|
|
use shader_type::*;
|
|
|
|
|
2023-01-27 09:12:59 +00:00
|
|
|
impl_pipeline_stage_info!(vertex, Vertex);
|
|
|
|
impl_pipeline_stage_info!(geometry, Geometry);
|
|
|
|
impl_pipeline_stage_info!(tesselation_control, TesselationControl);
|
|
|
|
impl_pipeline_stage_info!(tesselation_evaluation, TesselationEvaluation);
|
|
|
|
impl_pipeline_stage_info!(fragment, Fragment);
|
|
|
|
impl_pipeline_stage_info!(compute, Compute);
|
|
|
|
impl_pipeline_stage_info!(any_hit, AnyHit);
|
|
|
|
impl_pipeline_stage_info!(intersection, Intersection);
|
|
|
|
impl_pipeline_stage_info!(closest_hit, ClosestHit);
|
|
|
|
impl_pipeline_stage_info!(ray_generation, RayGeneration);
|
|
|
|
impl_pipeline_stage_info!(miss, Miss);
|
|
|
|
|
2024-03-24 20:29:47 +00:00
|
|
|
impl<ShaderModuleType: ShaderType> VulkanDevice for ShaderModule<ShaderModuleType> {
|
2023-01-14 12:03:01 +00:00
|
|
|
fn device(&self) -> &Arc<Device> {
|
|
|
|
&self.device
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-24 20:29:47 +00:00
|
|
|
impl_vk_handle!(ShaderModule<ShaderModuleType: ShaderType,>, VkShaderModule, shader_module);
|
2023-01-14 12:03:01 +00:00
|
|
|
|
2024-03-24 20:29:47 +00:00
|
|
|
impl<ShaderModuleType: ShaderType> Drop for ShaderModule<ShaderModuleType> {
|
2023-01-14 12:03:01 +00:00
|
|
|
fn drop(&mut self) {
|
|
|
|
self.device.destroy_shader_module(self.shader_module);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait AddSpecializationConstant<T> {
|
|
|
|
fn add(&mut self, value: T, id: u32);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct SpecializationConstants {
|
|
|
|
// store data as raw bytes
|
|
|
|
data: Vec<u8>,
|
|
|
|
entries: Vec<VkSpecializationMapEntry>,
|
|
|
|
|
|
|
|
info: VkSpecializationInfo,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SpecializationConstants {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
let mut me = SpecializationConstants {
|
|
|
|
data: Vec::new(),
|
|
|
|
entries: Vec::new(),
|
|
|
|
|
|
|
|
info: VkSpecializationInfo::empty(),
|
|
|
|
};
|
|
|
|
|
|
|
|
me.info.set_data(&me.data);
|
|
|
|
me.info.set_map_entries(&me.entries);
|
|
|
|
|
|
|
|
me
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn vk_handle(&self) -> &VkSpecializationInfo {
|
|
|
|
&self.info
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_add_specialization_constant {
|
|
|
|
($($type: ty),+) => {
|
|
|
|
$(
|
|
|
|
impl AddSpecializationConstant<$type> for SpecializationConstants {
|
|
|
|
fn add(&mut self, value: $type, id: u32) {
|
|
|
|
let bytes = value.to_ne_bytes();
|
|
|
|
|
|
|
|
self.entries.push(VkSpecializationMapEntry {
|
|
|
|
constantID: id,
|
|
|
|
offset: self.data.len() as u32,
|
|
|
|
size: bytes.len(),
|
|
|
|
});
|
|
|
|
|
|
|
|
self.data.extend(&bytes);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)+
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
impl_add_specialization_constant!(f32, f64, u64, i64, u32, i32, u16, i16, u8, i8, usize, isize);
|