use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use anyhow::Result;
use ash::vk;
use crate::util::cache::{Resource, ResourceKey};
use crate::Device;
#[derive(Derivative)]
#[derivative(Debug)]
pub struct Shader {
#[derivative(Debug = "ignore")]
device: Device,
handle: vk::ShaderModule,
}
impl Shader {
pub unsafe fn handle(&self) -> vk::ShaderModule {
self.handle
}
}
#[derive(Debug, Clone)]
pub struct ShaderCreateInfo {
stage: vk::ShaderStageFlags,
code: Vec<u32>,
code_hash: u64,
pub(crate) persistent: bool,
}
impl ShaderCreateInfo {
pub fn stage(&self) -> vk::ShaderStageFlags {
self.stage
}
pub fn code(&self) -> &[u32] {
self.code.as_slice()
}
pub fn code_hash(&self) -> u64 {
self.code_hash
}
}
impl ResourceKey for ShaderCreateInfo {
fn persistent(&self) -> bool {
self.persistent
}
}
impl Resource for Shader {
type Key = ShaderCreateInfo;
type ExtraParams<'a> = ();
const MAX_TIME_TO_LIVE: u32 = 8;
fn create(device: Device, key: &Self::Key, _: Self::ExtraParams<'_>) -> Result<Self> {
let info = vk::ShaderModuleCreateInfo {
s_type: vk::StructureType::SHADER_MODULE_CREATE_INFO,
p_next: std::ptr::null(),
flags: Default::default(),
code_size: key.code.len() * 4, p_code: key.code.as_ptr(),
};
let handle = unsafe { device.create_shader_module(&info, None)? };
#[cfg(feature = "log-objects")]
trace!("Created new VkShaderModule {handle:p}");
Ok(Self {
device: device.clone(),
handle,
})
}
}
impl Drop for Shader {
fn drop(&mut self) {
#[cfg(feature = "log-objects")]
trace!("Destroying VkShaderModule {:p}", self.handle);
unsafe {
self.device.destroy_shader_module(self.handle, None);
}
}
}
impl ShaderCreateInfo {
pub fn from_spirv(stage: vk::ShaderStageFlags, code: Vec<u32>) -> Self {
let mut hasher = DefaultHasher::new();
code.hash(&mut hasher);
Self {
stage,
code,
code_hash: hasher.finish(),
persistent: false,
}
}
}