use std::ffi::c_void;
use std::fmt;
use std::num::NonZeroU64;
use noesis_runtime::render_device::TextureHandle;
#[cfg(feature = "shim")]
use noesis_runtime::render_device::types::Batch;
use noesis_runtime::render_device::types::SamplerState;
pub const MAX_SHADER_TEXTURES: usize = 4;
pub const MAX_SHADER_CONSTANTS: u32 = 512;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct PixelShaderHandle(pub NonZeroU64);
impl PixelShaderHandle {
#[must_use]
pub fn as_ptr(self) -> *mut c_void {
std::ptr::without_provenance_mut(self.0.get() as usize)
}
#[must_use]
pub fn from_ptr(ptr: *mut c_void) -> Option<Self> {
NonZeroU64::new(ptr.addr() as u64).map(Self)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum PixelShaderKind {
Brush,
Effect,
}
#[derive(Copy, Clone, Debug)]
pub struct PixelShaderDesc<'a> {
pub label: &'a str,
pub kind: PixelShaderKind,
pub source: &'a str,
pub textures: u32,
pub constants: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PixelShaderError(pub String);
impl fmt::Display for PixelShaderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl std::error::Error for PixelShaderError {}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct BatchShader<'a> {
pub shader: PixelShaderHandle,
pub textures: [Option<(TextureHandle, SamplerState)>; MAX_SHADER_TEXTURES],
pub constants: Option<&'a [u8]>,
}
impl BatchShader<'_> {
#[must_use]
pub fn new(shader: PixelShaderHandle) -> Self {
Self {
shader,
textures: [None; MAX_SHADER_TEXTURES],
constants: None,
}
}
#[cfg(feature = "shim")]
#[must_use]
pub fn from_batch(batch: &Batch) -> Option<Self> {
let mut shader = Self::new(PixelShaderHandle::from_ptr(batch.pixel_shader)?);
shader.textures[0] = batch.shadow_handle().map(|h| (h, batch.shadow_sampler));
Some(shader)
}
}