From 696ca340e00490ad0435009226f7279bb6f8d68b Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Wed, 16 Jun 2021 16:54:55 -0700 Subject: [PATCH] Improve docs for `TypeInner`, `valid::TypeFlags`, and some internal types. --- src/back/spv/mod.rs | 12 +++++++++ src/lib.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++ src/valid/type.rs | 31 +++++++++++++++++++++- 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/back/spv/mod.rs b/src/back/spv/mod.rs index daabc4c4e6..f1522a5c4d 100644 --- a/src/back/spv/mod.rs +++ b/src/back/spv/mod.rs @@ -127,14 +127,26 @@ impl Function { } } +/// A SPIR-V type constructed during code generation. +/// +/// In the process of writing SPIR-V, we need to synthesize various types for +/// intermediate results and such. However, it's inconvenient to use +/// `crate::Type` or `crate::TypeInner` for these, as the IR module is immutable +/// so we can't ever create a `Handle` to refer to them. So for local use +/// in the SPIR-V writer, we have this home-grown type enum that covers only the +/// cases we need (for example, it doesn't cover structs). #[derive(Debug, PartialEq, Hash, Eq, Copy, Clone)] enum LocalType { + /// A scalar, vector, or pointer to one of those. Value { + /// If `None`, this represents a scalar type. If `Some`, this represents + /// a vector type of the given size. vector_size: Option, kind: crate::ScalarKind, width: crate::Bytes, pointer_class: Option, }, + /// A matrix of floating-point values. Matrix { columns: crate::VectorSize, rows: crate::VectorSize, diff --git a/src/lib.rs b/src/lib.rs index f109e2e3e6..361c080693 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -476,6 +476,26 @@ pub enum TypeInner { width: Bytes, }, /// Pointer to another type. + /// + /// ## Pointers to non-`SIZED` types + /// + /// The `base` type of a pointer may be a non-[`SIZED`] type like a + /// dynamically-sized [`Array`], or a [`Struct`] whose last member is a + /// dynamically sized array. Such pointers occur as the types of + /// [`GlobalVariable`] or [`AccessIndex`] expressions referring to + /// dynamically-sized arrays. + /// + /// However, among pointers to non-`SIZED` types, only pointers to `Struct`s + /// are [`DATA`]. Pointers to dynamically sized `Array`s cannot be passed as + /// arguments, stored in variables, or held in arrays or structures. Their + /// only use is as the types of `AccessIndex` expressions. + /// + /// [`SIZED`]: valid::TypeFlags::SIZED + /// [`DATA`]: valid::TypeFlags::DATA + /// [`Array`]: TypeInner::Array + /// [`Struct`]: TypeInner::Struct + /// [`GlobalVariable`]: Expression::GlobalVariable + /// [`AccessIndex`]: Expression::AccessIndex Pointer { base: Handle, class: StorageClass, @@ -487,14 +507,57 @@ pub enum TypeInner { width: Bytes, class: StorageClass, }, + /// Homogenous list of elements. + /// + /// The `base` type must be a [`SIZED`], [`DATA`] type. + /// + /// ## Dynamically sized arrays + /// + /// An `Array` is [`SIZED`] unless its `size` is [`Dynamic`]. + /// Dynamically-sized arrays may only appear in a few situations: + /// + /// - They may appear as the last member of a [`Struct`] whose `top_level` + /// flag is set. + /// + /// - They may appear as the base type of a [`Pointer`]. An + /// [`AccessIndex`] expression referring to a top-level struct's final + /// unsized array member would have such a pointer type. However, such + /// pointer types may only appear as the types of such intermediate + /// expressions. They are not [`DATA`], and cannot be stored in + /// variables, held in arrays or structs, or passed as parameters. + /// + /// [`SIZED`]: crate::valid::TypeFlags::SIZED + /// [`DATA`]: crate::valid::TypeFlags::DATA + /// [`Dynamic`]: ArraySize::Dynamic + /// [`Struct`]: TypeInner::Struct + /// [`Pointer`]: TypeInner::Pointer + /// [`AccessIndex`]: Expression::AccessIndex Array { base: Handle, size: ArraySize, stride: u32, }, + /// User-defined structure. + /// + /// A `Struct` type is [`DATA`], and the types of its members must be + /// `DATA` as well. + /// + /// Member types must be [`SIZED`], except for the final member of a + /// top-level struct, which may be a dynamically sized [`Array`]. The + /// `Struct` type itself is `SIZED` when all its members are `SIZED`. + /// + /// When `top_level` is true, this `Struct` represents the contents of a + /// buffer resource occupying a single binding slot in a shader's resource + /// interface. Top-level `Struct`s may not be used as members of any other + /// struct, or as array elements. + /// + /// [`DATA`]: crate::valid::TypeFlags::DATA + /// [`SIZED`]: crate::valid::TypeFlags::SIZED + /// [`Array`]: TypeInner::Array Struct { + /// This struct serves as the type of a binding slot in a shader's resource interface. top_level: bool, members: Vec, //TODO: should this be unaligned? diff --git a/src/valid/type.rs b/src/valid/type.rs index 7ddc0f6aa3..474c5dc0af 100644 --- a/src/valid/type.rs +++ b/src/valid/type.rs @@ -5,16 +5,45 @@ use crate::{ }; bitflags::bitflags! { + /// Flags associated with [`Type`]s by [`Validator`]. + /// + /// [`Type`]: crate::Type + /// [`Validator`]: crate::valid::Validator #[repr(transparent)] pub struct TypeFlags: u8 { /// Can be used for data variables. + /// + /// This flag is required on types of local variables, function + /// arguments, array elements, and struct members. + /// + /// This includes all types except `Image`, `Sampler`, `ValuePointer`, + /// and some `Pointer` types. const DATA = 0x1; - /// The data type has known size. + + /// The data type has a size known by pipeline creation time. + /// + /// Unsized types are quite restricted. The only unsized types permitted + /// by Naga, other than the non-[`DATA`] types like [`Image`] and + /// [`Sampler`], are dynamically-sized [`Array`s], and [`Struct`s] whose + /// last members are such arrays. See the documentation for those types + /// for details. + /// + /// [`DATA`]: TypeFlags::DATA + /// [`Image`]: crate::Type::Image + /// [`Sampler`]: crate::Type::Sampler + /// [`Array`]: crate::Type::Array + /// [`Struct`]: crate::Type::struct const SIZED = 0x2; + /// Can be be used for interfacing between pipeline stages. + /// + /// This includes non-bool scalars and vectors, matrices, and structs + /// and arrays containing only interface types. const INTERFACE = 0x4; + /// Can be used for host-shareable structures. const HOST_SHARED = 0x8; + /// This is a top-level host-shareable type. const TOP_LEVEL = 0x10; }