summaryrefslogtreecommitdiffstats
path: root/third_party/rust/gfx-hal/src/pso/specialization.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/gfx-hal/src/pso/specialization.rs
parentInitial commit. (diff)
downloadfirefox-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.rs134
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()
+ }
+ };
+}