Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  ast.rs   Sprache: unbekannt

 
use std::{borrow::Cow, fmt};

use super::{builtins::MacroCall, Span};
use crate::{
    AddressSpace, BinaryOperator, Binding, Constant, Expression, Function, GlobalVariable, Handle,
    Interpolation, Literal, Sampling, StorageAccess, Type, UnaryOperator,
};

#[derive(Debug, Clone, Copy)]
pub enum GlobalLookupKind {
    Variable(Handle<GlobalVariable>),
    Constant(Handle<Constant>, Handle<Type>),
    BlockSelect(Handle<GlobalVariable>, u32),
}

#[derive(Debug, Clone, Copy)]
pub struct GlobalLookup {
    pub kind: GlobalLookupKind,
    pub entry_arg: Option<usize>,
    pub mutable: bool,
}

#[derive(Debug, Clone)]
pub struct ParameterInfo {
    pub qualifier: ParameterQualifier,
    /// Whether the parameter should be treated as a depth image instead of a
    /// sampled image.
    pub depth: bool,
}

/// How the function is implemented
#[derive(Clone, Copy)]
pub enum FunctionKind {
    /// The function is user defined
    Call(Handle<Function>),
    /// The function is a builtin
    Macro(MacroCall),
}

impl fmt::Debug for FunctionKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Self::Call(_) => write!(f, "Call"),
            Self::Macro(_) => write!(f, "Macro"),
        }
    }
}

#[derive(Debug)]
pub struct Overload {
    /// Normalized function parameters, modifiers are not applied
    pub parameters: Vec<Handle<Type>>,
    pub parameters_info: Vec<ParameterInfo>,
    /// How the function is implemented
    pub kind: FunctionKind,
    /// Whether this function was already defined or is just a prototype
    pub defined: bool,
    /// Whether this overload is the one provided by the language or has
    /// been redeclared by the user (builtins only)
    pub internal: bool,
    /// Whether or not this function returns void (nothing)
    pub void: bool,
}

bitflags::bitflags! {
    /// Tracks the variations of the builtin already generated, this is needed because some
    /// builtins overloads can't be generated unless explicitly used, since they might cause
    /// unneeded capabilities to be requested
    #[derive(Default)]
    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    pub struct BuiltinVariations: u32 {
        /// Request the standard overloads
        const STANDARD = 1 << 0;
        /// Request overloads that use the double type
        const DOUBLE = 1 << 1;
        /// Request overloads that use `samplerCubeArray(Shadow)`
        const CUBE_TEXTURES_ARRAY = 1 << 2;
        /// Request overloads that use `sampler2DMSArray`
        const D2_MULTI_TEXTURES_ARRAY = 1 << 3;
    }
}

#[derive(Debug, Default)]
pub struct FunctionDeclaration {
    pub overloads: Vec<Overload>,
    /// Tracks the builtin overload variations that were already generated
    pub variations: BuiltinVariations,
}

#[derive(Debug)]
pub struct EntryArg {
    pub name: Option<String>,
    pub binding: Binding,
    pub handle: Handle<GlobalVariable>,
    pub storage: StorageQualifier,
}

#[derive(Debug, Clone)]
pub struct VariableReference {
    pub expr: Handle<Expression>,
    /// Whether the variable is of a pointer type (and needs loading) or not
    pub load: bool,
    /// Whether the value of the variable can be changed or not
    pub mutable: bool,
    pub constant: Option<(Handle<Constant>, Handle<Type>)>,
    pub entry_arg: Option<usize>,
}

#[derive(Debug, Clone)]
pub struct HirExpr {
    pub kind: HirExprKind,
    pub meta: Span,
}

#[derive(Debug, Clone)]
pub enum HirExprKind {
    Access {
        base: Handle<HirExpr>,
        index: Handle<HirExpr>,
    },
    Select {
        base: Handle<HirExpr>,
        field: String,
    },
    Literal(Literal),
    Binary {
        left: Handle<HirExpr>,
        op: BinaryOperator,
        right: Handle<HirExpr>,
    },
    Unary {
        op: UnaryOperator,
        expr: Handle<HirExpr>,
    },
    Variable(VariableReference),
    Call(FunctionCall),
    /// Represents the ternary operator in glsl (`:?`)
    Conditional {
        /// The expression that will decide which branch to take, must evaluate to a boolean
        condition: Handle<HirExpr>,
        /// The expression that will be evaluated if [`condition`] returns `true`
        ///
        /// [`condition`]: Self::Conditional::condition
        accept: Handle<HirExpr>,
        /// The expression that will be evaluated if [`condition`] returns `false`
        ///
        /// [`condition`]: Self::Conditional::condition
        reject: Handle<HirExpr>,
    },
    Assign {
        tgt: Handle<HirExpr>,
        value: Handle<HirExpr>,
    },
    /// A prefix/postfix operator like `++`
    PrePostfix {
        /// The operation to be performed
        op: BinaryOperator,
        /// Whether this is a postfix or a prefix
        postfix: bool,
        /// The target expression
        expr: Handle<HirExpr>,
    },
    /// A method call like `what.something(a, b, c)`
    Method {
        /// expression the method call applies to (`what` in the example)
        expr: Handle<HirExpr>,
        /// the method name (`something` in the example)
        name: String,
        /// the arguments to the method (`a`, `b`, and `c` in the example)
        args: Vec<Handle<HirExpr>>,
    },
}

#[derive(Debug, Hash, PartialEq, Eq)]
pub enum QualifierKey<'a> {
    String(Cow<'a, str>),
    /// Used for `std140` and `std430` layout qualifiers
    Layout,
    /// Used for image formats
    Format,
}

#[derive(Debug)]
pub enum QualifierValue {
    None,
    Uint(u32),
    Layout(StructLayout),
    Format(crate::StorageFormat),
}

#[derive(Debug, Default)]
pub struct TypeQualifiers<'a> {
    pub span: Span,
    pub storage: (StorageQualifier, Span),
    pub invariant: Option<Span>,
    pub interpolation: Option<(Interpolation, Span)>,
    pub precision: Option<(Precision, Span)>,
    pub sampling: Option<(Sampling, Span)>,
    /// Memory qualifiers used in the declaration to set the storage access to be used
    /// in declarations that support it (storage images and buffers)
    pub storage_access: Option<(StorageAccess, Span)>,
    pub layout_qualifiers: crate::FastHashMap<QualifierKey<'a>, (QualifierValue, Span)>,
}

impl<'a> TypeQualifiers<'a> {
    /// Appends `errors` with errors for all unused qualifiers
    pub fn unused_errors(&self, errors: &mut Vec<super::Error>) {
        if let Some(meta) = self.invariant {
            errors.push(super::Error {
                kind: super::ErrorKind::SemanticError(
                    "Invariant qualifier can only be used in in/out variables".into(),
                ),
                meta,
            });
        }

        if let Some((_, meta)) = self.interpolation {
            errors.push(super::Error {
                kind: super::ErrorKind::SemanticError(
                    "Interpolation qualifiers can only be used in in/out variables".into(),
                ),
                meta,
            });
        }

        if let Some((_, meta)) = self.sampling {
            errors.push(super::Error {
                kind: super::ErrorKind::SemanticError(
                    "Sampling qualifiers can only be used in in/out variables".into(),
                ),
                meta,
            });
        }

        if let Some((_, meta)) = self.storage_access {
            errors.push(super::Error {
                kind: super::ErrorKind::SemanticError(
                    "Memory qualifiers can only be used in storage variables".into(),
                ),
                meta,
            });
        }

        for &(_, meta) in self.layout_qualifiers.values() {
            errors.push(super::Error {
                kind: super::ErrorKind::SemanticError("Unexpected qualifier".into()),
                meta,
            });
        }
    }

    /// Removes the layout qualifier with `name`, if it exists and adds an error if it isn't
    /// a [`QualifierValue::Uint`]
    pub fn uint_layout_qualifier(
        &mut self,
        name: &'a str,
        errors: &mut Vec<super::Error>,
    ) -> Option<u32> {
        match self
            .layout_qualifiers
            .remove(&QualifierKey::String(name.into()))
        {
            Some((QualifierValue::Uint(v), _)) => Some(v),
            Some((_, meta)) => {
                errors.push(super::Error {
                    kind: super::ErrorKind::SemanticError("Qualifier expects a uint value".into()),
                    meta,
                });
                // Return a dummy value instead of `None` to differentiate from
                // the qualifier not existing, since some parts might require the
                // qualifier to exist and throwing another error that it doesn't
                // exist would be unhelpful
                Some(0)
            }
            _ => None,
        }
    }

    /// Removes the layout qualifier with `name`, if it exists and adds an error if it isn't
    /// a [`QualifierValue::None`]
    pub fn none_layout_qualifier(&mut self, name: &'a str, errors: &mut Vec<super::Error>) -> bool {
        match self
            .layout_qualifiers
            .remove(&QualifierKey::String(name.into()))
        {
            Some((QualifierValue::None, _)) => true,
            Some((_, meta)) => {
                errors.push(super::Error {
                    kind: super::ErrorKind::SemanticError(
                        "Qualifier doesn't expect a value".into(),
                    ),
                    meta,
                });
                // Return a `true` to since the qualifier is defined and adding
                // another error for it not being defined would be unhelpful
                true
            }
            _ => false,
        }
    }
}

#[derive(Debug, Clone)]
pub enum FunctionCallKind {
    TypeConstructor(Handle<Type>),
    Function(String),
}

#[derive(Debug, Clone)]
pub struct FunctionCall {
    pub kind: FunctionCallKind,
    pub args: Vec<Handle<HirExpr>>,
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum StorageQualifier {
    AddressSpace(AddressSpace),
    Input,
    Output,
    Const,
}

impl Default for StorageQualifier {
    fn default() -> Self {
        StorageQualifier::AddressSpace(AddressSpace::Function)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StructLayout {
    Std140,
    Std430,
}

// TODO: Encode precision hints in the IR
/// A precision hint used in GLSL declarations.
///
/// Precision hints can be used to either speed up shader execution or control
/// the precision of arithmetic operations.
///
/// To use a precision hint simply add it before the type in the declaration.
/// ```glsl
/// mediump float a;
/// ```
///
/// The default when no precision is declared is `highp` which means that all
/// operations operate with the type defined width.
///
/// For `mediump` and `lowp` operations follow the spir-v
/// [`RelaxedPrecision`][RelaxedPrecision] decoration semantics.
///
/// [RelaxedPrecision]: https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#_a_id_relaxedprecisionsection_a_relaxed_precision
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum Precision {
    /// `lowp` precision
    Low,
    /// `mediump` precision
    Medium,
    /// `highp` precision
    High,
}

#[derive(Debug, Clone, PartialEq, Copy)]
pub enum ParameterQualifier {
    In,
    Out,
    InOut,
    Const,
}

impl ParameterQualifier {
    /// Returns true if the argument should be passed as a lhs expression
    pub const fn is_lhs(&self) -> bool {
        match *self {
            ParameterQualifier::Out | ParameterQualifier::InOut => true,
            _ => false,
        }
    }
}

/// The GLSL profile used by a shader.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Profile {
    /// The `core` profile, default when no profile is specified.
    Core,
}

[ Dauer der Verarbeitung: 0.25 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge