bitflags::bitflags! { /// Validation flags. /// /// If you are working with trusted shaders, then you may be able /// to save some time by skipping validation. /// /// If you do not perform full validation, invalid shaders may /// cause Naga to panic. If you do perform full validation and /// [`Validator::validate`] returns `Ok`, then Naga promises that /// code generation will either succeed or return an error; it /// should never panic. /// /// The default value for `ValidationFlags` is /// `ValidationFlags::all()`. #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] #[derive(Clone, Copy, Debug, Eq, PartialEq)] pubstruct ValidationFlags: u8 { /// Expressions. const EXPRESSIONS = 0x1; /// Statements and blocks of them. const BLOCKS = 0x2; /// Uniformity of control flow for operations that require it. const CONTROL_FLOW_UNIFORMITY = 0x4; /// Host-shareable structure layouts. const STRUCT_LAYOUTS = 0x8; /// Constants. const CONSTANTS = 0x10; /// Group, binding, and location attributes. const BINDINGS = 0x20;
}
}
bitflags::bitflags! { /// Allowed IR capabilities. #[must_use] #[cfg_attr(feature = "serialize", derive(serde::Serialize))] #[cfg_attr(feature = "deserialize", derive(serde::Deserialize))] #[derive(Clone, Copy, Debug, Eq, PartialEq)] pubstruct Capabilities: u32 { /// Support for [`AddressSpace::PushConstant`][1]. /// /// [1]: crate::AddressSpace::PushConstant const PUSH_CONSTANT = 1 << 0; /// Float values with width = 8. const FLOAT64 = 1 << 1; /// Support for [`BuiltIn::PrimitiveIndex`][1]. /// /// [1]: crate::BuiltIn::PrimitiveIndex const PRIMITIVE_INDEX = 1 << 2; /// Support for non-uniform indexing of sampled textures and storage buffer arrays. const SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING = 1 << 3; /// Support for non-uniform indexing of uniform buffers and storage texture arrays. const UNIFORM_BUFFER_AND_STORAGE_TEXTURE_ARRAY_NON_UNIFORM_INDEXING = 1 << 4; /// Support for non-uniform indexing of samplers. const SAMPLER_NON_UNIFORM_INDEXING = 1 << 5; /// Support for [`BuiltIn::ClipDistance`]. /// /// [`BuiltIn::ClipDistance`]: crate::BuiltIn::ClipDistance const CLIP_DISTANCE = 1 << 6; /// Support for [`BuiltIn::CullDistance`]. /// /// [`BuiltIn::CullDistance`]: crate::BuiltIn::CullDistance const CULL_DISTANCE = 1 << 7; /// Support for 16-bit normalized storage texture formats. const STORAGE_TEXTURE_16BIT_NORM_FORMATS = 1 << 8; /// Support for [`BuiltIn::ViewIndex`]. /// /// [`BuiltIn::ViewIndex`]: crate::BuiltIn::ViewIndex const MULTIVIEW = 1 << 9; /// Support for `early_depth_test`. const EARLY_DEPTH_TEST = 1 << 10; /// Support for [`BuiltIn::SampleIndex`] and [`Sampling::Sample`]. /// /// [`BuiltIn::SampleIndex`]: crate::BuiltIn::SampleIndex /// [`Sampling::Sample`]: crate::Sampling::Sample const MULTISAMPLED_SHADING = 1 << 11; /// Support for ray queries and acceleration structures. const RAY_QUERY = 1 << 12; /// Support for generating two sources for blending from fragment shaders. const DUAL_SOURCE_BLENDING = 1 << 13; /// Support for arrayed cube textures. const CUBE_ARRAY_TEXTURES = 1 << 14; /// Support for 64-bit signed and unsigned integers. const SHADER_INT64 = 1 << 15; /// Support for subgroup operations. /// Implies support for subgroup operations in both fragment and compute stages, /// but not necessarily in the vertex stage, which requires [`Capabilities::SUBGROUP_VERTEX_STAGE`]. const SUBGROUP = 1 << 16; /// Support for subgroup barriers. const SUBGROUP_BARRIER = 1 << 17; /// Support for subgroup operations in the vertex stage. const SUBGROUP_VERTEX_STAGE = 1 << 18; /// Support for [`AtomicFunction::Min`] and [`AtomicFunction::Max`] on /// 64-bit integers in the [`Storage`] address space, when the return /// value is not used. /// /// This is the only 64-bit atomic functionality available on Metal 3.1. /// /// [`AtomicFunction::Min`]: crate::AtomicFunction::Min /// [`AtomicFunction::Max`]: crate::AtomicFunction::Max /// [`Storage`]: crate::AddressSpace::Storage const SHADER_INT64_ATOMIC_MIN_MAX = 1 << 19; /// Support for all atomic operations on 64-bit integers. const SHADER_INT64_ATOMIC_ALL_OPS = 1 << 20; /// Support for [`AtomicFunction::Add`], [`AtomicFunction::Sub`], /// and [`AtomicFunction::Exchange { compare: None }`] on 32-bit floating-point numbers /// in the [`Storage`] address space. /// /// [`AtomicFunction::Add`]: crate::AtomicFunction::Add /// [`AtomicFunction::Sub`]: crate::AtomicFunction::Sub /// [`AtomicFunction::Exchange { compare: None }`]: crate::AtomicFunction::Exchange /// [`Storage`]: crate::AddressSpace::Storage const SHADER_FLOAT32_ATOMIC = 1 << 21; /// Support for atomic operations on images. const TEXTURE_ATOMIC = 1 << 22;
}
}
/// A checklist of expressions that must be visited by a specific kind of /// statement. /// /// For example: /// /// - [`CallResult`] expressions must be visited by a [`Call`] statement. /// - [`AtomicResult`] expressions must be visited by an [`Atomic`] statement. /// /// Be sure not to remove any [`Expression`] handle from this set unless /// you've explicitly checked that it is the right kind of expression for /// the visiting [`Statement`]. /// /// [`CallResult`]: crate::Expression::CallResult /// [`Call`]: crate::Statement::Call /// [`AtomicResult`]: crate::Expression::AtomicResult /// [`Atomic`]: crate::Statement::Atomic /// [`Expression`]: crate::Expression /// [`Statement`]: crate::Statement
needs_visit: HandleSet<crate::Expression>,
}
#[derive(Clone, Debug, thiserror::Error)] #[cfg_attr(test, derive(PartialEq))] pubenum ConstantError { #[error("Initializer must be a const-expression")]
InitializerExprType, #[error("The type doesn't match the constant")]
InvalidType, #[error("The type is not constructible")]
NonConstructibleType,
}
#[derive(Clone, Debug, thiserror::Error)] #[cfg_attr(test, derive(PartialEq))] pubenum OverrideError { #[error("Override name and ID are missing")]
MissingNameAndID, #[error("Override ID must be unique")]
DuplicateID, #[error("Initializer must be a const-expression or override-expression")]
InitializerExprType, #[error("The type doesn't match the override")]
InvalidType, #[error("The type is not constructible")]
NonConstructibleType, #[error("The type is not a scalar")]
TypeNotScalar, #[error("Override declarations are not allowed")]
NotAllowed,
}
#[derive(Clone, Debug, thiserror::Error)] #[cfg_attr(test, derive(PartialEq))] pubenum ValidationError { #[error(transparent)]
InvalidHandle(#[from] InvalidHandleError), #[error(transparent)]
Layouter(#[from] LayoutError), #[error("Type {handle:?} '{name}' is invalid")] Type {
handle: Handle<crate::Type>,
name: String,
source: TypeError,
}, #[error("Constant expression {handle:?} is invalid")]
ConstExpression {
handle: Handle<crate::Expression>,
source: ConstExpressionError,
}, #[error("Array size expression {handle:?} is not strictly positive")]
ArraySizeError { handle: Handle<crate::Expression> }, #[error("Constant {handle:?} '{name}' is invalid")]
Constant {
handle: Handle<crate::Constant>,
name: String,
source: ConstantError,
}, #[error("Override {handle:?} '{name}' is invalid")] Override {
handle: Handle<crate::Override>,
name: String,
source: OverrideError,
}, #[error("Global variable {handle:?} '{name}' is invalid")]
GlobalVariable {
handle: Handle<crate::GlobalVariable>,
name: String,
source: GlobalVariableError,
}, #[error("Function {handle:?} '{name}' is invalid")]
Function {
handle: Handle<crate::Function>,
name: String,
source: FunctionError,
}, #[error("Entry point {name} at {stage:?} is invalid")]
EntryPoint {
stage: crate::ShaderStage,
name: String,
source: EntryPointError,
}, #[error("Module is corrupted")]
Corrupted,
}
fn validate_constant(
&self,
handle: Handle<crate::Constant>,
gctx: crate::proc::GlobalCtx,
mod_info: &ModuleInfo,
global_expr_kind: &ExpressionKindTracker,
) -> Result<(), ConstantError> { let con = &gctx.constants[handle];
let type_info = &self.types[con.ty.index()]; if !type_info.flags.contains(TypeFlags::CONSTRUCTIBLE) { return Err(ConstantError::NonConstructibleType);
}
if !global_expr_kind.is_const(con.init) { return Err(ConstantError::InitializerExprType);
}
let decl_ty = &gctx.types[con.ty].inner; let init_ty = mod_info[con.init].inner_with(gctx.types); if !decl_ty.equivalent(init_ty, gctx.types) { return Err(ConstantError::InvalidType);
}
iflet Some(init) = o.init { let init_ty = mod_info[init].inner_with(gctx.types); if !decl_ty.equivalent(init_ty, gctx.types) { return Err(OverrideError::InvalidType);
}
}
Ok(())
}
/// Check the given module to be valid. pubfn validate(
&mutself,
module: &crate::Module,
) -> Result<ModuleInfo, WithSpan<ValidationError>> { self.allow_overrides = true; self.validate_impl(module)
}
/// Check the given module to be valid. /// /// With the additional restriction that overrides are not present. pubfn validate_no_overrides(
&mutself,
module: &crate::Module,
) -> Result<ModuleInfo, WithSpan<ValidationError>> { self.allow_overrides = false; self.validate_impl(module)
}
self.layouter.update(module.to_ctx()).map_err(|e| { let handle = e.ty;
ValidationError::from(e).with_span_handle(handle, &module.types)
})?;
// These should all get overwritten. let placeholder = TypeResolution::Value(crate::TypeInner::Scalar(crate::Scalar {
kind: crate::ScalarKind::Bool,
width: 0,
}));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.