Directory portal: juejin.cn/post/701059…
www.w3.org/TR/webgpu/#…
GPUPipelineBase Exercises ├ GPURenderPipeline ├Copy the code
pipeline
Pipeline represents a certain calculation process. In WebGPU, there are two kinds of rendering pipeline and calculation pipeline.
This process requires objects or resources such as binding groups, VBos, shaders, etc., and then eventually outputs something like a rendering pipeline that outputs a color value (in the form of a color attachment), and a computed pipeline that outputs it to its designated location, which I won’t go into too much detail here.
Structurally, a pipeline consists of a series of programmable phases and a number of fixed states.
Note that depending on the operating system and the graphics driver, some fixed states are compiled into the shader code, so it is a good idea to combine them into a pipeline object.
Both pipeline objects can be created from device objects.
In the corresponding channel encoder, the pipeline can be switched for different calculation procedures.
1 Basic pipeline
dictionary GPUPipelineDescriptorBase : GPUObjectDescriptorBase {
GPUPipelineLayout layout;
};
interface mixin GPUPipelineBase {
GPUBindGroupLayout getBindGroupLayout(unsigned long index);
};
Copy the code
Two lines were need parameter object, at the time of creating parameter objects have their own different kinds of concrete, but are inherited from the GPUPipelineDescriptorBase type here.
Both pipelines also inherit from the base pipeline type GPUPipelineBase.
1.1 getBindGroupLayout method of base pipeline
Each pipeline object has this method, which takes a number of type unsigned long as an argument and returns a binding group layout object at the corresponding position in the pipeline layout object.
Note: If no layout object is passed when the pipeline is created, this method automatically constructs the binding group layout object based on the group feature in the shader code.
It is important to note that this numeric parameter is smaller than the maxBindGroups value in the device restriction list.
1.2 Default pipeline layout
If a pipeline layout object is not set when it is created, a default layout object is automatically created internally. This process is not fully explained in the documentation, but is described as a “reflection” technique, which is then constructed step by step.
For details about how to create a default pipeline layout, see WebGPU Spec 10.1.1 in the documentation.
The default pipeline layout object whose bindGroupLayouts array is an empty array.
1.3 Programmable stage: GPUProgrammableStage
The parameter object is used when creating the pipeline object. The parameter object has different programmable stages that can be set. Each stage is a GPUProgrammableStage object. This is detailed in the pipeline creation section below.
An object of type GPUProgrammableStage organizes what GPUShaderModule is used for a specific stage in the pipeline, what WGSL entry point function name is used, and what constant values should be passed.
We’ll talk about it in detail.
dictionary GPUProgrammableStage {
required GPUShaderModule module;
required USVString entryPoint;
record<USVString, GPUPipelineConstantValue> constants;
};
typedef double GPUPipelineConstantValue;
Copy the code
For each such object, there are two mandatory arguments:
-
Module, variable of type GPUShaderModule, shader module, see shader module section
-
EntryPoint, a string that specifies an entry function in the Module shader code
There is also an optional parameter Constants, which is a JavaScript object of type GPUPipelineConstantValue that is used to pass a constant value of the Override property in the shader code.
The key of this object can be the I in the parentheses of the OVERRIDE (I) feature in WGSL, or it can be a constant name. For example (take the vertex phase) :
const pipeline = device.createRenderPipeline({
vertex: {
/ *... * /
constants: {
1300: 2.0.// Will be passed to the 1300th gain constant in the shader code
depth: -1.// The depth constant will be passed to the shader code}}})Copy the code
Corresponding shader code:
[[override(1300)]] let gain: f32; [[override]] let depth: f32; [[override(0)]] let has_point_light: bool = true; [[Override (1200)]] Let specular_param: f32 = 2.3; [[override]] let width: f32 = 0.0; // Other codeCopy the code
If you want to override any of the WGSL constants with default values, you can pass an object like this:
const pipeline = device.createRenderPipeline({
vertex: {
/ *... * /
constants: {
1300: 2.0.// Will be passed to the 1300th gain constant in the shader code
depth: -1.// The depth constant will be passed to the shader code
0: false.1200: 3.0.width: 20,}}})Copy the code
When a JavaScript numeric type is converted to WGSL, it is automatically converted based on the specific type (bool, i32, u32, f32) of the constant in WGSL.
1.4 Supplementary information: pipeline and coloring stage
The WebGPU provides instructions to the GPU by issuing drawing commands or scheduling commands.
The behavior of the computation that the pipeline performs on the GPU is described as a series of stages, some of which are programmable. In WebGPU, a pipeline needs to be created before drawing or scheduling, which is called rendering pipeline and calculation pipeline.
1.5 How do I verify the compliance of programmable phase objects
When creating a pipeline, there are requirements for a stage object (called stage) and a pipeline layout object (called Layout) :
- Stage. module must be a valid one
GPUShaderModule
object - Stage. module shader code must have an entry function with the same name as stage.entryPoint
- Verify the binding for each bound variable used in the entry function
- For each sampled texture used in the entry function, set the texture to texture, the sampler to sampler, and sampler. Type if it is “filtering”, then texture. SampleType cannot be “unfilterable-float”.
- For all constants in stage.constants, there must be a corresponding Override constant in the shader; If constants in the shader are not given default values using initialization syntax, then values must be given in stage.Constants.
1.6 How can I verify the compliance of bound variables in a shader
As with the caption intent, this section guides the syntax writing and organization of bound variables in the shader.
Call the shader variable bindGroupId and bindId and call the pipelineLayout object pipelineLayout. Binding group layout can be made of pipelineLayout. BindGroupLayouts [bindGroupId] getting and for bindGroupLayout:
-
BindGroupLayout must have an entry object with the same binding value as bindId;
-
Iterate through entries in bindGroupLayout and set the traversed GPUBindGroupLayoutEntry variable to Entry:
-
If the type is buffer, and entry.buffer.type is
- “Uniform”, then the shader code uses this variable
var<uniform>
The statement - “Storage”, then the shader code uses this variable
var<storage, read_write>
The statement - “Read-only -storage”, then the shader code uses this variable
var<storage, read>
The statement
- “Uniform”, then the shader code uses this variable
-
If is a buffer type and entry. Buffer. MinBindingSize is not zero:
- If shader code in a structure of a final field is unbounded array, then the entry. The buffer. The minBindingSize must be greater than or equal to the array of offsets and with pace
- If shader code is not a structure the last field in unbounded array, then the entry. The buffer. The minBindingSize must be greater than or equal to the size of the structure
-
If it is of sampler type and entry.sampler. Type is
- “Filtering”, so variable is used
sampler
type - “Comparison”, then variable is used
comparison_sampler
type
- “Filtering”, so variable is used
-
If it is texture type, if and only if entry. Texture. Multisampled is true, The variable must be texture_multiSAMpled_2d
or texture_depth_multiSAMpled_2d
.
-
If it is the texture type, when entry.texture. Type is
- “Float”, “unfilterable-float”, “sint”, “uint” when variable is used
texture_1d<T>
.texture_2d<T>
.texture_2d_array<T>
.texture_cube<T>
.texture_cube_array<T>
.texture_3d<T>
Or,texture_multisampled_2d<T>
Type to declare; SampleType is f32 when “float”, “unfilterable-float”, T is i32 when “sint”, T is u32 when “uint”; - “Depth”, variable to use
texture_depth_2d
.texture_depth_2d_array
.texture_depth_cube
.texture_depth_cube_array
或texture_depth_multisampled_2d
Type to declare
- “Float”, “unfilterable-float”, “sint”, “uint” when variable is used
-
If the texture type, when entry. Texture. ViewDimension is
- “1d”, variable is used
texture_1d<T>
The statement; - “2d”, variable is used
texture_2d<T>
或texture_multisampled_2d<T>
The statement; - “2D-array”, variable is used
texture_2d_array<T>
The statement; - “Cube”, variable is used
texture_cube<T>
The statement; - “Cube-array”, variable is used
texture_cube_array<T>
The statement; - “3D”, variable is used
texture_3d<T>
The statement;
- “1d”, variable is used
-
If it is storageTexture type, when entry. StorageTexture. ViewDimension is
-
“1d”, the variable is declared using texture_storage_1D
,>
;
-
“2d”, variable is declared using texture_storage_2d
,>
;
-
“2D-array”, variable is declared using texture_storage_2d_array
,>
;
-
“3d”, variable is declared using texture_storage_3D
,>
;
Entry. StorageTexture. Access is A “write – only”, the generic in A write is used, the generic type T to entry. StorageTexture. The format.
-
-
2 Rendering pipeline
The GPURenderPipeline is a pipeline that controls the vertex coloring and chip coloring phases.
It can be used by the render channel encoder GPURenderPassEncoder and the render package encoder GPURenderBundleEncoder.
The inputs to the render pipeline are:
- through
GPUPipelineLayout
The resource bound to the binding group provided by - Vertex and index data, used by the following vertex shader phase
- Color attachment, described by color target state
- An optional depth template attachment, described by the depth template state
The output of the render pipeline is:
- The type of the binding group is
"storage"
GPUBuffer resources - Binding in the group
access
Properties for"write-only"
GPUStorageTexture resources - Color in attachment
- Optional depth template attachment
The rendering pipeline has the following rendering stages:
- Vertex Fetch is obtained from Vertex Fetch
GPUVertexState
Object buffers property to describe and control - Vertex Shader, by Vertex Shader
GPUVertexState
Object description and control - Primitive Assembly, by
GPUPrimitiveState
Object description and control - Rasterization, by
GPUPrimitiveState
,GPUDepthStencilState
和GPUMultisampleState
Object to describe and control - Fragment Shader, by
GPUFragmentState
Object to control - Template test and operation (StencilTest) and DepthTest and write (DepthTest), followed by
GPUDepthStencilState
Object description and control - Fusion output, by
GPUFragmentState
Targets property of the object to describe and control
The above types of GPUVertexState, GPUPrimitiveState, GPUFragmentState, GPUDepthStencilState, and GPUMultisampleState are listed below Vertex coloring stage, pixel assembly stage, slice coloring stage, deep template testing stage and multiple sampling stage are introduced in several sections. Corresponds to the rendering pipeline to create next Section GPURenderPipelineDescriptor object of vertex, primitive, fragments, depthStencil, fragments field.
Of these five phases, only vertex coloring phase and chip coloring phase are programmable.
The WebIDL definition for the render pipeline is as follows:
[Exposed=(Window, DedicatedWorker), SecureContext]
interface GPURenderPipeline {
};
GPURenderPipeline includes GPUObjectBase;
GPURenderPipeline includes GPUPipelineBase;
Copy the code
2.1 Pipeline creation
The render pipeline is created through the device object’s createRenderPipeline method.
Create the rendering pipeline needs a GPURenderPipelineDescriptor type of object as a parameter.
dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase {
required GPUVertexState vertex;
GPUPrimitiveState primitive = {};
GPUDepthStencilState depthStencil;
GPUMultisampleState multisample = {};
GPUFragmentState fragment;
};
Copy the code
In this object, there are several phase states, and the purpose of each field is briefly described here, with their corresponding classes described in more detail in the following sections.
vertex
Fields,GPUVertexState
In addition to the attributes of the programmable stage object, it also describes the entry point function of the vertex shader, and the layout of the vertex data input into the pipeline.primitive
Fields,GPUPrimitiveState
Type of JavaScript object that describes information about primitive assembly. By default, the object is empty.depthStencil
Fields,GPUDepthStencilState
Type JavaScript object, which is an optional object that describes deep template test information;multisample
Fields,GPUMultisampleState
A JavaScript object of type, which by default is an empty object, describing the multisample information of the pipeline;fragment
Fields,GPUFragmentState
In addition to the properties of the programmable phase object, it also describes the entry point function of the slice shader and how to output the slice color. If it is null, then the render pipeline will not output color, only in colorless output mode, which is normally used only for depth template testing.
2.1.1 Creating a Pipeline asynchronously
Besides synchronized createRenderPipeline method device object to create, can also through the device object createRenderPipelineAsync object to asynchronous created, it returns the resolve value object rendering pipeline is a Promise, You can call in an asynchronous function await to get it resolve value, asynchronous create functions also use GPURenderPipelineDescriptor parameter object.
2.1.2 how to validate GPURenderPipelineDescriptor compliance
Meet all the following conditions:
- Verify that the programmable properties of the vertex shader stage object are not problematic
- GPUVertexState = GPUVertexState = GPUVertexState
- Fragment if descriptor. Fragment exists (not null) :
- Verify that the programmable properties of the chip coloring phase object are not problematic
- Verify that the chip coloring phase object itself has a problem
- If the fragment shader used in “sample_mask” built-in variables, then descriptor. The multisample. AlphaToCoverageEnable to set to false
- Verify that there is a problem with the primitive assembly stage object
- If Descriptor. DepthStencil is not null, then verify that the depth template test phase object has a problem
- Verify that there is no problem with the multiple sampling stage object
- For user-defined exits in vertex shaders, the slice shader must have corresponding entrances, as discussed in WGSL
- For the slice shader and the custom components in the slice shader, the total number of components passed between the two shaders by location is smaller than the number in the device restriction list
maxInterStageShaderComponents
Value.
2.2 Pixel assembly stage
GPURenderPipelineDescriptor Object in the primitive field values, is a JavaScript Object.
enum GPUPrimitiveTopology {
"point-list",
"line-list",
"line-strip",
"triangle-list",
"triangle-strip"
};
enum GPUFrontFace {
"ccw",
"cw"
};
enum GPUCullMode {
"none",
"front",
"back"
};
dictionary GPUPrimitiveState {
GPUPrimitiveTopology topology = "triangle-list";
GPUIndexFormat stripIndexFormat;
GPUFrontFace frontFace = "ccw";
GPUCullMode cullMode = "none";
boolean clampDepth = false;
};
Copy the code
The primitive assembly stage object is of type GPUPrimitiveState, and all parameters are optional, as is itself optional.
- parameter
topology
.GPUPrimitiveTopology
String enumeration type of value indicating how vertices are assembled, default is triangle list"triangle-list"
And the triangle belt"triangle-strip"
, the line list"line-list"
, the line with"line-strip"
And simply draw points"piont-list"
Is similar to the mode parameter of drawArray in WebGL; - parameter
stripIndexFormat
If it is an index triangle, specify the numeric type of the index value, which is a string enumeration typeGPUIndexFormat
, see the definition of WebIDL in the vertex coloring stage; - parameter
frontFace
, optional. The default value is"ccw"
, is a string enumeration typeGPUFrontFace
, refers to the rotation direction of the triangle formed by points, CCW is counterclockwise, cw is clockwise. - parameter
cullMode
, optional. The default value is"none"
, is a string enumeration typeGPUCullMode
“, refers to the culling mode. In addition to None, there are both forward and back culling. - parameter
clampDepth
This parameter is optional. The default value is false. If enabled, the depth value will be truncated. Need to be enabled when requesting device objectsclamp-depth
Function.
2.2.1 Vertex IndexFormat GPUIndexFormat
enum GPUIndexFormat {
"uint16",
"uint32"
};
Copy the code
The vertex index format, GPUIndexFormat, determines the data type of index values in the VBO and the starting value of primiples when the primiples are “line-strip” and “triangle-strip”.
The Primitive Restart Value indicates where to Restart a Primitive rather than continue to construct a triangle using previously indexed vertices.
[GPUPrimitiveState](#2.2 Primitive assembly phase), if its “Topology” field specifies “line-strip” or “triangle-strip”, Its “stripIndexFormat” field needs to be set accordingly so that the pipeline can be created using primitives to recalculate the value.
If “triangle-list”, “line-list”, and “point-list” are used, then “stripIndexFormat” should be set to undefined, The index is set using the setIndexBuffer method of the GPURenderPassEncoder.
.
GPUIndexFormat is used in the Vertex shader phase (Vertex State).
Uint16 represents the reset value of 2byte (0xFFFF), that is, 2byte takes an index number; Uint32 Indicates that the reset value is 4 bytes (0xFFFFFFFF), that is, an index number is taken from 4 bytes.
2.2.2 How to verify the compliance of objects in the pixel assembly stage
If all of the following conditions are met, then the primitive assembly stage object is fine:
- The topology field for the primitive assembly phase object is “line-strip” or “triangle-strip”, so stripIndexFormat cannot be undefined; The topology is something else, stripIndexFormat has to be undefined;
- ClampDepth of objects in the assembly stage is true, so the device’s function list should include “depth-clamp” function
2.2.3 Code Examples
const renderPipeline = device.createRenderPipeline({
/ *... * /
primitive: {
topology: "triangle-list",}})Copy the code
2.3 Vertex coloring stage
Vertex shader stage Object, is that the value of the vertex in GPURenderPipelineDescriptor Object, is a JavaScript Object, To satisfy the GPUVertexState type (including its parent type GPUProgrammableStage) :
dictionary GPUVertexState: GPUProgrammableStage { sequence<GPUVertexBufferLayout? > buffers = []; }; dictionary GPUVertexBufferLayout { required GPUSize64 arrayStride; GPUVertexStepMode stepMode = "vertex"; required sequence<GPUVertexAttribute> attributes; }; enum GPUVertexStepMode { "vertex", "instance" };Copy the code
The GPUVertexState object requires a Buffers field, which is an array of the GPUVertexBufferLayout object.
The GPUVertexBufferLayout object takes two mandatory arguments:
arrayStride
, unsigned longlong type, indicating the step size of all data (coordinates, colors, normals, texture coordinates, etc.) contained in a vertex;attributes
, an array of elements of typeGPUVertexAttribute
Object describing the number of vertices in this piece of dataVertex attribute;
There is also an optional argument, GPUVertexStepMode character enumeration type of the field stepMode, the default value is “vertex”; It represents how to access vertex data and has two values:
- “Vertex”, meaning that no matter how many times the render channel encoder issues a draw (whatever the instanceCount parameter of the draw method is), the vertex data will be read from the beginning of the VertexBuffer, but will continue reading from the end of the first read;
- “Instance”, which means that even if the render channel encoder draws multiple times (the instanceCount parameter of the draw method is greater than 1), after the first draw (after the vertex shader has run once), the vertex data will still be fetched from the same starting point of the VertexBuffer;
2.3.1 VertexBuffer and GPUVertexAttribute
Conceptually, the vertex cache is a descriptive view of the vertex data in video memory. Specifically, it is an array. The distance between the preceding array element and the following array element is called the ArrayStride (byte), or the length of the element.
Each element, called a vertex data, consists of several vertex attributes. The location of each vertex property in the vertex shader is unique.
dictionary GPUVertexAttribute {
required GPUVertexFormat format;
required GPUSize64 offset;
required GPUIndex32 shaderLocation;
};
Copy the code
In the Attributes array of the GPUVertexBufferLayout object, each element is the GPUVertexAttribute object.
Each GPUVertexAttribute object takes three mandatory parameters:
format
.GPUVertexFormat
The character enumeration type, see below [vertex format](# vertex format GPUVertexFormat), determines the numeric type and element composition of certain vertex attributes;offset
, type unsigned longlong, specifying its offset in bytes for each vertex.shaderLocation
Unsigned long, which specifies its location in the WGSL vertex shader.
2.3.2 VertexFormat GPUVertexFormat
enum GPUVertexFormat {
"uint8x2",
"uint8x4",
"sint8x2",
"sint8x4",
"unorm8x2",
"unorm8x4",
"snorm8x2",
"snorm8x4",
"uint16x2",
"uint16x4",
"sint16x2",
"sint16x4",
"unorm16x2",
"unorm16x4",
"snorm16x2",
"snorm16x4",
"float16x2",
"float16x4",
"float32",
"float32x2",
"float32x3",
"float32x4",
"uint32",
"uint32x2",
"uint32x3",
"uint32x4",
"sint32",
"sint32x2",
"sint32x3",
"sint32x4",
};
Copy the code
GPUVertexFormat enumeration of vertexFormat in WebIDL contains two parts of information according to the component type of the vertex (two, three, four dimensions) and the number type of each dimension. Some of these are abbreviated:
unorm
= unsigned normalized u (unsigned) + normalized norm (normalized)snorm
= normalized s (signed) + normalized norm (normalized)uint
= unsigned integersint
= signed integerfloat
= floating point number
Using the common “float32x3” (note that the x is a lowercase x) example, the value type for a Vertex property is three float32 numbers (not necessarily coordinates, but other Vertex attributes).
2.3.3 Code Examples
const renderPipeline = device.createRenderPipeline({
/ *... * /
vertex: {
module: device.createShaderModule({
code: ` /* wgsl vertex shader code */ `,}).entryPoint: 'vertex_main'.buffers: [{arrayStride: 4 * 5.// One vertex takes 20 bytes
attributes: [{// for Position VertexAttribute
shaderLocation: 0.offset: 0.format: "float32x3" // The coordinate attributes of the vertices account for 12 bytes, with three FLOAT32 digits
},
{
// for UV0 VertexAttribute
shaderLocation: 1.offset: 3 * 4.format: "float32x2" // The vertex texture coordinates take up 8 bytes, with two Float32 digits}]}]}})Copy the code
Example above:
- Use of
GPUVertexFormat
“Float32x3”, “float32X2”; - A vertex data block (block) is 20 bytes long. That is, it takes a “stride” of 20 bytes to get from the head of one vertex data to the head of the next vertex data.
- For a block of vertex data arranged in this VertexBuffer, there are two
GPUVertexAttribute
, one is the coordinate, followed by the second is the 2d texture coordinate, so the texture coordinate data should start at the 12th byte of the vertex data block (0 to 11 bytes are the coordinate’s three float32 digits).
2.3.4 How do I verify the compliance of GPUVertexBufferLayout
Call a GPUVertexBufferLayout object a Layout if it meets the following criteria:
- Layout. arrayStride ≤ in the device restriction list
maxVertexBufferArrayStride
And is a multiple of 4 - For each element in layout.attributes, make it attrib:
- If layout.arrayStride is 0, attrib.offset + sizeof(attrib.format) ≤ in the device restriction list
maxVertexBufferArrayStride
- Otherwise, attrib.offset + sizeof(attrib.format) ≤ layout.arrayStride
- Attrib. offset must be at least a multiple of min(4, sizeof(attrib.format))
- Attrib. ShaderLocation < in the device restriction list
maxVertexAttributes
- If layout.arrayStride is 0, attrib.offset + sizeof(attrib.format) ≤ in the device restriction list
- For each vertex attribute of the entry function in the vertex shader code, each GPUVertexAttribute element object in layout.attributes must satisfy:
- Vertex property variable type in shader code, compared to attrib.format:
- When attrib.format is one of “unorm”, “snorm”, or “float”, the variable type in shader code is
vecN<f32>
或f32
- When attrib.format is one of the “uint” types, the variable type in shader code is
vecN<u32>
或u32
- When attrib.format is one of the “sint” types, the variable type in shader code is
vecN<i32>
或i32
- When attrib.format is one of “unorm”, “snorm”, or “float”, the variable type in shader code is
- The location property value of the vertex property in the shader should be equal to attrib. ShaderLocation
- Vertex property variable type in shader code, compared to attrib.format:
2.3.5 How do I verify the compliance of GPUVertexState, a vertex shader object
Let a GPUVertexState object be state if it meets the following criteria:
- State.buffers. Length ≤ in the device limit list
maxVertexBuffers
- Every element in state.buffers should be validated by the vertex cache layout object.
- The sum of attributes for all elements of the state.buffers array ≤ in the device limit list
maxVertexAttributes
- All GPUVertexAttribute vertex attribute objects must have unique shaderLocation
2.4 Chip coloring stage
Fragment shader stage Object, is that the value of the fragments in GPURenderPipelineDescriptor Object, is a JavaScript Object, To satisfy the GPUFragmentState type (including its parent type GPUProgrammableStage) :
dictionary GPUFragmentState: GPUProgrammableStage {
required sequence<GPUColorTargetState> targets;
};
Copy the code
- parameter
targets
Is an element ofGPUColorTargetState
An array of objects of type, is a mandatory parameter, see [2.6 Color Output stage](#2.6 color Output stage)
How to verify the compliance of the object in the chip coloring phase
Let the GPUFragmentState object at the fragment coloring stage be state, which meets the following requirements:
- State. The targets. Length 8 or less
- Targets for each element, called colorState:
- ColorState. The format must beWebGPU Spec 24.1.1 Plain Color FormatsThe bidding for
RENDER_ATTACHMENT
A kind of - Colorstate. blend = undefined:
- Colorstate. format is selected in WebGPU Spec 24.1.1 Plain color formats
- Colorstate.blend. color, colorState.blend.alpha must be valid
- ColorState writeMask 16 or less
- The chip shader entry function has an output location matching state.targets. The type of the pipeline output object must correspond to colorstate. format, otherwise colorState.writeMask must be 0
- ColorState. The format must beWebGPU Spec 24.1.1 Plain Color FormatsThe bidding for
Colorstate.blend. color, colorstate.blend. alpha Call it component. If component.operation is “min” or “Max”, then component.srcFactor and component.dstFactor must both be “one”.
For example,
const renderPipeline = device.createRenderPipeline({
/ *... * /
fragment: {
module: device.createShaderModule({
code: `/* wgsl fragment shader source code */`,}).entryPoint: "fragment_main".targets: [{
format: "bgra8unorm"}]}})Copy the code
2.5 Deep Template Testing Phase
Depth template testing phase Object is GPURenderPipelineDescriptor depthStencil field values in the Object, is a JavaScript Object, to meet GPUDepthStencilState type:
dictionary GPUDepthStencilState {
required GPUTextureFormat format;
boolean depthWriteEnabled = false;
GPUCompareFunction depthCompare = "always";
GPUStencilFaceState stencilFront = {};
GPUStencilFaceState stencilBack = {};
GPUStencilValue stencilReadMask = 0xFFFFFFFF;
GPUStencilValue stencilWriteMask = 0xFFFFFFFF;
GPUDepthBias depthBias = 0;
float depthBiasSlopeScale = 0;
float depthBiasClamp = 0;
};
dictionary GPUStencilFaceState {
GPUCompareFunction compare = "always";
GPUStencilOperation failOp = "keep";
GPUStencilOperation depthFailOp = "keep";
GPUStencilOperation passOp = "keep";
};
enum GPUStencilOperation {
"keep",
"zero",
"replace",
"invert",
"increment-clamp",
"decrement-clamp",
"increment-wrap",
"decrement-wrap"
};
Copy the code
Since there is no text introduction for this part of the official, it will be specially added when there are examples to study later.
How do I verify the compliance of objects in the deep template test phase
For the GPUDepthStencilState object in the deep template test phase, set it to state, as long as:
- Format is one of the WebGPU Spec 24.1.2 Depth/ Stencil formats;
- If state. DepthWriteEnabled is true, or if state. DepthCompare is not “always”, then state
- If state.stencilFront or state.stencilBack is not the default, then state.format must be in template format
2.6 Color output stage
Object color output stage, GPUColorTargeState type, is GPURenderPipelineDescriptor object fragments the targets in the field the type of the array element in the field.
dictionary GPUColorTargetState {
required GPUTextureFormat format;
GPUBlendState blend;
GPUColorWriteFlags writeMask = 0xF; // GPUColorWrite.ALL
};
Copy the code
Subtypes:
dictionary GPUBlendState {
required GPUBlendComponent color;
required GPUBlendComponent alpha;
};
typedef [EnforceRange] unsigned long GPUColorWriteFlags;
[Exposed=(Window, DedicatedWorker)]
namespace GPUColorWrite {
const GPUFlagsConstant RED = 0x1;
const GPUFlagsConstant GREEN = 0x2;
const GPUFlagsConstant BLUE = 0x4;
const GPUFlagsConstant ALPHA = 0x8;
const GPUFlagsConstant ALL = 0xF;
};
Copy the code
Mixed mode
dictionary GPUBlendComponent {
GPUBlendOperation operation = "add";
GPUBlendFactor srcFactor = "one";
GPUBlendFactor dstFactor = "zero";
};
enum GPUBlendFactor {
"zero",
"one",
"src",
"one-minus-src",
"src-alpha",
"one-minus-src-alpha",
"dst",
"one-minus-dst",
"dst-alpha",
"one-minus-dst-alpha",
"src-alpha-saturated",
"constant",
"one-minus-constant"
};
enum GPUBlendOperation {
"add",
"subtract",
"reverse-subtract",
"min",
"max"
};
Copy the code
Since there is no text introduction for this part of the official, it will be specially added when there are examples to study later.
2.7 Multiple sampling stage
Object color output stage, GPUMultisampleState type, is that the value of the multisample GPURenderPipelineDescriptor object.
dictionary GPUMultisampleState {
GPUSize32 count = 1;
GPUSampleMask mask = 0xFFFFFFFF;
boolean alphaToCoverageEnabled = false;
};
Copy the code
- parameter
count
, sampling times, can only be 1 or 4, the default is 1; - parameter
mask
, sample mask value, type is unsigned long, default value is0xFFFFFFFF
; - parameter
alphaToCoverageEnabled
The default value is false.
The latter two values are described in the WebGPU Spec 21.3.10 sampling mask. A slice with a sampling mask value of 0 will not output color. It consists of three mask variables and. One shader-output-mask is determined by the built-in variable sample_mask in the chip shader, which is formed by the alphaToCoverageEnabled and mask values at this point. Here is a brief description.
How do I verify compliance of multiple sampling phase objects
AlphaToCoverageEnabled If true, count must be greater than 1.
The code for
const renderPipeline = device.createRenderPipeline({
/ *... * /
multisample: {
count: 4}})Copy the code
2.8 Comprehensive code examples
const renderPipeline = device.createRenderPipeline({
layout: [/* GPURenderPipelineLayout[] */].vertex: { /* {}: GPUVertexState */ },
fragment: { /* {}: GPUVertexState */ },
primitive: { /* {}: GPUPrimitiveState */ },
multisample: { /* {}: GPUMultisampleState */}})Copy the code
3 Pipeline Calculation
Calculation pipeline, GPUComputePipeline type, is a pipeline that can be used in the calculation channel encoder GPUComputePassEncoder to complete a general calculation process.
The input and output of the compute pipeline are bound in a binding group and provided via GPUPipelineLayout (see the Resource Binding section).
It does not have specific output results like the render pipeline. Its results will be written to two resources in the binding group, buffer with type “storage” and storageTexture with type “write-only”.
There is only one stage for calculating the pipeline: calculating the shader.
Here is the interface definition for calculating pipelines:
[Exposed=(Window, DedicatedWorker), SecureContext]
interface GPUComputePipeline {
};
GPUComputePipeline includes GPUObjectBase;
GPUComputePipeline includes GPUPipelineBase;
Copy the code
Calculate the pipeline creation
The device object createComputePipeline can create a computational pipeline, it needs a GPUComputePipelineDescriptor types of JavaScript object as parameters.
dictionary GPUComputePipelineDescriptor : GPUPipelineDescriptorBase {
required GPUProgrammableStage compute;
};
Copy the code
GPUComputePipelineDescriptor type inherits from GPUPipelineDescriptorBase type, means also to follow the parent type field rules.
Can also create calculation through the device object createComputePipelineAsync method of asynchronous pipeline, grammar and asynchronous create rendering pipeline, parameter and synchronization to create calculation pipeline.
How to validate GPUComputePipelineDescriptor parameter object compliance
Make GPUComputePipelineDescriptor object called descriptor.
- Descriptor. Layout and device object must be valid
- Verify that the programmable properties of the computed coloring phase object are not problematic
- The size of the workgroup used to compute the shader in Descriptor.com pute should not be greater than that in the device object restricted list
maxComputeWorkgroupStorageSize
Value, which is used by each workgroup not greater than the device object restriction listmaxComputeInvocationsPerWorkgroup
Value; - Descriptor.com pute to compute the shader
workgroup_size
None of the three component values of a feature must be greater than those in the device object restriction listmaxComputeWorkgroupSizeX
,maxComputeWorkgroupSizeY
,maxComputeWorkgroupSizeZ
The value of the;
If all of the above passes, a correct calculation pipeline object is returned.
The code for
const computePipeline = device.createComputePipeline({
compute: {
module: device.createShaderModule({
code: `/* wgsl compute shader source code */`
}),
entryPoint: "main",}})Copy the code
4.
This part is quite long, and I haven’t practiced some of it yet, so it’s quite difficult to study and translate.
But when you boil it down to the backbone, there are only four things:
- What are pipelines, what are the inputs and outputs, how are they created, what types of pipelines are there
- The pipeline is made up of phases, three of which (vertex coloring, slice coloring, and general computation) are programmable phases
- The wiring rules between the binding group layout, vertex cache layout and the pit bits of the shader code that accompany the pipeline
- Very important concepts in the vertex shader phase: VertexBuffer and vertex properties
A pipeline is the smallest unit in a WebGPU that performs a complete computation (or rendering, or general-purpose computation), with its own inputs and outputs.
You can pass different Vertexbuffers and resource binding groups to the channel encoder in the next article, but the channel encoder does more than just set data to the pipeline, as we’ll see below.