diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/gfx-hal/src/pso/specialization.rs | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/gfx-hal/src/pso/specialization.rs')
-rw-r--r-- | third_party/rust/gfx-hal/src/pso/specialization.rs | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/third_party/rust/gfx-hal/src/pso/specialization.rs b/third_party/rust/gfx-hal/src/pso/specialization.rs new file mode 100644 index 0000000000..d4c15c3d25 --- /dev/null +++ b/third_party/rust/gfx-hal/src/pso/specialization.rs @@ -0,0 +1,134 @@ +//! Pipeline specialization types. + +use std::{borrow::Cow, ops::Range, slice}; + +/// Description of a specialization constant for the pipeline. +#[derive(Debug, Clone, Hash, PartialEq)] +pub struct SpecializationConstant { + /// Constant identifier in shader source. + pub id: u32, + /// Value to override specialization constant. + pub range: Range<u16>, +} + +/// Information required for pipeline specialization. +/// +/// Specialization allows for easy configuration of multiple similar pipelines. +/// For example, there may be a boolean exposed to the shader that switches +/// the [specularity](https://en.wikipedia.org/wiki/Specularity) on/off, +/// provided via a [specialization constant][SpecializationConstant]. +/// +/// That would produce separate PSO's for the "on" and "off" states +/// but they share most of the internal stuff and are fast to produce. +/// More importantly, they are fast to execute, since the driver +/// can optimize out the branch on that other PSO creation. +#[derive(Debug, Clone)] +pub struct Specialization<'a> { + /// Array of descriptors of specialization constants to override. + pub constants: Cow<'a, [SpecializationConstant]>, + /// Raw data of the specialization constants + pub data: Cow<'a, [u8]>, +} + +impl Specialization<'_> { + /// Empty specialization instance. + pub const EMPTY: Self = Specialization { + constants: Cow::Borrowed(&[]), + data: Cow::Borrowed(&[]), + }; +} + +impl Default for Specialization<'_> { + fn default() -> Self { + Specialization::EMPTY + } +} + +#[doc(hidden)] +#[derive(Debug, Default)] +pub struct SpecializationStorage { + constants: Vec<SpecializationConstant>, + data: Vec<u8>, +} + +/// List of specialization constants. +#[doc(hidden)] +pub trait SpecConstList: Sized { + fn fold(self, storage: &mut SpecializationStorage); +} + +impl<T> From<T> for Specialization<'_> +where + T: SpecConstList, +{ + fn from(list: T) -> Self { + let mut storage = SpecializationStorage::default(); + list.fold(&mut storage); + Specialization { + data: Cow::Owned(storage.data), + constants: Cow::Owned(storage.constants), + } + } +} + +#[doc(hidden)] +#[derive(Debug)] +pub struct SpecConstListNil; + +#[doc(hidden)] +#[derive(Debug)] +pub struct SpecConstListCons<H, T> { + pub head: (u32, H), + pub tail: T, +} + +impl SpecConstList for SpecConstListNil { + fn fold(self, _storage: &mut SpecializationStorage) {} +} + +impl<H, T> SpecConstList for SpecConstListCons<H, T> +where + T: SpecConstList, +{ + fn fold(self, storage: &mut SpecializationStorage) { + let size = std::mem::size_of::<H>(); + assert!(storage.data.len() + size <= u16::max_value() as usize); + let offset = storage.data.len() as u16; + storage.data.extend_from_slice(unsafe { + // Inspecting bytes is always safe. + let head_ptr: *const H = &self.head.1; + slice::from_raw_parts(head_ptr as *const u8, size) + }); + storage.constants.push(SpecializationConstant { + id: self.head.0, + range: offset..offset + size as u16, + }); + self.tail.fold(storage) + } +} + +/// Macro for specifying list of specialization constants for `EntryPoint`. +#[macro_export] +macro_rules! spec_const_list { + (@ $(,)?) => { + $crate::pso::SpecConstListNil + }; + + (@ $head_id:expr => $head_constant:expr $(,$tail_id:expr => $tail_constant:expr)* $(,)?) => { + $crate::pso::SpecConstListCons { + head: ($head_id, $head_constant), + tail: $crate::spec_const_list!(@ $($tail_id => $tail_constant),*), + } + }; + + ($($id:expr => $constant:expr),* $(,)?) => { + $crate::spec_const_list!(@ $($id => $constant),*).into() + }; + + ($($constant:expr),* $(,)?) => { + { + let mut counter = 0; + $crate::spec_const_list!(@ $({ counter += 1; counter - 1 } => $constant),*).into() + } + }; +} |