Standardize some docs (#1660)

* Rewrite front/back doc summaries

- Use line comments instead of block comments
- Standardize language for each front/backend
- Add reference link for each format
- Minor punctuation changes

* Add documentation for keywords module

* Clarify contents of keywords module in summary

* Refer to modules by their type name

* Add basic summary for valid module

* Adjust EarlyDepthTest and ConservativeDepth docs

* Remove "in" from list

* Adjust wording

* Standardize format of docstrings

* Adjust module links to be consistent with other links

* Add summary for reserved keywords list

* Remove extraneous doc spaces with `cargo fmt`

* Correct spelling of whether and rewrite some lines

* Fill out GLSL backend docs

* Remove unnecessary link targets

* Fill out DOT backend docs

* Change module line comments to block comments

* Remove unnecessary spaces

* Fix mistake during rebasing
This commit is contained in:
Noel Tautges
2022-02-03 12:27:21 -06:00
committed by GitHub
parent f63003cd36
commit 42bf3545c9
36 changed files with 393 additions and 298 deletions

View File

@@ -3,7 +3,7 @@
use std::fs;
use std::{error::Error, fmt, io::Read, path::Path, str::FromStr};
/// Translate shaders to different formats
/// Translate shaders to different formats.
#[derive(argh::FromArgs, Debug, Clone)]
struct Args {
/// bitmask of the ValidationFlags to be used, use 0 to disable validation

View File

@@ -1,8 +1,11 @@
/*! GraphViz (DOT) backend
*
* This backend writes a graph in the DOT format, for the ease
* of IR inspection and debugging.
!*/
/*!
Backend for [DOT][dot] (Graphviz).
This backend writes a graph in the DOT language, for the ease
of IR inspection and debugging.
[dot]: https://graphviz.org/doc/info/lang.html
*/
use crate::{
arena::Handle,
@@ -470,6 +473,7 @@ fn write_fun(
Ok(())
}
/// Write shader module to a [`String`].
pub fn write(module: &crate::Module, mod_info: Option<&ModuleInfo>) -> Result<String, FmtError> {
use std::fmt::Write as _;

View File

@@ -6,56 +6,57 @@ use crate::{
use std::fmt::Write;
bitflags::bitflags! {
/// Structure used to encode a set of additions to glsl that aren't supported by all versions
/// Structure used to encode additions to GLSL that aren't supported by all versions.
pub struct Features: u32 {
/// Buffer address space support
/// Buffer address space support.
const BUFFER_STORAGE = 1;
const ARRAY_OF_ARRAYS = 1 << 1;
/// 8 byte floats
/// 8 byte floats.
const DOUBLE_TYPE = 1 << 2;
/// Includes support for more image formats
/// More image formats.
const FULL_IMAGE_FORMATS = 1 << 3;
const MULTISAMPLED_TEXTURES = 1 << 4;
const MULTISAMPLED_TEXTURE_ARRAYS = 1 << 5;
const CUBE_TEXTURES_ARRAY = 1 << 6;
const COMPUTE_SHADER = 1 << 7;
/// Adds support for image load and early depth tests
/// Image load and early depth tests.
const IMAGE_LOAD_STORE = 1 << 8;
const CONSERVATIVE_DEPTH = 1 << 9;
/// Interpolation and auxiliary qualifiers. Perspective, Flat, and
/// Centroid are available in all GLSL versions we support.
/// Interpolation and auxiliary qualifiers.
///
/// Perspective, Flat, and Centroid are available in all GLSL versions we support.
const NOPERSPECTIVE_QUALIFIER = 1 << 11;
const SAMPLE_QUALIFIER = 1 << 12;
const CLIP_DISTANCE = 1 << 13;
const CULL_DISTANCE = 1 << 14;
// Sample ID
/// Sample ID.
const SAMPLE_VARIABLES = 1 << 15;
/// Arrays with a dynamic length
/// Arrays with a dynamic length.
const DYNAMIC_ARRAY_SIZE = 1 << 16;
const MULTI_VIEW = 1 << 17;
/// Adds support for fused multiply-add
/// Fused multiply-add.
const FMA = 1 << 18;
}
}
/// Helper structure used to store the required [`Features`](Features) needed to output a
/// Helper structure used to store the required [`Features`] needed to output a
/// [`Module`](crate::Module)
///
/// Provides helper methods to check for availability and writing required extensions
pub struct FeaturesManager(Features);
impl FeaturesManager {
/// Creates a new [`FeaturesManager`](FeaturesManager) instance
/// Creates a new [`FeaturesManager`] instance
pub fn new() -> Self {
Self(Features::empty())
}
/// Adds to the list of required [`Features`](Features)
/// Adds to the list of required [`Features`]
pub fn request(&mut self, features: Features) {
self.0 |= features
}
/// Checks that all required [`Features`](Features) are available for the specified
/// Checks that all required [`Features`] are available for the specified
/// [`Version`](super::Version) otherwise returns an
/// [`Error::MissingFeatures`](super::Error::MissingFeatures)
pub fn check_availability(&self, version: Version) -> BackendResult {
@@ -214,10 +215,10 @@ impl FeaturesManager {
}
impl<'a, W> Writer<'a, W> {
/// Helper method that searches the module for all the needed [`Features`](Features)
/// Helper method that searches the module for all the needed [`Features`]
///
/// # Errors
/// If the version doesn't support any of the needed [`Features`](Features) a
/// If the version doesn't support any of the needed [`Features`] a
/// [`Error::MissingFeatures`](super::Error::MissingFeatures) will be returned
pub(super) fn collect_required_features(&mut self) -> BackendResult {
let ep_info = self.info.get_entry_point(self.entry_point_idx as usize);
@@ -386,7 +387,7 @@ impl<'a, W> Writer<'a, W> {
self.features.check_availability(self.options.version)
}
/// Helper method that checks the [`Features`](Features) needed by a scalar
/// Helper method that checks the [`Features`] needed by a scalar
fn scalar_required_features(&mut self, kind: ScalarKind, width: Bytes) {
if kind == ScalarKind::Float && width == 8 {
self.features.request(Features::DOUBLE_TYPE);

View File

@@ -1,22 +1,25 @@
//! OpenGL shading language backend
//!
//! The main structure is [`Writer`](Writer), it maintains internal state that is used
//! to output a [`Module`](crate::Module) into glsl
//!
//! # Supported versions
//! ### Core
//! - 330
//! - 400
//! - 410
//! - 420
//! - 430
//! - 450
//! - 460
//!
//! ### ES
//! - 300
//! - 310
//!
/*!
Backend for [GLSL][glsl] (OpenGL Shading Language).
The main structure is [`Writer`], it maintains internal state that is used
to output a [`Module`](crate::Module) into glsl
# Supported versions
### Core
- 330
- 400
- 410
- 420
- 430
- 450
- 460
### ES
- 300
- 310
[glsl]: https://www.khronos.org/registry/OpenGL/index_gl.php
*/
// GLSL is mostly a superset of C but it also removes some parts of it this is a list of relevant
// aspects for this backend.
@@ -33,7 +36,7 @@
// `#extension name: behaviour`
// Extensions provide increased features in a plugin fashion but they aren't required to be
// supported hence why they are called extensions, that's why `behaviour` is used it specifies
// wether the extension is strictly required or if it should only be enabled if needed. In our case
// whether the extension is strictly required or if it should only be enabled if needed. In our case
// when we use extensions we set behaviour to `require` always.
//
// The only thing that glsl removes that makes a difference are pointers.
@@ -61,11 +64,12 @@ mod features;
/// Contains a constant with a slice of all the reserved keywords RESERVED_KEYWORDS
mod keywords;
/// List of supported core glsl versions
/// List of supported `core` GLSL versions.
pub const SUPPORTED_CORE_VERSIONS: &[u16] = &[330, 400, 410, 420, 430, 440, 450];
/// List of supported es glsl versions
/// List of supported `es` GLSL versions.
pub const SUPPORTED_ES_VERSIONS: &[u16] = &[300, 310, 320];
/// Mapping between resources and bindings.
pub type BindingMap = std::collections::BTreeMap<crate::ResourceBinding, u8>;
impl crate::AtomicFunction {
@@ -130,14 +134,14 @@ impl<'a> GlobalTypeKind<'a> {
}
}
/// glsl version
/// A GLSL version.
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub enum Version {
/// `core` glsl
/// `core` GLSL.
Desktop(u16),
/// `es` glsl
/// `es` GLSL.
Embedded(u16),
}
@@ -206,10 +210,11 @@ impl fmt::Display for Version {
}
bitflags::bitflags! {
/// Configuration flags for the [`Writer`].
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub struct WriterFlags: u32 {
/// Flip output Y and extend Z from (0,1) to (-1,1).
/// Flip output Y and extend Z from (0, 1) to (-1, 1).
const ADJUST_COORDINATE_SPACE = 0x1;
/// Supports GL_EXT_texture_shadow_lod on the host, which provides
/// additional functions on shadows and arrays of shadows.
@@ -217,14 +222,14 @@ bitflags::bitflags! {
}
}
/// Structure that contains the configuration used in the [`Writer`](Writer)
/// Configuration used in the [`Writer`].
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub struct Options {
/// The glsl version to be used
/// The GLSL version to be used.
pub version: Version,
/// Configuration flags for the writer.
/// Configuration flags for the [`Writer`].
pub writer_flags: WriterFlags,
/// Map of resources association to binding locations.
pub binding_map: BindingMap,
@@ -240,40 +245,41 @@ impl Default for Options {
}
}
// A subset of options that are meant to be changed per pipeline.
/// A subset of options meant to be changed per pipeline.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub struct PipelineOptions {
/// The stage of the entry point
/// The stage of the entry point.
pub shader_stage: ShaderStage,
/// The name of the entry point
/// The name of the entry point.
///
/// If no entry point that matches is found a error will be thrown while creating a new instance
/// of [`Writer`](struct.Writer.html)
/// If no entry point that matches is found while creating a [`Writer`], a error will be thrown.
pub entry_point: String,
}
/// Structure that contains a reflection info
/// Reflection info for texture mappings and uniforms.
pub struct ReflectionInfo {
/// Mapping between texture names and variables/samplers.
pub texture_mapping: crate::FastHashMap<String, TextureMapping>,
/// Mapping between uniform variables and names.
pub uniforms: crate::FastHashMap<Handle<crate::GlobalVariable>, String>,
}
/// Structure that connects a texture to a sampler or not
/// Mapping between a texture and its sampler, if it exists.
///
/// glsl pre vulkan has no concept of separate textures and samplers instead everything is a
/// `gsamplerN` where `g` is the scalar type and `N` is the dimension, but naga uses separate textures
/// and samplers in the IR so the backend produces a [`HashMap`](crate::FastHashMap) with the texture name
/// as a key and a [`TextureMapping`](TextureMapping) as a value this way the user knows where to bind.
/// GLSL pre-Vulkan has no concept of separate textures and samplers. Instead, everything is a
/// `gsamplerN` where `g` is the scalar type and `N` is the dimension. But naga uses separate textures
/// and samplers in the IR, so the backend produces a [`FastHashMap`](crate::FastHashMap) with the texture name
/// as a key and a [`TextureMapping`] as a value. This way, the user knows where to bind.
///
/// [`Storage`](crate::ImageClass::Storage) images produce `gimageN` and don't have an associated sampler
/// so the [`sampler`](Self::sampler) field will be [`None`](std::option::Option::None)
/// [`Storage`](crate::ImageClass::Storage) images produce `gimageN` and don't have an associated sampler,
/// so the [`sampler`](Self::sampler) field will be [`None`].
#[derive(Debug, Clone)]
pub struct TextureMapping {
/// Handle to the image global variable
/// Handle to the image global variable.
pub texture: Handle<crate::GlobalVariable>,
/// Handle to the associated sampler global variable if it exists
/// Handle to the associated sampler global variable, if it exists.
pub sampler: Option<Handle<crate::GlobalVariable>>,
}
@@ -338,88 +344,88 @@ impl ShaderStage {
/// Shorthand result used internally by the backend
type BackendResult<T = ()> = Result<T, Error>;
/// A glsl compilation error.
/// A GLSL compilation error.
#[derive(Debug, Error)]
pub enum Error {
/// A error occurred while writing to the output
/// A error occurred while writing to the output.
#[error("Format error")]
FmtError(#[from] FmtError),
/// The specified [`Version`](Version) doesn't have all required [`Features`](super)
/// The specified [`Version`] doesn't have all required [`Features`].
///
/// Contains the missing [`Features`](Features)
/// Contains the missing [`Features`].
#[error("The selected version doesn't support {0:?}")]
MissingFeatures(Features),
/// [`AddressSpace::PushConstant`](crate::AddressSpace::PushConstant) was used more than
/// once in the entry point which isn't supported
/// once in the entry point, which isn't supported.
#[error("Multiple push constants aren't supported")]
MultiplePushConstants,
/// The specified [`Version`](Version) isn't supported
/// The specified [`Version`] isn't supported.
#[error("The specified version isn't supported")]
VersionNotSupported,
/// The entry point couldn't be found
/// The entry point couldn't be found.
#[error("The requested entry point couldn't be found")]
EntryPointNotFound,
/// A call was made to an unsupported external
/// A call was made to an unsupported external.
#[error("A call was made to an unsupported external: {0}")]
UnsupportedExternal(String),
/// A scalar with an unsupported width was requested
/// A scalar with an unsupported width was requested.
#[error("A scalar with an unsupported width was requested: {0:?} {1:?}")]
UnsupportedScalar(crate::ScalarKind, crate::Bytes),
/// A image was used with multiple samplers, this isn't supported
/// A image was used with multiple samplers, which isn't supported.
#[error("A image was used with multiple samplers")]
ImageMultipleSamplers,
#[error("{0}")]
Custom(String),
}
/// Binary operation with a different logic on the GLSL side
/// Binary operation with a different logic on the GLSL side.
enum BinaryOperation {
/// Vector comparison should use the function like `greaterThan()`, etc.
VectorCompare,
/// GLSL `%` is SPIR-V `OpUMod/OpSMod` and `mod()` is `OpFMod`, but [`BinaryOperator::Modulo`](crate::BinaryOperator::Modulo) is `OpFRem`
/// GLSL `%` is SPIR-V `OpUMod/OpSMod` and `mod()` is `OpFMod`, but [`BinaryOperator::Modulo`](crate::BinaryOperator::Modulo) is `OpFRem`.
Modulo,
/// Any plain operation. No additional logic required
/// Any plain operation. No additional logic required.
Other,
}
/// Main structure of the glsl backend responsible for all code generation
/// Writer responsible for all code generation.
pub struct Writer<'a, W> {
// Inputs
/// The module being written
/// The module being written.
module: &'a crate::Module,
/// The module analysis.
info: &'a valid::ModuleInfo,
/// The output writer
/// The output writer.
out: W,
/// User defined configuration to be used
/// User defined configuration to be used.
options: &'a Options,
// Internal State
/// Features manager used to store all the needed features and write them
/// Features manager used to store all the needed features and write them.
features: FeaturesManager,
namer: proc::Namer,
/// A map with all the names needed for writing the module
/// (generated by a [`Namer`](crate::proc::Namer))
/// (generated by a [`Namer`](crate::proc::Namer)).
names: crate::FastHashMap<NameKey, String>,
/// A map with the names of global variables needed for reflections
/// A map with the names of global variables needed for reflections.
reflection_names_globals: crate::FastHashMap<Handle<crate::GlobalVariable>, String>,
/// The selected entry point
/// The selected entry point.
entry_point: &'a crate::EntryPoint,
/// The index of the selected entry point
/// The index of the selected entry point.
entry_point_idx: proc::EntryPointIndex,
/// Used to generate a unique number for blocks
/// A generator for unique block numbers.
block_id: IdGenerator,
/// Set of expressions that have associated temporary variables
/// Set of expressions that have associated temporary variables.
named_expressions: crate::NamedExpressions,
}
impl<'a, W: Write> Writer<'a, W> {
/// Creates a new [`Writer`](Writer) instance
/// Creates a new [`Writer`] instance.
///
/// # Errors
/// - If the version specified isn't supported (or invalid)
/// - If the entry point couldn't be found on the module
/// - If the version specified doesn't support some used features
/// - If the version specified is invalid or supported.
/// - If the entry point couldn't be found in the module.
/// - If the version specified doesn't support some used features.
pub fn new(
out: W,
module: &'a crate::Module,
@@ -1988,7 +1994,7 @@ impl<'a, W: Write> Writer<'a, W> {
Expression::Load { pointer } => self.write_expr(pointer, ctx)?,
// `ImageSample` is a bit complicated compared to the rest of the IR.
//
// First there are three variations depending wether the sample level is explicitly set,
// First there are three variations depending whether the sample level is explicitly set,
// if it's automatic or it it's bias:
// `texture(image, coordinate)` - Automatic sample level
// `texture(image, coordinate, bias)` - Bias sample level

View File

@@ -1,28 +1,30 @@
//! Helpers for the hlsl backend
//!
//! Important note about `Expression::ImageQuery`/`Expression::ArrayLength` and hlsl backend:
//!
//! Due to implementation of `GetDimensions` function in hlsl (<https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-to-getdimensions>)
//! backend can't work with it as an expression.
//! Instead, it generates a unique wrapped function per `Expression::ImageQuery`, based on texure info and query function.
//! See `WrappedImageQuery` struct that represents a unique function and will be generated before writing all statements and expressions.
//! This allowed to works with `Expression::ImageQuery` as expression and write wrapped function.
//!
//! For example:
//! ```wgsl
//! let dim_1d = textureDimensions(image_1d);
//! ```
//!
//! ```hlsl
//! int NagaDimensions1D(Texture1D<float4>)
//! {
//! uint4 ret;
//! image_1d.GetDimensions(ret.x);
//! return ret.x;
//! }
//!
//! int dim_1d = NagaDimensions1D(image_1d);
//! ```
/*!
Helpers for the hlsl backend
Important note about `Expression::ImageQuery`/`Expression::ArrayLength` and hlsl backend:
Due to implementation of `GetDimensions` function in hlsl (<https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-to-getdimensions>)
backend can't work with it as an expression.
Instead, it generates a unique wrapped function per `Expression::ImageQuery`, based on texure info and query function.
See `WrappedImageQuery` struct that represents a unique function and will be generated before writing all statements and expressions.
This allowed to works with `Expression::ImageQuery` as expression and write wrapped function.
For example:
```wgsl
let dim_1d = textureDimensions(image_1d);
```
```hlsl
int NagaDimensions1D(Texture1D<float4>)
{
uint4 ret;
image_1d.GetDimensions(ret.x);
return ret.x;
}
int dim_1d = NagaDimensions1D(image_1d);
```
*/
use super::{super::FunctionCtx, BackendResult, Error};
use crate::{arena::Handle, proc::NameKey};

View File

@@ -1,6 +1,9 @@
//! HLSL Reserved Words
//! - <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-keywords>
//! - <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-reserved-words>
/*!
HLSL Reserved Words
- <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-keywords>
- <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-appendix-reserved-words>
*/
pub const RESERVED: &[&str] = &[
"AppendStructuredBuffer",
"asm",

View File

@@ -1,21 +1,25 @@
//! HLSL shading language backend
//!
//! # Supported shader model versions:
//! - 5.0
//! - 5.1
//! - 6.0
//!
//! All matrix construction/deconstruction is row based in HLSL. This means that when
//! we construct a matrix from column vectors, our matrix will be implicitly transposed.
//! The inverse transposition happens when we call `[0]` to get the zeroth column vector.
//!
//! Because all of our matrices are implicitly transposed, we flip arguments to `mul`. `mat * vec`
//! becomes `vec * mat`, etc. This acts as the inverse transpose making the results identical.
//!
//! The only time we don't get this implicit transposition is when reading matrices from Uniforms/Push Constants.
//! To deal with this, we add `row_major` to all declarations of matrices in Uniforms/Push Constants.
//!
//! Finally because all of our matrices are transposed, if you use `mat3x4`, it'll become `float4x3` in HLSL.
/*!
Backend for [HLSL][hlsl] (High-Level Shading Language).
# Supported shader model versions:
- 5.0
- 5.1
- 6.0
All matrix construction/deconstruction is row based in HLSL. This means that when
we construct a matrix from column vectors, our matrix will be implicitly transposed.
The inverse transposition happens when we call `[0]` to get the zeroth column vector.
Because all of our matrices are implicitly transposed, we flip arguments to `mul`. `mat * vec`
becomes `vec * mat`, etc. This acts as the inverse transpose making the results identical.
The only time we don't get this implicit transposition is when reading matrices from Uniforms/Push Constants.
To deal with this, we add `row_major` to all declarations of matrices in Uniforms/Push Constants.
Finally because all of our matrices are transposed, if you use `mat3x4`, it'll become `float4x3` in HLSL.
[hlsl]: https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl
*/
mod conv;
mod help;
@@ -92,7 +96,7 @@ pub enum EntryPointError {
MissingBinding(crate::ResourceBinding),
}
/// Structure that contains the configuration used in the [`Writer`](Writer)
/// Configuration used in the [`Writer`].
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
@@ -135,14 +139,15 @@ impl Options {
}
}
/// Structure that contains a reflection info
/// Reflection info for entry point names.
#[derive(Default)]
pub struct ReflectionInfo {
/// Mapping of the entry point names. Each item in the array
/// corresponds to an entry point index. The real entry point name may be different if one of the
/// Mapping of the entry point names.
///
/// Each item in the array corresponds to an entry point index. The real entry point name may be different if one of the
/// reserved words are used.
///
///Note: Some entry points may fail translation because of missing bindings.
/// Note: Some entry points may fail translation because of missing bindings.
pub entry_point_names: Vec<Result<String, EntryPointError>>,
}

View File

@@ -1,6 +1,8 @@
//! Logic related to `ByteAddressBuffer` operations.
//!
//! HLSL backend uses byte address buffers for all storage buffers in IR.
/*!
Logic related to `ByteAddressBuffer` operations.
HLSL backend uses byte address buffers for all storage buffers in IR.
*/
use super::{super::FunctionCtx, BackendResult, Error};
use crate::{

View File

@@ -1,4 +1,6 @@
//! Functions which export shader modules into binary and text formats.
/*!
Backend functions that export shader [`Module`](super::Module)s into binary and text formats.
*/
#[cfg(feature = "dot-out")]
pub mod dot;
@@ -202,9 +204,9 @@ impl crate::TypeInner {
}
impl crate::Statement {
/// Returns true if the statement directly terminates the current block
/// Returns true if the statement directly terminates the current block.
///
/// Used to decided wether case blocks require a explicit `break`
/// Used to decide whether case blocks require a explicit `break`.
pub fn is_terminator(&self) -> bool {
match *self {
crate::Statement::Break

View File

@@ -1,4 +1,5 @@
/*! Metal Shading Language (MSL) backend
/*!
Backend for [MSL][msl] (Metal Shading Language).
## Binding model
@@ -21,7 +22,9 @@ pretend that MSL doesn't have all the restrictions it has.
For the result type, if it's a structure, we re-compose it with a temporary value
holding the result.
!*/
[msl]: https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
*/
use crate::{arena::Handle, proc::index, valid::ModuleInfo};
use std::{
@@ -197,12 +200,13 @@ impl Default for Options {
}
}
// A subset of options that are meant to be changed per pipeline.
/// A subset of options that are meant to be changed per pipeline.
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub struct PipelineOptions {
/// Allow `BuiltIn::PointSize` in the vertex shader.
///
/// Metal doesn't like this for non-point primitive topologies.
pub allow_point_size: bool,
}

View File

@@ -1,4 +1,6 @@
//! Implementations for `BlockContext` methods.
/*!
Implementations for `BlockContext` methods.
*/
use super::{
index::BoundsCheckResult, make_local, selection::Selection, Block, BlockContext, Dimension,

View File

@@ -1,4 +1,6 @@
//! Generating SPIR-V for image operations.
/*!
Generating SPIR-V for image operations.
*/
use super::{
selection::{MergeTuple, Selection},

View File

@@ -1,4 +1,6 @@
//! Bounds-checking for SPIR-V output.
/*!
Bounds-checking for SPIR-V output.
*/
use super::{selection::Selection, Block, BlockContext, Error, IdGenerator, Instruction, Word};
use crate::{arena::Handle, proc::BoundsCheckPolicy};

View File

@@ -1,5 +1,8 @@
/*! Standard Portable Intermediate Representation (SPIR-V) backend
!*/
/*!
Backend for [SPIR-V][spv] (Standard Portable Intermediate Representation).
[spv]: https://www.khronos.org/registry/SPIR-V/
*/
mod block;
mod helpers;
@@ -627,17 +630,16 @@ impl Default for Options {
}
}
// A subset of options that are meant to be changed per pipeline.
// A subset of options meant to be changed per pipeline.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
pub struct PipelineOptions {
/// The stage of the entry point
/// The stage of the entry point.
pub shader_stage: crate::ShaderStage,
/// The name of the entry point
/// The name of the entry point.
///
/// If no entry point that matches is found a error will be thrown while creating a new instance
/// of [`Writer`](struct.Writer.html)
/// If no entry point that matches is found while creating a [`Writer`], a error will be thrown.
pub entry_point: String,
}

View File

@@ -1,4 +1,6 @@
//! Reusing collections' previous allocations.
/*!
Reusing collections' previous allocations.
*/
/// A value that can be reset to its initial state, retaining its current allocations.
///

View File

@@ -1,59 +1,61 @@
//! Generate SPIR-V conditional structures.
//!
//! Builders for `if` structures with `and`s.
//!
//! The types in this module track the information needed to emit SPIR-V code
//! for complex conditional structures, like those whose conditions involve
//! short-circuiting 'and' and 'or' structures. These track labels and can emit
//! `OpPhi` instructions to merge values produced along different paths.
//!
//! This currently only supports exactly the forms Naga uses, so it doesn't
//! support `or` or `else`, and only supports zero or one merged values.
//!
//! Naga needs to emit code roughly like this:
//!
//! ```ignore
//!
//! value = DEFAULT;
//! if COND1 && COND2 {
//! value = THEN_VALUE;
//! }
//! // use value
//!
//! ```
//!
//! Assuming `ctx` and `block` are a mutable references to a [`BlockContext`]
//! and the current [`Block`], and `merge_type` is the SPIR-V type for the
//! merged value `value`, we can build SPIR-V for the code above like so:
//!
//! ```ignore
//!
//! let cond = Selection::start(block, merge_type);
//! // ... compute `cond1` ...
//! cond.if_true(ctx, cond1, DEFAULT);
//! // ... compute `cond2` ...
//! cond.if_true(ctx, cond2, DEFAULT);
//! // ... compute THEN_VALUE
//! let merged_value = cond.finish(ctx, THEN_VALUE);
//!
//! ```
//!
//! After this, `merged_value` is either `DEFAULT` or `THEN_VALUE`, depending on
//! the path by which the merged block was reached.
//!
//! This takes care of writing all branch instructions, including an
//! `OpSelectionMerge` annotation in the header block; starting new blocks and
//! assigning them labels; and emitting the `OpPhi` that gathers together the
//! right sources for the merged values, for every path through the selection
//! construct.
//!
//! When there is no merged value to produce, you can pass `()` for `merge_type`
//! and the merge values. In this case no `OpPhi` instructions are produced, and
//! the `finish` method returns `()`.
//!
//! To enforce proper nesting, a `Selection` takes ownership of the `&mut Block`
//! pointer for the duration of its lifetime. To obtain the block for generating
//! code in the selection's body, call the `Selection::block` method.
/*!
Generate SPIR-V conditional structures.
Builders for `if` structures with `and`s.
The types in this module track the information needed to emit SPIR-V code
for complex conditional structures, like those whose conditions involve
short-circuiting 'and' and 'or' structures. These track labels and can emit
`OpPhi` instructions to merge values produced along different paths.
This currently only supports exactly the forms Naga uses, so it doesn't
support `or` or `else`, and only supports zero or one merged values.
Naga needs to emit code roughly like this:
```ignore
value = DEFAULT;
if COND1 && COND2 {
value = THEN_VALUE;
}
// use value
```
Assuming `ctx` and `block` are a mutable references to a [`BlockContext`]
and the current [`Block`], and `merge_type` is the SPIR-V type for the
merged value `value`, we can build SPIR-V for the code above like so:
```ignore
let cond = Selection::start(block, merge_type);
// ... compute `cond1` ...
cond.if_true(ctx, cond1, DEFAULT);
// ... compute `cond2` ...
cond.if_true(ctx, cond2, DEFAULT);
// ... compute THEN_VALUE
let merged_value = cond.finish(ctx, THEN_VALUE);
```
After this, `merged_value` is either `DEFAULT` or `THEN_VALUE`, depending on
the path by which the merged block was reached.
This takes care of writing all branch instructions, including an
`OpSelectionMerge` annotation in the header block; starting new blocks and
assigning them labels; and emitting the `OpPhi` that gathers together the
right sources for the merged values, for every path through the selection
construct.
When there is no merged value to produce, you can pass `()` for `merge_type`
and the merge values. In this case no `OpPhi` instructions are produced, and
the `finish` method returns `()`.
To enforce proper nesting, a `Selection` takes ownership of the `&mut Block`
pointer for the duration of its lifetime. To obtain the block for generating
code in the selection's body, call the `Selection::block` method.
*/
use super::{Block, BlockContext, Instruction};
use spirv::Word;

View File

@@ -1,3 +1,9 @@
/*!
Backend for [WGSL][wgsl] (WebGPU Shading Language).
[wgsl]: https://gpuweb.github.io/gpuweb/wgsl.html
*/
mod writer;
use thiserror::Error;

View File

@@ -23,8 +23,8 @@ pub struct GlobalLookup {
#[derive(Debug, Clone)]
pub struct ParameterInfo {
pub qualifier: ParameterQualifier,
/// Wether the parameter should be treated as a depth image instead of a
/// sampled image
/// Whether the parameter should be treated as a depth image instead of a
/// sampled image.
pub depth: bool,
}
@@ -62,10 +62,10 @@ pub struct Overload {
#[derive(Debug, Default)]
pub struct FunctionDeclaration {
pub overloads: Vec<Overload>,
/// Wether or not this function has the name of a builtin
/// Whether or not this function has the name of a builtin.
pub builtin: bool,
/// In case [`builtin`](Self::builtin) is true, this field indicates wether
/// this function already has double overloads added or not, otherwise is unused
/// If [`builtin`](Self::builtin) is true, this field indicates whether
/// this function already has double overloads added or not. Otherwise, it is unused.
pub double: bool,
}
@@ -176,7 +176,7 @@ pub enum StructLayout {
}
// TODO: Encode precision hints in the IR
/// A precision hint used in glsl declarations
/// 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.
@@ -229,7 +229,7 @@ impl ParameterQualifier {
}
}
/// The glsl profile used by a shader
/// The GLSL profile used by a shader.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Profile {
/// The `core` profile, default when no profile is specified.

View File

@@ -17,22 +17,22 @@ fn join_with_comma(list: &[ExpectedToken]) -> String {
string
}
/// One of the expected tokens returned in [`InvalidToken`](ErrorKind::InvalidToken)
/// One of the expected tokens returned in [`InvalidToken`](ErrorKind::InvalidToken).
#[derive(Debug, PartialEq)]
pub enum ExpectedToken {
/// A specific token was expected
/// A specific token was expected.
Token(TokenValue),
/// A type was expected
/// A type was expected.
TypeName,
/// An identifier was expected
/// An identifier was expected.
Identifier,
/// An integer literal was expected
/// An integer literal was expected.
IntLiteral,
/// A float literal was expected
/// A float literal was expected.
FloatLiteral,
/// A boolean literal was expected
/// A boolean literal was expected.
BoolLiteral,
/// The end of file was expected
/// The end of file was expected.
Eof,
}
impl From<TokenValue> for ExpectedToken {
@@ -54,7 +54,7 @@ impl std::fmt::Display for ExpectedToken {
}
}
/// Information about the cause of an error
/// Information about the cause of an error.
#[derive(Debug, Error)]
#[cfg_attr(test, derive(PartialEq))]
pub enum ErrorKind {
@@ -112,7 +112,7 @@ impl From<ConstantSolvingError> for ErrorKind {
}
}
/// Error returned during shader parsing
/// Error returned during shader parsing.
#[derive(Debug, Error)]
#[error("{kind}")]
#[cfg_attr(test, derive(PartialEq))]

View File

@@ -1,10 +1,16 @@
//! Front end for consuming the OpenGl Shading language (GLSL).
//!
//! To begin take a look at the documentation for the [`Parser`](Parser).
//!
//! # Supported versions
//! Currently only the versions 450 and 460 are supported and 440 is partially
//! supported, furthermore the vulkan flavor is assumed.
/*!
Frontend for [GLSL][glsl] (OpenGL Shading Language).
To begin, take a look at the documentation for the [`Parser`](Parser).
# Supported versions
## Vulkan
- 440 (partial)
- 450
- 460
[glsl]: https://www.khronos.org/registry/OpenGL/index_gl.php
*/
pub use ast::{Precision, Profile};
pub use error::{Error, ErrorKind, ExpectedToken};
@@ -31,7 +37,7 @@ mod variables;
type Result<T> = std::result::Result<T, Error>;
/// Per shader options passed to [`parse`](Parser::parse)
/// Per-shader options passed to [`parse`](Parser::parse).
///
/// The [`From`](From) trait is implemented for [`ShaderStage`](ShaderStage) to
/// provide a quick way to create a Options instance.
@@ -61,16 +67,16 @@ impl From<ShaderStage> for Options {
}
}
/// Additional information about the glsl shader
/// Additional information about the GLSL shader.
///
/// Stores additional information about the glsl shader which might not be
/// Stores additional information about the GLSL shader which might not be
/// stored in the shader [`Module`](Module).
#[derive(Debug)]
pub struct ShaderMetadata {
/// The glsl version specified in the shader trought the use of the
/// The GLSL version specified in the shader trought the use of the
/// `#version` preprocessor directive.
pub version: u16,
/// The glsl profile specified in the shader trought the use of the
/// The GLSL profile specified in the shader trought the use of the
/// `#version` preprocessor directive.
pub profile: Profile,
/// The shader stage in the pipeline, passed to the [`parse`](Parser::parse)
@@ -80,8 +86,8 @@ pub struct ShaderMetadata {
/// The workgroup size for compute shaders, defaults to `[1; 3]` for
/// compute shaders and `[0; 3]` for non compute shaders.
pub workgroup_size: [u32; 3],
/// Wether or not early fragment tests where requested by the shader,
/// defaults to `false`.
/// Whether or not early fragment tests where requested by the shader.
/// Defaults to `false`.
pub early_fragment_tests: bool,
/// The shader can request extensions via the
@@ -118,7 +124,7 @@ impl Default for ShaderMetadata {
}
}
/// The `Parser` is the central structure of the glsl frontend.
/// The `Parser` is the central structure of the GLSL frontend.
///
/// To instantiate a new `Parser` the [`Default`](Default) trait is used, so a
/// call to the associated function [`Parser::default`](Parser::default) will

View File

@@ -1,13 +1,16 @@
//! Module responsible for calculating the offset and span for types.
//!
//! There exists two types of layouts std140 and std430 (there's technically
//! two more layouts, shared and packed. Shared is not supported by spirv. Packed is
//! implementation dependent and for now it's just implemented as an alias to
//! std140).
//!
//! The OpenGl spec (the layout rules are defined by the OpenGl spec in section
//! 7.6.2.2 as opposed to the GLSL spec) uses the term basic machine units which are
//! equivalent to bytes.
/*!
Module responsible for calculating the offset and span for types.
There exists two types of layouts std140 and std430 (there's technically
two more layouts, shared and packed. Shared is not supported by spirv. Packed is
implementation dependent and for now it's just implemented as an alias to
std140).
The OpenGl spec (the layout rules are defined by the OpenGl spec in section
7.6.2.2 as opposed to the GLSL spec) uses the term basic machine units which are
equivalent to bytes.
*/
use super::{
ast::StructLayout,
error::{Error, ErrorKind},

View File

@@ -16,7 +16,7 @@ pub struct Token {
pub meta: Span,
}
/// A token passed from the lexing used in the parsing
/// A token passed from the lexing used in the parsing.
///
/// This type is exported since it's returned in the
/// [`InvalidToken`](super::ErrorKind::InvalidToken) error.

View File

@@ -31,15 +31,15 @@ pub struct VarDeclaration<'a> {
pub meta: Span,
}
/// Information about a builtin used in [`add_builtin`](Parser::add_builtin)
/// Information about a builtin used in [`add_builtin`](Parser::add_builtin).
struct BuiltInData {
/// The type of the builtin
/// The type of the builtin.
inner: TypeInner,
/// The builtin class associated with
/// The associated builtin class.
builtin: BuiltIn,
/// Wether it should be allowed to write to the builtin or not
/// Whether the builtin can be written to or not.
mutable: bool,
/// The storage used for the builtin
/// The storage used for the builtin.
storage: StorageQualifier,
}

View File

@@ -1,4 +1,6 @@
//! Interpolation defaults.
/*!
Interpolation defaults.
*/
impl crate::Binding {
/// Apply the usual default interpolation for `ty` to `binding`.

View File

@@ -1,4 +1,6 @@
//! Parsers which load shaders into memory.
/*!
Frontend parsers that consume binary and text shaders and load them into [`Module`](super::Module)s.
*/
mod interpolator;

View File

@@ -1,4 +1,5 @@
/*! SPIR-V frontend
/*!
Frontend for [SPIR-V][spv] (Standard Portable Intermediate Representation).
## ID lookups
@@ -23,7 +24,9 @@ Instead, we detect when such matrix is accessed in the `OpAccessChain`,
and we generate a parallel expression that loads the value, but transposed.
This value then gets used instead of `OpLoad` result later on.
!*/
[spv]: https://www.khronos.org/registry/SPIR-V/
*/
mod convert;
mod error;
mod function;

View File

@@ -1,6 +1,8 @@
//! Front end for consuming [WebGPU Shading Language][wgsl].
//!
//! [wgsl]: https://gpuweb.github.io/gpuweb/wgsl.html
/*!
Frontend for [WGSL][wgsl] (WebGPU Shading Language).
[wgsl]: https://gpuweb.github.io/gpuweb/wgsl.html
*/
mod conv;
mod lexer;

View File

@@ -1,2 +1,6 @@
/*!
Lists of reserved keywords for each shading language with a [frontend][crate::front] or [backend][crate::back].
*/
#[cfg(any(feature = "wgsl-in", feature = "wgsl-out"))]
pub mod wgsl;

View File

@@ -1,4 +1,11 @@
/*!
Reserved keywords for [WGSL][wgsl] (WebGPU Shading Language).
[wgsl]: https://gpuweb.github.io/gpuweb/wgsl.html
*/
// https://gpuweb.github.io/gpuweb/wgsl/#keyword-summary
/// Reserved keywords.
pub const RESERVED: &[&str] = &[
// type-defining keywords
"array",

View File

@@ -182,8 +182,7 @@ tree.
[`Validator::validate`]: valid::Validator::validate
[`ModuleInfo`]: valid::ModuleInfo
!*/
*/
// TODO: use `strip_prefix` instead when Rust 1.45 <= MSRV
#![allow(
@@ -235,18 +234,23 @@ pub type FastHashSet<K> = rustc_hash::FxHashSet<K>;
/// Map of expressions that have associated variable names
pub(crate) type NamedExpressions = FastHashMap<Handle<Expression>, String>;
/// Early fragment tests. In a standard situation if a driver determines that it is possible to
/// switch on early depth test it will. Typical situations when early depth test is switched off:
/// - Calling ```discard``` in a shader.
/// Early fragment tests.
///
/// In a standard situation, if a driver determines that it is possible to switch on early depth test, it will.
///
/// Typical situations when early depth test is switched off:
/// - Calling `discard` in a shader.
/// - Writing to the depth buffer, unless ConservativeDepth is enabled.
///
/// SPIR-V: ExecutionMode EarlyFragmentTests
/// In GLSL: layout(early_fragment_tests) in;
/// HLSL: Attribute earlydepthstencil
/// To use in a shader:
/// - GLSL: `layout(early_fragment_tests) in;`
/// - HLSL: `Attribute earlydepthstencil`
/// - SPIR-V: `ExecutionMode EarlyFragmentTests`
///
/// For more, see:
/// - <https://www.khronos.org/opengl/wiki/Early_Fragment_Test#Explicit_specification>
/// - <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/sm5-attributes-earlydepthstencil>
/// - <https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#Execution_Mode>
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
@@ -256,20 +260,22 @@ pub struct EarlyDepthTest {
}
/// Enables adjusting depth without disabling early Z.
///
/// SPIR-V: ExecutionMode DepthGreater/DepthLess/DepthUnchanged
/// GLSL: layout (depth_<greater/less/unchanged/any>) out float gl_FragDepth;
/// - ```depth_any``` option behaves as if the layout qualifier was not present.
/// HLSL: SV_Depth/SV_DepthGreaterEqual/SV_DepthLessEqual
/// To use in a shader:
/// - GLSL: `layout (depth_<greater/less/unchanged/any>) out float gl_FragDepth;`
/// - `depth_any` option behaves as if the layout qualifier was not present.
/// - HLSL: `SV_DepthGreaterEqual`/`SV_DepthLessEqual`/`SV_Depth`
/// - SPIR-V: `ExecutionMode Depth<Greater/Less/Unchanged>`
///
/// For more, see:
/// - <https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_conservative_depth.txt>
/// - <https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics#system-value-semantics>
/// - <https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#Execution_Mode>
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
pub enum ConservativeDepth {
/// Shader may rewrite depth only with a value greater than calculated;
/// Shader may rewrite depth only with a value greater than calculated.
GreaterEqual,
/// Shader may rewrite depth smaller than one that would have been written without the modification.
@@ -474,7 +480,7 @@ bitflags::bitflags! {
}
}
// Storage image format.
/// Image storage format.
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
@@ -1333,7 +1339,7 @@ pub enum Expression {
pub use block::Block;
/// The value of the switch case
/// The value of the switch case.
// Clone is used only for error reporting and is not intended for end users
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
@@ -1521,6 +1527,7 @@ pub struct FunctionArgument {
pub binding: Option<Binding>,
}
/// A function result.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]

View File

@@ -1,4 +1,6 @@
//! Definitions for index bounds checking.
/*!
Definitions for index bounds checking.
*/
use crate::{valid, Handle, UniqueArena};
use bit_set::BitSet;

View File

@@ -1,4 +1,6 @@
//! Module processing functionality.
/*!
[`Module`](super::Module) processing functionality.
*/
pub mod index;
mod layouter;

View File

@@ -55,7 +55,7 @@ impl Span {
}
}
/// Check wether `self` was defined or is a default/unknown span
/// Check whether `self` was defined or is a default/unknown span
pub fn is_defined(&self) -> bool {
*self != Self::default()
}

View File

@@ -1,3 +1,7 @@
/*!
Shader validator.
*/
mod analyzer;
mod compose;
mod expression;

View File

@@ -1,4 +1,6 @@
//! Test SPIR-V backend capability checks.
/*!
Test SPIR-V backend capability checks.
*/
#![cfg(all(feature = "wgsl-in", feature = "spv-out"))]

View File

@@ -1,4 +1,6 @@
//! Tests for the WGSL front end.
/*!
Tests for the WGSL front end.
*/
#![cfg(feature = "wgsl-in")]
fn check(input: &str, snapshot: &str) {