Skip to content

Commit

Permalink
Add optional feature dual_source_blending (gpuweb#4621)
Browse files Browse the repository at this point in the history
This patch adds `dual_source_blending` to WebGPU and WGSL SPEC.
- Add `dual_source_blending` as an optional feature in both WebGPU and WGSL.
- Support `@blend_src` in WGSL when `dual_source_blending` is enabled.
- Add all the blend factors that use `src1` to WebGPU SPEC.

Co-authored-by: Kai Ninomiya <kainino@chromium.org>
  • Loading branch information
Jiawei-Shao and kainino0x authored Jun 18, 2024
1 parent 538a4c7 commit 6eeebff
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 15 deletions.
78 changes: 70 additions & 8 deletions spec/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ spec: WGSL; urlPrefix: https://gpuweb.github.io/gpuweb/wgsl/#
type: dfn
text: f16; url: f16
text: location; url: input-output-locations
text: blend_src; url: input-output-locations
text: interpolation; url: interpolation
text: pipeline-overridable; url: pipeline-overridable
text: pipeline constant ID; url: pipeline-constant-id
Expand Down Expand Up @@ -114,6 +115,7 @@ spec: WGSL; urlPrefix: https://gpuweb.github.io/gpuweb/wgsl/#
for: extension
text: f16; url: extension-f16
text: clip_distances; url: extension-clip_distances
text: dual_source_blending; url: extension-dual_source_blending
type: abstract-op
text: SizeOf; url: sizeof
spec: Internationalization Glossary; urlPrefix: https://www.w3.org/TR/i18n-glossary/#
Expand Down Expand Up @@ -8239,20 +8241,30 @@ dictionary GPUFragmentState
- [$validating GPUProgrammableStage$]({{GPUShaderStage/FRAGMENT}}, |descriptor|, |layout|) succeeds.
- |descriptor|.{{GPUFragmentState/targets}}.length must be &le;
|device|.{{device/[[limits]]}}.{{supported limits/maxColorAttachments}}.
- Let |entryPoint| be [$get the entry point$]({{GPUShaderStage/FRAGMENT}}, |descriptor|).
- Let |usesDualSourceBlending| be `false`.
- [=list/For each=] |index| of the [=list/indices=] of |descriptor|.{{GPUFragmentState/targets}}
containing a non-`null` value |colorState|:
- |colorState|.{{GPUColorTargetState/format}} must be listed in [[#plain-color-formats]]
with {{GPUTextureUsage/RENDER_ATTACHMENT}} capability.
- |colorState|.{{GPUColorTargetState/writeMask}} must be &lt; 16.
- If |colorState|.{{GPUColorTargetState/blend}} is [=map/exist|provided=]:
- The |colorState|.{{GPUColorTargetState/format}} must be [=blendable=].
- |colorState|.{{GPUColorTargetState/blend}}.{{GPUBlendState/color}}
must be a [=valid GPUBlendComponent=].
- |colorState|.{{GPUColorTargetState/blend}}.{{GPUBlendState/alpha}}
must be a [=valid GPUBlendComponent=].
- |colorState|.{{GPUColorTargetState/writeMask}} must be &lt; 16.
- If [$get the entry point$]({{GPUShaderStage/FRAGMENT}}, |descriptor|) has a
[=shader stage output=] value |output| with [=location=] attribute equal to |index|:

- If |colorState|.{{GPUColorTargetState/blend}}.{{GPUBlendState/color}}.{{GPUBlendComponent/srcFactor}} or
|colorState|.{{GPUColorTargetState/blend}}.{{GPUBlendState/color}}.{{GPUBlendComponent/dstFactor}} or
|colorState|.{{GPUColorTargetState/blend}}.{{GPUBlendState/alpha}}.{{GPUBlendComponent/srcFactor}} or
|colorState|.{{GPUColorTargetState/blend}}.{{GPUBlendState/alpha}}.{{GPUBlendComponent/dstFactor}}
uses the second input of the corresponding blending unit (is any of
{{GPUBlendFactor/"src1"}}, {{GPUBlendFactor/"one-minus-src1"}},
{{GPUBlendFactor/"src1-alpha"}}, {{GPUBlendFactor/"one-minus-src1-alpha"}}), then:

- Set |usesDualSourceBlending| to `true`.
- For each [=shader stage output=] value |output| with [=location=] attribute equal to |index|
in |entryPoint|:
- For each component in |colorState|.{{GPUColorTargetState/format}}, there must be a
corresponding component in |output|.
(That is, RGBA requires vec4, RGB requires vec3 or vec4, RG requires vec2 or vec3 or vec4.)
Expand All @@ -8271,12 +8283,20 @@ dictionary GPUFragmentState
|colorState|.{{GPUColorTargetState/blend}}.{{GPUBlendState/color}}.{{GPUBlendComponent/srcFactor}}
or .{{GPUBlendComponent/dstFactor}} uses the source alpha
(is any of {{GPUBlendFactor/"src-alpha"}}, {{GPUBlendFactor/"one-minus-src-alpha"}},
or {{GPUBlendFactor/"src-alpha-saturated"}}), then:
{{GPUBlendFactor/"src-alpha-saturated"}}, {{GPUBlendFactor/"src1-alpha"}} or
{{GPUBlendFactor/"one-minus-src1-alpha"}}), then:
- |output| must have an alpha channel (that is, it must be a vec4).

Otherwise, since there is no shader output for the attachment:

- |colorState|.{{GPUColorTargetState/writeMask}} must be 0.
- If |colorState|.{{GPUColorTargetState/writeMask}} is not 0:
- |entryPoint| must have a [=shader stage output=] with [=location=] equal to |index|
and [=blend_src=] omitted or equal to 0.
- If |usesDualSourceBlending| is `true`:
- All the [=shader stage output=] values of |entryPoint| must have a [=blend_src=] attribute.
- |descriptor|.{{GPUFragmentState/targets}}.length must be 1.
- Let |colorState| be |descriptor|.{{GPUFragmentState/targets}}[0].
- If |colorState|.{{GPUColorTargetState/writeMask}} is not 0:
- |entryPoint| must have a [=shader stage output=] with [=location=] equal to 0
and [=blend_src=] equal to 1.
- [$Validating GPUFragmentState's color attachment bytes per sample$](|device|, |descriptor|.{{GPUFragmentState/targets}}) succeeds.
</div>
</div>
Expand Down Expand Up @@ -8407,6 +8427,12 @@ location:
<td><b><code>RGBA<sub>src</src></code></b>
<td>Color output by the fragment shader for the color attachment.
If the shader doesn't return an alpha channel, src-alpha blend factors cannot be used.
<tr>
<td><b><code>RGBA<sub>src1</src></code></b>
<td>Color output by the fragment shader for the color attachment with
<a href="https://gpuweb.github.io/gpuweb/wgsl/#input-output-locations">"@blend_src" attribute</a>
equal to `1`.
If the shader doesn't return an alpha channel, src1-alpha blend factors cannot be used.
<tr>
<td><b><code>RGBA<sub>dst</src></code></b>
<td>Color currently in the color attachment.
Expand Down Expand Up @@ -8438,6 +8464,10 @@ enum GPUBlendFactor {
"src-alpha-saturated",
"constant",
"one-minus-constant",
"src1",
"one-minus-src1",
"src1-alpha",
"one-minus-src1-alpha",
};
</script>

Expand All @@ -8448,12 +8478,14 @@ enum GPUBlendFactor {
<tr>
<th>GPUBlendFactor
<th>Blend factor RGBA components
<th>[=Feature=]
</tr>
</thead>
<tbody dfn-type=enum-value dfn-for=GPUBlendFactor>
<tr>
<td><dfn>"zero"</dfn>
<td><code>(0, 0, 0, 0)</code>
<td rowspan=13>
<tr>
<td><dfn>"one"</dfn>
<td><code>(1, 1, 1, 1)</code>
Expand Down Expand Up @@ -8490,6 +8522,19 @@ enum GPUBlendFactor {
<tr>
<td><dfn>"one-minus-constant"</dfn>
<td><code>(1 - R<sub>const</sub>, 1 - G<sub>const</sub>, 1 - B<sub>const</sub>, 1 - A<sub>const</sub>)</code>
<tr>
<td><dfn>"src1"</dfn>
<td><code>(R<sub>src1</sub>, G<sub>src1</sub>, B<sub>src1</sub>, A<sub>src1</sub>)</code>
<td rowspan=4>{{GPUFeatureName/dual-source-blending}}
<tr>
<td><dfn>"one-minus-src1"</dfn>
<td><code>(1 - R<sub>src1</sub>, 1 - G<sub>src1</sub>, 1 - B<sub>src1</sub>, 1 - A<sub>src1</sub>)</code>
<tr>
<td><dfn>"src1-alpha"</dfn>
<td><code>(A<sub>src1</sub>, A<sub>src1</sub>, A<sub>src1</sub>, A<sub>src1</sub>)</code>
<tr>
<td><dfn>"one-minus-src1-alpha"</dfn>
<td><code>(1 - A<sub>src1</sub>, 1 - A<sub>src1</sub>, 1 - A<sub>src1</sub>, 1 - A<sub>src1</sub>)</code>
</tbody>
</table>

Expand Down Expand Up @@ -15620,6 +15665,23 @@ This feature adds the following [=optional API surfaces=]:
- New WGSL extensions:
- [=extension/clip_distances=]

<h3 id=dom-gpufeaturename-dual-source-blending data-dfn-type=enum-value data-dfn-for=GPUFeatureName>`"dual-source-blending"`
</h3>

Allows the use of [=blend_src=] in WGSL and simultaneously using both pixel shader outputs
(`@blend_src(0)` and `@blend_src(1)`) as inputs to a blending operation with the single color
attachment at [=location=] `0`.

This feature adds the following [=optional API surfaces=]:
- Allows the use of the below {{GPUBlendFactor}}s:
- {{GPUBlendFactor/"src1"}}
- {{GPUBlendFactor/"one-minus-src1"}}
- {{GPUBlendFactor/"src1-alpha"}}
- {{GPUBlendFactor/"one-minus-src1-alpha"}}

- New WGSL extensions:
- [=extension/dual_source_blending=]

# Appendices # {#appendices}

## Texture Format Capabilities ## {#texture-format-caps}
Expand Down
59 changes: 52 additions & 7 deletions wgsl/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,7 @@ The [=syntax/attribute=] names are:
* <a for=attribute lt=interpolate>`'interpolate'`</a>
* <a for=attribute lt=invariant>`'invariant'`</a>
* <a for=attribute lt=location>`'location'`</a>
* <a for=attribute lt=blend_src>`'blend_src'`</a>
* <a for=attribute lt=must_use>`'must_use'`</a>
* <a for=attribute lt=size>`'size'`</a>
* <a for=attribute lt=vertex>`'vertex'`</a>
Expand Down Expand Up @@ -1758,6 +1759,10 @@ The valid [=enable-extensions=] are listed in the following table.
<td>The built-in variable [=built-in values/clip_distances=] is valid to use in the WGSL
module. Otherwise, using [=built-in values/clip_distances=] will result in a
[=shader-creation error=].
<tr><td><dfn noexport dfn-for="extension">`dual_source_blending`</dfn>
<td>`"dual_source_blending"`
<td>The attribute [=attribute/blend_src=] is valid to use in the WGSL module. Otherwise, using
[=attribute/blend_src=] will result in a [=shader-creation error=].
</table>

<div class='example wgsl using extensions expect-error' heading="Using hypothetical enable-extensions">
Expand Down Expand Up @@ -3106,12 +3111,13 @@ The following attributes can be applied to structure members:
* [=attribute/align=]
* [=attribute/builtin=]
* [=attribute/location=]
* [=attribute/blend_src=]
* [=attribute/interpolate=]
* [=attribute/invariant=]
* [=attribute/size=]

Attributes [=attribute/builtin=], [=attribute/location=], [=attribute/interpolate=], and [=attribute/invariant=]
are [=IO attributes=].
Attributes [=attribute/builtin=], [=attribute/location=], [=attribute/blend_src=],
[=attribute/interpolate=], and [=attribute/invariant=] are [=IO attributes=].
An [=IO attribute=] on a member of a structure *S* has effect only when
*S* is used as the type of a [=formal parameter=] or [=return type=] of an [=entry point=].
See [[#stage-inputs-outputs]].
Expand Down Expand Up @@ -8020,6 +8026,7 @@ WGSL defines the following attributes that can be applied to function
parameters and return types:
* [=attribute/builtin=]
* [=attribute/location=]
* [=attribute/blend_src=]
* [=attribute/interpolate=]
* [=attribute/invariant=]

Expand Down Expand Up @@ -8411,6 +8418,33 @@ path: syntax/binding_attr.syntax.bs.include

</table>

## `blend_src` ## {#blend-src-attr}

<pre class=include>
path: syntax/blend_src_attr.syntax.bs.include
</pre>

<table class='data builtin'>
<caption><dfn noexport dfn-for="attribute">`blend_src`</dfn> Attribute</caption>
<tr>
<td style="width:10%">Description
<td>
Specifies a part of the [=fragment=] output when the feature [=extension/dual_source_blending=]
is enabled.
See [[#input-output-locations]].

[=shader-creation error|Must=] only be applied to a member of a [=structure=] type with a
[=attribute/location=] attribute.
[=shader-creation error|Must=] only be applied to declarations of objects with [=numeric scalar=]
or [=numeric vector=] type.
[=shader-creation error|Must=] only be used as an output of the [=fragment=] shader stage.

<tr>
<td>Parameters
<td>[=shader-creation error|Must=] be a [=const-expression=] that [=resolves=] to an [=i32=] or [=u32=] with value of `0` or `1`.

</table>

## `builtin` ## {#builtin-attr}

<pre class=include>
Expand Down Expand Up @@ -8922,6 +8956,7 @@ or to further describe the properties of an input or output.
The <dfn noexport>IO attributes</dfn> are:
* [=attribute/builtin=]
* [=attribute/location=]
* [=attribute/blend_src=]
* [=attribute/interpolate=]
* [=attribute/invariant=]

Expand Down Expand Up @@ -9429,11 +9464,21 @@ Each user-defined [=user-defined input datum|input=] and [=user-defined output d
Each structure member in the entry point IO [=shader-creation error|must=] be one of either a built-in value
(see [[#builtin-inputs-outputs]]), or assigned a location.

Locations [=shader-creation error|must not=] overlap within each of the following sets:
* Members within a structure type.
This applies to any structure, not just those used in shader stage inputs or outputs.
* An entry point's shader stage inputs,
i.e. locations for its formal parameters, or for the members of its formal parameters of structure type.

<div algorithm="locations in entry point inputs">
For each entry point defined in a WGSL module, let |inputs| be its set of shader stage inputs
(i.e. locations for its formal parameters, or for the members of its formal parameters of structure type).
- |inputs| [=shader-creation error|must not=] contain two entries with the same [=attribute/location=] value.
</div>
<div algorithm="locations in structs">
For each structure type |S| defined in a WGSL module (not just those used in shader stage inputs or outputs),
let |members| be the set of members of |S| that have [=attribute/location=] attributes.
- If any entry in |members| specifies a [=attribute/blend_src=] attribute:
- |members| [=shader-creation error|must=] contain exactly `2` entries,
one with `@location(0) @blend_src(0)` and one with `@location(0) @blend_src(1)`.
- All the |members| [=shader-creation error|must=] have same data type.
- Otherwise, |members| [=shader-creation error|must not=] contain two entries with the same [=attribute/location=] value.
</div>

Note: Location numbering is distinct between inputs and outputs:
Location numbers for an entry point's shader stage inputs do not conflict with location numbers for the entry point's shader stage outputs.
Expand Down
5 changes: 5 additions & 0 deletions wgsl/syntax.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ binding_attr :
'@' 'binding' '(' expression ',' ? ')'
;

blend_src_attr :
'@' 'blend_src' '(' expression ',' ? ')'
;

builtin_attr :
'@' 'builtin' '(' builtin_value_name ',' ? ')'
;
Expand Down Expand Up @@ -184,6 +188,7 @@ attribute :
'@' ident_pattern_token argument_expression_list ?
| align_attr
| binding_attr
| blend_src_attr
| builtin_attr
| const_attr
| diagnostic_attr
Expand Down
2 changes: 2 additions & 0 deletions wgsl/syntax/attribute.syntax.bs.include
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

<span class="choice">|</span> [=syntax/binding_attr=]

<span class="choice">|</span> [=syntax/blend_src_attr=]

<span class="choice">|</span> [=syntax/builtin_attr=]

<span class="choice">|</span> [=syntax/const_attr=]
Expand Down
5 changes: 5 additions & 0 deletions wgsl/syntax/blend_src_attr.syntax.bs.include
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div class='syntax' noexport='true'>
<dfn for=syntax>blend_src_attr</dfn> :

<span class="choice"></span> <a for=syntax_sym lt=attr>`'@'`</a> `'blend_src'` <a for=syntax_sym lt=paren_left>`'('`</a> [=syntax/expression=] <a for=syntax_sym lt=comma>`','`</a> ? <a for=syntax_sym lt=paren_right>`')'`</a>
</div>
2 changes: 2 additions & 0 deletions wgsl/wgsl.recursive.bs.include
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@

| `'@'` `'binding'` `'('` [=recursive descent syntax/expression=] `','` ? `')'`

| `'@'` `'blend_src'` `'('` [=recursive descent syntax/expression=] `','` ? `')'`

| `'@'` `'builtin'` `'('` [=syntax/ident_pattern_token=] `','` ? `')'`

| `'@'` `'diagnostic'` [=recursive descent syntax/diagnostic_control=]
Expand Down

0 comments on commit 6eeebff

Please sign in to comment.