diff --git a/samples/hello-cube.html b/samples/hello-cube.html index 10e5974d1c..d62521445e 100644 --- a/samples/hello-cube.html +++ b/samples/hello-cube.html @@ -123,47 +123,48 @@ verticesWriteArray.set(verticesArray); verticesBuffer.unmap(); + // Bind group binding layout + const transformBufferBindGroupLayoutEntry = { + binding: transformBindingNum, // id[[(0)]] + visibility: GPUShaderStageBit.VERTEX, + type: "uniform-buffer" + }; + + const bindGroupLayoutDescriptor = { entries: [transformBufferBindGroupLayoutEntry] }; + bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); + + const pipelineLayoutDescriptor = { bindGroupLayouts: [bindGroupLayout] }; + const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); + // Vertex Input - const positionAttributeDescriptor = { + const positionAttribute = { shaderLocation: positionAttributeNum, // [[attribute(0)]] offset: 0, format: "float4" }; - const colorAttributeDescriptor = { + const colorAttribute = { shaderLocation: colorAttributeNum, offset: colorOffset, format: "float4" } - const vertexBufferDescriptor = { - attributeSet: [positionAttributeDescriptor, colorAttributeDescriptor], + const vertexBufferLayout = { + attributeSet: [positionAttributeDescriptor, colorAttribute], stride: vertexSize, stepMode: "vertex" }; - const vertexInputDescriptor = { vertexBuffers: [vertexBufferDescriptor] }; - - // Bind group binding layout - const transformBufferBindGroupLayoutEntry = { - binding: transformBindingNum, // id[[(0)]] - visibility: GPUShaderStageBit.VERTEX, - type: "uniform-buffer" - }; - - const bindGroupLayoutDescriptor = { entries: [transformBufferBindGroupLayoutEntry] }; - bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); + const vertexInputState = { vertexBuffers: [vertexBufferLayout] }; // Pipeline - const depthStateDescriptor = { + const depthState = { depthWriteEnabled: true, depthCompare: "less" }; - const pipelineLayoutDescriptor = { bindGroupLayouts: [bindGroupLayout] }; - const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); - const vertexStageDescriptor = { + const vertexStage = { module: shaderModule, entryPoint: "vertex_main" }; - const fragmentStageDescriptor = { + const fragmentStage = { module: shaderModule, entryPoint: "fragment_main" }; @@ -183,16 +184,18 @@ }, writeMask: GPUColorWriteBits.ALL }; + const colorWriteState = { + outputs: [colorState] + }; const pipelineDescriptor = { layout: pipelineLayout, - vertexStage: vertexStageDescriptor, - fragmentStage: fragmentStageDescriptor, + vertexStage: vertexStage, + fragmentStage: fragmentStage, - primitiveTopology: "triangle-list", - colorStates: [colorState], - depthStencilState: depthStateDescriptor, - vertexInput: vertexInputDescriptor + vertexInput: vertexInputState + depthStencilState: depthState, + colorWrite: colorWriteState, }; pipeline = device.createRenderPipeline(pipelineDescriptor); diff --git a/spec/index.bs b/spec/index.bs index a4d8bcd885..96eff2e941 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -1049,20 +1049,20 @@ a better limit is not specified. maxVertexBuffers {{GPUSize32}} Higher 8 - The maximum number of {{GPUVertexStateDescriptor/vertexBuffers}} + The maximum number of {{GPUVertexInputState/vertexBuffers}} when creating a {{GPURenderPipeline}}. maxVertexAttributes {{GPUSize32}} Higher 16 - The maximum number of {{GPUVertexBufferLayoutDescriptor/attributes}} - in total across {{GPUVertexStateDescriptor/vertexBuffers}} + The maximum number of {{GPUVertexBufferLayout/attributes}} + in total across {{GPUVertexInputState/vertexBuffers}} when creating a {{GPURenderPipeline}}. maxVertexBufferArrayStride {{GPUSize32}} Higher 2048 - The maximum allowed {{GPUVertexBufferLayoutDescriptor/arrayStride}} + The maximum allowed {{GPUVertexBufferLayout/arrayStride}} when creating a {{GPURenderPipeline}}. @@ -3359,7 +3359,7 @@ has a default layout created and used instead. 1. Set |groupDesc|.{{GPUBindGroupLayoutDescriptor/entries}} to an empty sequence. - 1. For each {{GPUProgrammableStageDescriptor}} |stageDesc| in the descriptor used to create the pipeline: + 1. For each {{GPUProgrammableStage}} |stageDesc| in the descriptor used to create the pipeline: 1. Let |stageInfo| be the "reflection information" for |stageDesc|. @@ -3367,8 +3367,8 @@ has a default layout created and used instead. spec and get information what the interface is for a {{GPUShaderModule}} for a specific entrypoint. - 1. Let |shaderStage| be the {{GPUShaderStageFlags}} for |stageDesc|.{{GPUProgrammableStageDescriptor/entryPoint}} - in |stageDesc|.{{GPUProgrammableStageDescriptor/module}}. + 1. Let |shaderStage| be the {{GPUShaderStageFlags}} for |stageDesc|.{{GPUProgrammableStage/entryPoint}} + in |stageDesc|.{{GPUProgrammableStage/module}}. 1. For each resource |resource| in |stageInfo|'s resource interface: 1. Let |group| be |resource|'s "group" decoration. @@ -3467,30 +3467,30 @@ has a default layout created and used instead. -### GPUProgrammableStageDescriptor ### {#GPUProgrammableStageDescriptor} +### GPUProgrammableStage ### {#GPUProgrammableStage} -A {{GPUProgrammableStageDescriptor}} describes the entry point in the user-provided +A {{GPUProgrammableStage}} describes the entry point in the user-provided {{GPUShaderModule}} that controls one of the programmable stages of a [=pipeline=].
- validating GPUProgrammableStageDescriptor(stage, descriptor, layout) + validating GPUProgrammableStage(stage, descriptor, layout) **Arguments:** - {{GPUShaderStage}} |stage| - - {{GPUProgrammableStageDescriptor}} |descriptor| + - {{GPUProgrammableStage}} |descriptor| - {{GPUPipelineLayout}} |layout| Return `true` if all of the following conditions are satisfied: - - The |descriptor|.{{GPUProgrammableStageDescriptor/module}} is [=valid=] {{GPUShaderModule}}. - - The |descriptor|.{{GPUProgrammableStageDescriptor/module}} contains - an entry point at |stage| named |descriptor|.{{GPUProgrammableStageDescriptor/entryPoint}}. + - The |descriptor|.{{GPUProgrammableStage/module}} is [=valid=] {{GPUShaderModule}}. + - The |descriptor|.{{GPUProgrammableStage/module}} contains + an entry point at |stage| named |descriptor|.{{GPUProgrammableStage/entryPoint}}. - For each |binding| that is [=statically used=] by the shader entry point, the [$validating shader binding$](|binding|, |layout|) returns `true`. - For each texture sampling shader call that is [=statically used=] by the entry point: @@ -3604,7 +3604,7 @@ GPUComputePipeline includes GPUPipelineBase; @@ -3627,7 +3627,7 @@ dictionary GPUComputePipelineDescriptor : GPUPipelineDescriptorBase {
- |this| is a [=valid=] {{GPUDevice}}. - |descriptor|.{{GPUPipelineDescriptorBase/layout}} is [$valid to use with$] |this|. - - [$validating GPUProgrammableStageDescriptor$]({{GPUShaderStage/COMPUTE}}, + - [$validating GPUProgrammableStage$]({{GPUShaderStage/COMPUTE}}, |descriptor|.{{GPUComputePipelineDescriptor/computeStage}}, |descriptor|.{{GPUPipelineDescriptorBase/layout}}) succeeds.
@@ -3678,25 +3678,25 @@ as well as {{GPURenderBundleEncoder}}. Render [=pipeline=] inputs are: - bindings, according to the given {{GPUPipelineLayout}} - - vertex and index buffers, described by {{GPUVertexStateDescriptor}} - - the color attachments, described by {{GPUColorStateDescriptor}} - - optionally, the depth-stencil attachment, described by {{GPUDepthStencilStateDescriptor}} + - vertex and index buffers, described by {{GPUVertexInputState}} + - the color attachments, described by {{GPUColorOutputState}} + - optionally, the depth-stencil attachment, described by {{GPUDepthStencilState}} Render [=pipeline=] outputs are: - {{GPUBindGroupLayoutEntry/buffer}} bindings with a {{GPUBufferBindingLayout/type}} of {{GPUBufferBindingType/"storage"}} - {{GPUBindGroupLayoutEntry/storageTexture}} bindings with a {{GPUStorageTextureBindingLayout/access}} of {{GPUStorageTextureAccess/"write-only"}} - - the color attachments, described by {{GPUColorStateDescriptor}} - - optionally, depth-stencil attachment, described by {{GPUDepthStencilStateDescriptor}} + - the color attachments, described by {{GPUColorOutputState}} + - optionally, depth-stencil attachment, described by {{GPUDepthStencilState}} Stages of a render [=pipeline=]: - 1. Vertex fetch, controlled by {{GPUVertexStateDescriptor}} + 1. Vertex fetch, controlled by {{GPUVertexInputState}} 2. Vertex shader - 3. Primitive assembly, controlled by {{GPUPrimitiveTopology}} - 4. Rasterization, controlled by {{GPURasterizationStateDescriptor}} + 3. Primitive assembly - [[#primitive-assembly]] + 4. Rasterization - [[#rasterization]] 5. Fragment shader - 6. Stencil test and operation, controlled by {{GPUDepthStencilStateDescriptor}} - 7. Depth test and write, controlled by {{GPUDepthStencilStateDescriptor}} - 8. Output merging, controlled by {{GPUColorStateDescriptor}} + 6. Stencil test and operation, controlled by {{GPUDepthStencilState}} + 7. Depth test and write, controlled by {{GPUDepthStencilState}} + 8. Color write - [[#color-write]] Issue: we need a deeper description of these stages @@ -3726,18 +3726,13 @@ GPURenderPipeline includes GPUPipelineBase; @@ -3745,72 +3740,17 @@ dictionary GPURenderPipelineDescriptor : GPUPipelineDescriptorBase { the vertex shader entry point of the [=pipeline=] - {{GPURenderPipelineDescriptor/fragmentStage}} describes the fragment shader entry point of the [=pipeline=]. If it's `null`, the [[#no-color-output]] mode is enabled. -- {{GPURenderPipelineDescriptor/primitiveTopology}} configures - the primitive assembly stage of the [=pipeline=]. -- {{GPURenderPipelineDescriptor/rasterizationState}} configures +- {{GPURenderPipelineDescriptor/rasterization}} configures the rasterization stage of the [=pipeline=]. -- {{GPURenderPipelineDescriptor/colorStates}} describes - the color attachments that are written by the [=pipeline=]. -- {{GPURenderPipelineDescriptor/depthStencilState}} describes +- {{GPURenderPipelineDescriptor/depthStencil}} describes the optional depth-stencil attachment that is written by the [=pipeline=]. -- {{GPURenderPipelineDescriptor/vertexState}} configures +- {{GPURenderPipelineDescriptor/vertexInput}} configures the vertex fetch stage of the [=pipeline=]. -- {{GPURenderPipelineDescriptor/sampleCount}} is - the number of MSAA samples that each attachment has to have. -- {{GPURenderPipelineDescriptor/sampleMask}} is - a binary mask of MSAA samples, according to [[#sample-masking]]. -- {{GPURenderPipelineDescriptor/alphaToCoverageEnabled}} enables the [[#alpha-to-coverage]] mode. Issue(https://github.com/gpuweb/gpuweb/issues/936): Refactor the shape of the render pipeline descriptor to clearly enumerate the (ordered) list of pipeline stages. And start formalizing the spec text. -### No Color Output ### {#no-color-output} - -In no-color-output mode, [=pipeline=] does not produce any color attachment outputs, -and the {{GPURenderPipelineDescriptor/colorStates}} is expected to be empty. - -The [=pipeline=] still performs rasterization and produces depth values -based on the vertex position output. The depth testing and stencil operations can still be used. - -### Alpha to Coverage ### {#alpha-to-coverage} - -In alpha-to-coverage mode, an additional alpha-to-coverage mask -of MSAA samples is generated based on the |alpha| component of the -fragment shader output value of the {{GPURenderPipelineDescriptor/colorStates}}[0]. - -The algorithm of producing the extra mask is platform-dependent and can vary for different pixels. -It guarantees that: - - if |alpha| is 0.0 or less, the result is 0x0 - - if |alpha| is 1.0 or greater, the result is 0xFFFFFFFF - - if |alpha| is greater than some other |alpha1|, - then the produced sample mask has at least as many bits set to 1 as the mask for |alpha1| - -### Sample Masking ### {#sample-masking} - -The final sample mask for a pixel is computed as: -[=rasterization mask=] & {{GPURenderPipelineDescriptor/sampleMask}} & [=shader-output mask=]. - -Only the lower {{GPURenderPipelineDescriptor/sampleCount}} bits of the mask are considered. - -If the least-significant bit at position |N| of the [=final sample mask=] has value of "0", -the sample color outputs (corresponding to sample |N|) to all attachments of the fragment shader are discarded. -Also, no depth test or stencil operations are executed on the relevant samples of the depth-stencil attachment. - -Note: the color output for sample |N| is produced by the fragment shader execution -with SV_SampleIndex == |N| for the current pixel. -If the fragment shader doesn't use this semantics, it's only executed once per pixel. - -The rasterization mask is produced by the rasterization stage, -based on the shape of the rasterized polygon. The samples incuded in the shape get the relevant -bits 1 in the mask. - -The shader-output mask takes the output value of SV_Coverage semantics in the fragment shader. -If the semantics is not [=statically used=] by the shader, and {{GPURenderPipelineDescriptor/alphaToCoverageEnabled}} -is enabled, the [=shader-output mask=] becomes the [=alpha-to-coverage mask=]. Otherwise, it defaults to 0xFFFFFFFF. - -Issue: link to the semantics of SV_SampleIndex and SV_Coverage in WGSL spec. -
: createRenderPipeline(descriptor) :: @@ -3842,10 +3782,8 @@ Issue: link to the semantics of SV_SampleIndex and SV_Coverage in WGSL spec. 1. Make |pipeline| [=invalid=]. 1. Set |pipeline|.{{GPURenderPipeline/[[descriptor]]}} to |descriptor|. - 1. If |descriptor|.{{GPURenderPipelineDescriptor/primitiveTopology}} is - {{GPUPrimitiveTopology/"line-strip"}} or {{GPUPrimitiveTopology/"triangle-strip"}}: - 1. Set |pipeline|.{{GPURenderPipeline/[[strip_index_format]]}} to - |descriptor|.{{GPURenderPipelineDescriptor/vertexState}}.{{GPUVertexStateDescriptor/indexFormat}}. + 1. Set |pipeline|.{{GPURenderPipeline/[[strip_index_format]]}} to + |descriptor|.{{GPURenderPipelineDescriptor/primitiveAssembly}}.{{GPUPrimitiveAssemblyState/stripIndexFormat}}.
1. Return |pipeline|. @@ -3894,42 +3832,25 @@ Issue: link to the semantics of SV_SampleIndex and SV_Coverage in WGSL spec. Return `true` if all of the following conditions are satisfied: - - [$validating GPUProgrammableStageDescriptor$]({{GPUShaderStage/VERTEX}}, + - [$validating GPUVertexInputState$](|descriptor|.{{GPURenderPipelineDescriptor/vertexInput}}, + |descriptor|.{{GPURenderPipelineDescriptor/vertexStage}}) succeeds. + - [$validating GPUProgrammableStage$]({{GPUShaderStage/VERTEX}}, |descriptor|.{{GPURenderPipelineDescriptor/vertexStage}}, |descriptor|.{{GPUPipelineDescriptorBase/layout}}) succeeds. + - [$validating GPUPrimitiveAssemblyState$](|descriptor|.{{GPURenderPipelineDescriptor/primitiveAssembly}}, + |features|) succeeds. + - [$validating GPURasterizationState$](|descriptor|.{{GPURenderPipelineDescriptor/rasterization}}, + |features|) succeeds. + - If |descriptor|.{{GPURenderPipelineDescriptor/rasterization}}.{{GPURasterizationState/sampleCount}} is 1: + - |descriptor|.{{GPURenderPipelineDescriptor/colorWrite}}.{{GPUColorWriteState/alphaToCoverageEnabled}} is `false`, - If |descriptor|.{{GPURenderPipelineDescriptor/fragmentStage}} is not `null`: - - [$validating GPUProgrammableStageDescriptor$]({{GPUShaderStage/FRAGMENT}}, + - [$validating GPUProgrammableStage$]({{GPUShaderStage/FRAGMENT}}, |descriptor|.{{GPURenderPipelineDescriptor/fragmentStage}}, |descriptor|.{{GPUPipelineDescriptorBase/layout}}) succeeds. - - If |descriptor|.{{GPURenderPipelineDescriptor/fragmentStage}} is `null`: - - |descriptor|.{{GPURenderPipelineDescriptor/colorStates}} is empty. - - |descriptor|.{{GPURenderPipelineDescriptor/colorStates}}.length is less than - or equal to 4. - - For each |colorState| layout descriptor in the list - |descriptor|.{{GPURenderPipelineDescriptor/colorStates}}: - - [$validating GPUColorStateDescriptor$](|colorState|, - |descriptor|.{{GPURenderPipelineDescriptor/fragmentStage}}) succeeds. - - [$validating GPURasterizationStateDescriptor$](|descriptor|.{{GPURenderPipelineDescriptor/rasterizationState}}, - |features|) succeeds. - - if |descriptor|.{{GPURenderPipelineDescriptor/depthStencilState}} is not `null`: - - [$validating GPUDepthStencilStateDescriptor$](|descriptor|.{{GPURenderPipelineDescriptor/depthStencilState}}) succeeds. - - [$validating GPUVertexStateDescriptor$](|descriptor|.{{GPURenderPipelineDescriptor/vertexState}}, - |descriptor|.{{GPURenderPipelineDescriptor/vertexStage}}) succeeds. - - If |descriptor|.{{GPURenderPipelineDescriptor/alphaToCoverageEnabled}} is `true`: - - |descriptor|.{{GPURenderPipelineDescriptor/sampleCount}} is greater than 1. - - If the output SV_Coverage semantics is [=statically used=] by - |descriptor|.{{GPURenderPipelineDescriptor/fragmentStage}}: - - |descriptor|.{{GPURenderPipelineDescriptor/alphaToCoverageEnabled}} is `false`. - - If |descriptor|.{{GPURenderPipelineDescriptor/primitiveTopology}} is: -
- : {{GPUPrimitiveTopology/"line-strip"}} or - {{GPUPrimitiveTopology/"triangle-strip"}} - :: |descriptor|.{{GPURenderPipelineDescriptor/vertexState}}.{{GPUVertexStateDescriptor/indexFormat}} - is not `undefined` - : Otherwise - :: |descriptor|.{{GPURenderPipelineDescriptor/vertexState}}.{{GPUVertexStateDescriptor/indexFormat}} - is `undefined` -
+ - if |descriptor|.{{GPURenderPipelineDescriptor/depthStencil}} is not `null`: + - [$validating GPUDepthStencilState$](|descriptor|.{{GPURenderPipelineDescriptor/depthStencil}}) succeeds. + - [$validating GPUColorWriteState$](|descriptor|.{{GPURenderPipelineDescriptor/colorWrite}}, + |descriptor|.{{GPURenderPipelineDescriptor/fragmentStage}}) succeeds. Issue: validate interface matching rules between VS and FS. @@ -3940,7 +3861,19 @@ Issue: define what "compatible" means for render target formats. Issue: need a proper limit for the maximum number of color targets. -### Primitive Topology ### {#primitive-topology} +### Primitive Assembly State ### {#primitive-assembly} + + + +- {{GPUPrimitiveAssemblyState/topology}} defines what kind of + primitives are constructed by the [=pipeline=]. +- {{GPUPrimitiveAssemblyState/stripIndexFormat}} defines the supported + index format for strip topologies. -### Rasterization State ### {#rasterization-state} +
+ validating GPUPrimitiveAssemblyState(|descriptor|) + Return `true` if all of the following conditions are met: + - If |descriptor|.{{GPUPrimitiveAssemblyState/topology}} is: +
+ : {{GPUPrimitiveTopology/"line-strip"}} or + {{GPUPrimitiveTopology/"triangle-strip"}} + :: |descriptor|.{{GPUPrimitiveAssemblyState/stripIndexFormat}} is not `undefined` + : Otherwise + :: |descriptor|.{{GPUPrimitiveAssemblyState/stripIndexFormat}} is `undefined` +
+
+ +### Index Format ### {#index-format} + +The index format determines both the data type of index values in a buffer and, when used with +strip primitive topologies ({{GPUPrimitiveTopology/"line-strip"}} or +{{GPUPrimitiveTopology/"triangle-strip"}}) also specifies the primitive restart value. The +primitive restart value indicates which index value indicates that a new primitive +should be started rather than continuing to construct the triangle strip with the prior indexed +vertices. + +{{GPUPrimitiveAssemblyState}}s that specify a strip primitive topology must not have the +{{GPUPrimitiveAssemblyState/stripIndexFormat}} set to `undefined` +so that the [=primitive restart value=] that will be used is known at pipline creation time. + + + + + + + + + + + + + + + + + + +
Index formatPrimitive restart value
{{GPUIndexFormat/"uint16"}}0xFFFF
{{GPUIndexFormat/"uint32"}}0xFFFFFFFF
+ + +### Rasterizer State ### {#rasterization} + + +- {{GPURasterizationState/sampleCount}} is + the number of MSAA samples that each attachment has to have. +- {{GPURasterizationState/sampleMask}} is + a binary mask of MSAA samples, according to [[#sample-masking]]. +
- validating GPURasterizationStateDescriptor(|descriptor|, |features|) - 1. If |descriptor|.{{GPURasterizationStateDescriptor/clampDepth}} is `true` and |features| - doesn't [=list/contain=] {{GPUFeatureName/"depth-clamping"}}, return `false`. - 1. Return `true`. + validating GPURasterizationState(|device|, |descriptor|) + Return `true` if all of the following conditions are met: + - |descriptor|.{{GPURasterizationState/clampDepth}} is `false`, + or |device|.{{device/[[features]]}} [=list/contain=] {{GPUFeatureName/"depth-clamping"}}.
-### Color State ### {#color-state} +#### Sample Masking #### {#sample-masking} + +The final sample mask for a pixel is computed as: +[=rasterization mask=] & {{GPURasterizationState/sampleMask}} & [=shader-output mask=]. + +Only the lower {{GPURasterizationState/sampleCount}} bits of the mask are considered. + +If the least-significant bit at position |N| of the [=final sample mask=] has value of "0", +the sample color outputs (corresponding to sample |N|) to all attachments of the fragment shader are discarded. +Also, no depth test or stencil operations are executed on the relevant samples of the depth-stencil attachment. + +Note: the color output for sample |N| is produced by the fragment shader execution +with SV_SampleIndex == |N| for the current pixel. +If the fragment shader doesn't use this semantics, it's only executed once per pixel. + +The rasterization mask is produced by the rasterization stage, +based on the shape of the rasterized polygon. The samples incuded in the shape get the relevant +bits 1 in the mask. + +The shader-output mask takes the output value of SV_Coverage semantics in the fragment shader. +If the semantics is not [=statically used=] by the shader, and {{GPUColorWriteState/alphaToCoverageEnabled}} +is enabled, the [=shader-output mask=] becomes the [=alpha-to-coverage mask=]. Otherwise, it defaults to 0xFFFFFFFF. + +Issue: link to the semantics of SV_SampleIndex and SV_Coverage in WGSL spec. + +### Color Write State ### {#color-write} + +- {{GPUColorWriteState/outputs}} describes + the color outputs that are written by the [=pipeline=]. +- {{GPUColorWriteState/alphaToCoverageEnabled}} enables the [[#alpha-to-coverage]] mode. + +
+ validating GPUColorWriteState(descriptor, fragmentStage) + **Arguments:** + - {{GPUColorOutputState}} |descriptor| + - {{GPUProgrammableStage}} |fragmentStage| + + Return `true`, if and only if, all of the following conditions are satisfied: + + - For each |colorState| at |index| in |descriptor|.{{GPUColorWriteState/outputs}}: + - [$validating GPUColorOutputState$](|colorState|) succeeds. + - |fragmentStage| contains an output variable [=statically used=]: + - with `location` annotation equal to |index| + - with a type that is compatible with |colorState|.{{GPUColorOutputState/format}} + with {{GPUTextureUsage/RENDER_ATTACHMENT}} capability. + - If the output `SV_Coverage` semantics is [=statically used=] by |fragmentStage|: + - |descriptor|.{{GPUColorWriteState/alphaToCoverageEnabled}} is `false`. + - If |fragmentStage| is `null`: + - |descriptor|.{{GPUColorWriteState/outputs}} is empty. + - |descriptor|.{{GPUColorWriteState/outputs}}.length is less than + or equal to 4. +
+ +#### No Color Output #### {#no-color-output} + +In no-color-output mode, [=pipeline=] does not produce any color attachment outputs, +and the {{GPUColorWriteState/outputs}} is expected to be empty. + +The [=pipeline=] still performs rasterization and produces depth values +based on the vertex position output. The depth testing and stencil operations can still be used. + +#### Alpha to Coverage #### {#alpha-to-coverage} + +In alpha-to-coverage mode, which is enabled by {{GPUColorWriteState/alphaToCoverageEnabled}}, +an additional alpha-to-coverage mask +of MSAA samples is generated based on the |alpha| component of the +fragment shader output value of the {{GPUColorWriteState/outputs}}[0]. + +The algorithm of producing the extra mask is platform-dependent and can vary for different pixels. +It guarantees that: + - if |alpha| is 0.0 or less, the result is 0x0 + - if |alpha| is 1.0 or greater, the result is 0xFFFFFFFF + - if |alpha| is greater than some other |alpha1|, + then the produced sample mask has at least as many bits set to 1 as the mask for |alpha1| + +#### Color Output State #### {#color-output-state} + +
- validating GPUColorStateDescriptor(descriptor, fragmentStage) + validating GPUColorOutputState(descriptor) **Arguments:** - - {{GPUColorStateDescriptor}} |descriptor| - - {{GPUProgrammableStageDescriptor}} |fragmentStage| + - {{GPUColorOutputState}} |descriptor| Return `true`, if and only if, all of the following conditions are satisfied: - - |descriptor|.{{GPUColorStateDescriptor/format}} is listed in {#plain-color-formats} + - |descriptor|.{{GPUColorOutputState/format}} is listed in {#plain-color-formats} with {{GPUTextureUsage/RENDER_ATTACHMENT}} capability. - - |descriptor|.{{GPUColorStateDescriptor/blend}} is either `undefined`, - or the |descriptor|.{{GPUColorStateDescriptor/format}} is filterable + - |descriptor|.{{GPUColorOutputState/blend}} is either `undefined`, + or the |descriptor|.{{GPUColorOutputState/format}} is filterable according to the {#plain-color-formats} table. - - |descriptor|.{{GPUColorStateDescriptor/writeMask}} is less than 16. - - |fragmentStage| contains an output variable with a type that is compatible with - |descriptor|.{{GPUColorStateDescriptor/format}}. + - |descriptor|.{{GPUColorOutputState/writeMask}} is less than 16.
### Depth/Stencil State ### {#depth-stencil-state}
- validating GPUDepthStencilStateDescriptor(descriptor) + validating GPUDepthStencilState(descriptor) **Arguments:** - - {{GPUDepthStencilStateDescriptor}} |descriptor| + - {{GPUDepthStencilState}} |descriptor| Return `true`, if and only if, all of the following conditions are satisfied: - - |descriptor|.{{GPUDepthStencilStateDescriptor/format}} is listed in {#depth-formats}. - - if |descriptor|.{{GPUDepthStencilStateDescriptor/depthWriteEnabled}} is `true` or - |descriptor|.{{GPUDepthStencilStateDescriptor/depthCompare}} is not {{GPUCompareFunction/"always"}}: - - |descriptor|.{{GPUDepthStencilStateDescriptor/format}} must have a depth component. - - if |descriptor|.{{GPUDepthStencilStateDescriptor/stencilFront}} or - |descriptor|.{{GPUDepthStencilStateDescriptor/stencilBack}} are not default values: - - |descriptor|.{{GPUDepthStencilStateDescriptor/format}} must have a stencil component. + - |descriptor|.{{GPUDepthStencilState/format}} is listed in {#depth-formats}. + - if |descriptor|.{{GPUDepthStencilState/depthWriteEnabled}} is `true` or + |descriptor|.{{GPUDepthStencilState/depthCompare}} is not {{GPUCompareFunction/"always"}}: + - |descriptor|.{{GPUDepthStencilState/format}} must have a depth component. + - if |descriptor|.{{GPUDepthStencilState/stencilFront}} or + |descriptor|.{{GPUDepthStencilState/stencilBack}} are not default values: + - |descriptor|.{{GPUDepthStencilState/format}} must have a stencil component. Issue: how can this algorithm support depth/stencil formats that are added in extensions?
### Vertex State ### {#vertex-state} - - -The index format determines both the data type of index values in a buffer and, when used with -strip primitive topologies ({{GPUPrimitiveTopology/"line-strip"}} or -{{GPUPrimitiveTopology/"triangle-strip"}}) also specifies the primitive restart value. The -primitive restart value indicates which index value indicates that a new primitive -should be started rather than continuing to construct the triangle strip with the prior indexed -vertices. - -{{GPURenderPipelineDescriptor}}s that specify a strip primitive topology must not have the -{{GPUVertexStateDescriptor/indexFormat}} set to `undefined` so that the [=primitive restart value=] -that will be used is known at pipline creation time. - - - - - - - - - - - - - - - - - - -
Index formatPrimitive restart value
{{GPUIndexFormat/"uint16"}}0xFFFF
{{GPUIndexFormat/"uint32"}}0xFFFFFFFF
- #### Vertex Formats #### {#vertex-formats} The name of the format specifies the data type of the component, the number of @@ -4231,35 +4267,34 @@ enum GPUInputStepMode { A vertex buffer is, conceptually, a view into buffer memory as an *array of structures*. -{{GPUVertexBufferLayoutDescriptor/arrayStride}} is the stride, in bytes, between *elements* of that array. +{{GPUVertexBufferLayout/arrayStride}} is the stride, in bytes, between *elements* of that array. Each element of a vertex buffer is like a *structure* with a memory layout defined by its -{{GPUVertexBufferLayoutDescriptor/attributes}}, which describe the *members* of the structure. +{{GPUVertexBufferLayout/attributes}}, which describe the *members* of the structure. -Each {{GPUVertexAttributeDescriptor}} describes its -{{GPUVertexAttributeDescriptor/format}} and its -{{GPUVertexAttributeDescriptor/offset}}, in bytes, within the structure. +Each {{GPUVertexAttribute}} describes its +{{GPUVertexAttribute/format}} and its +{{GPUVertexAttribute/offset}}, in bytes, within the structure. Each attribute appears as a separate input in a vertex shader, each bound by a numeric *location*, -which is specified by {{GPUVertexAttributeDescriptor/shaderLocation}}. -Every location must be unique within the {{GPUVertexStateDescriptor}}. +which is specified by {{GPUVertexAttribute/shaderLocation}}. +Every location must be unique within the {{GPUVertexInputState}}.
- validating GPUVertexBufferLayoutDescriptor(descriptor, vertexStage) + validating GPUVertexBufferLayout(descriptor, vertexStage) **Arguments:** - - {{GPUVertexBufferLayoutDescriptor}} |descriptor| - - {{GPUProgrammableStageDescriptor}} |vertexStage| + - {{GPUVertexBufferLayout}} |descriptor| + - {{GPUProgrammableStage}} |vertexStage| Return `true`, if and only if, all of the following conditions are satisfied: - 1. |descriptor|.{{GPUVertexBufferLayoutDescriptor/arrayStride}} is less than or equal to + 1. |descriptor|.{{GPUVertexBufferLayout/arrayStride}} is less than or equal to {{GPULimits/maxVertexBufferArrayStride|GPULimits.maxVertexBufferArrayStride}}. - 1. Any attribute |at| in the list |descriptor|.{{GPUVertexBufferLayoutDescriptor/attributes}} has - |at|.{{GPUVertexAttributeDescriptor/offset}} + sizeOf(|at|.{{GPUVertexAttributeDescriptor/format}}) less or equal to - |descriptor|.{{GPUVertexBufferLayoutDescriptor/arrayStride}}. - 1. For every vertex attribute in the shader reflection of |vertexStage|.{{GPUProgrammableStageDescriptor/module}} - that is know to be [=statically used=] by |vertexStage|.{{GPUProgrammableStageDescriptor/entryPoint}}, - there is a corresponding |at| element of |descriptor|.{{GPUVertexBufferLayoutDescriptor/attributes}} that: - 1. The shader format is |at|.{{GPUVertexAttributeDescriptor/format}}. - 2. The shader location is |at|.{{GPUVertexAttributeDescriptor/shaderLocation}}. + 1. Any attribute |at| in the list |descriptor|.{{GPUVertexBufferLayout/attributes}} has + |at|.{{GPUVertexAttribute/offset}} + sizeOf(|at|.{{GPUVertexAttribute/format}}) less or equal to + |descriptor|.{{GPUVertexBufferLayout/arrayStride}}. + 1. For every vertex attribute in the shader reflection of |vertexStage|.{{GPUProgrammableStage/module}} + that is know to be [=statically used=] by |vertexStage|.{{GPUProgrammableStage/entryPoint}}, + there is a corresponding |at| element of |descriptor|.{{GPUVertexBufferLayout/attributes}} that: + 1. The shader format is |at|.{{GPUVertexAttribute/format}}. + 2. The shader location is |at|.{{GPUVertexAttribute/shaderLocation}}.
- validating GPUVertexStateDescriptor(descriptor, vertexStage) + validating GPUVertexInputState(descriptor, vertexStage) **Arguments:** - - {{GPUVertexStateDescriptor}} |descriptor| - - {{GPUProgrammableStageDescriptor}} |vertexStage| + - {{GPUVertexInputState}} |descriptor| + - {{GPUProgrammableStage}} |vertexStage| Return `true`, if and only if, all of the following conditions are satisfied: - 1. |descriptor|.{{GPUVertexStateDescriptor/vertexBuffers}}.length is less than or equal to + 1. |descriptor|.{{GPUVertexInputState/vertexBuffers}}.length is less than or equal to {{GPULimits/maxVertexBuffers|GPULimits.maxVertexBuffers}} - 1. Each |vertexBuffer| layout descriptor in the list |descriptor|.{{GPUVertexStateDescriptor/vertexBuffers}} - passes [$validating GPUVertexBufferLayoutDescriptor$](|vertexBuffer|, |vertexStage|) - 1. The sum of |vertexBuffer|.{{GPUVertexBufferLayoutDescriptor/attributes}}.length, - over every |vertexBuffer| in |descriptor|.{{GPUVertexStateDescriptor/vertexBuffers}}, + 1. Each |vertexBuffer| layout descriptor in the list |descriptor|.{{GPUVertexInputState/vertexBuffers}} + passes [$validating GPUVertexBufferLayout$](|vertexBuffer|, |vertexStage|) + 1. The sum of |vertexBuffer|.{{GPUVertexBufferLayout/attributes}}.length, + over every |vertexBuffer| in |descriptor|.{{GPUVertexInputState/vertexBuffers}}, is less than or equal to {{GPULimits/maxVertexAttributes|GPULimits.maxVertexAttributes}}. - 1. Each |at| in the union of all {{GPUVertexAttributeDescriptor}} - across |descriptor|.{{GPUVertexStateDescriptor/vertexBuffers}} has a distinct - |at|.{{GPUVertexAttributeDescriptor/shaderLocation}} value. + 1. Each |at| in the union of all {{GPUVertexAttribute}} + across |descriptor|.{{GPUVertexInputState/vertexBuffers}} has a distinct + |at|.{{GPUVertexAttribute/shaderLocation}} value.
# Command Buffers # {#command-buffers} @@ -6200,7 +6235,7 @@ enum GPUStoreOp { - Let |pipelineDescriptor| be |encoder|.{{GPURenderEncoderBase/[[pipeline]]}}.{{GPURenderPipeline/[[descriptor]]}}. - For each {{GPUIndex32}} |slot| `0` to - |pipelineDescriptor|.{{GPURenderPipelineDescriptor/vertexState}}.{{GPUVertexStateDescriptor/vertexBuffers}}.length: + |pipelineDescriptor|.{{GPURenderPipelineDescriptor/vertexInput}}.{{GPUVertexInputState/vertexBuffers}}.length: - |encoder|.{{GPURenderEncoderBase/[[vertex_buffers]]}}[|slot|] must not be `null`. @@ -7123,7 +7158,7 @@ typedef [EnforceRange] long GPUSignedOffset32; typedef unsigned long GPUFlagsConstant; -## Colors & Vectors ## {#colors-and-vectors} +## Colors & Vectors ## {#outputs-and-vectors}