-
Notifications
You must be signed in to change notification settings - Fork 370
Add inherited Bind Groups to Render Bundles. #5185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2885,6 +2885,7 @@ enum GPUFeatureName { | |
| "clip-distances", | ||
| "dual-source-blending", | ||
| "subgroups", | ||
| "interited-bundle-bind-groups", | ||
| }; | ||
| </script> | ||
|
|
||
|
|
@@ -10804,6 +10805,12 @@ It must only be included by interfaces which also include those mixins. | |
| : <dfn>\[[dynamic_offsets]]</dfn>, of type [=ordered map=]<{{GPUIndex32}}, [=list=]<{{GPUBufferDynamicOffset}}>>, initally empty | ||
| :: | ||
| The current dynamic offsets for each {{GPUBindingCommandsMixin/[[bind_groups]]}} entry. | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we could replace
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wondered about that myself. I'll take a pass at it and see how complicated it would be. |
||
| : <dfn>\[[inheritedBindGroupState]]</dfn>, of type [=ordered map=]<{{GPUIndex32}}, [=InheritedBindGroupState=]}}>, initially empty | ||
| :: | ||
| State for the bind groups that will be inherited from an executing encoder. | ||
|
|
||
| Note: This will only have entries in {{GPURenderBundleEncoder}} instances. | ||
| </dl> | ||
|
|
||
| ## Bind Groups ## {#programmable-passes-bind-groups} | ||
|
|
@@ -10863,6 +10870,7 @@ It must only be included by interfaces which also include those mixins. | |
| - |index| must be < | ||
| |this|.{{GPUObjectBase/[[device]]}}.{{device/[[limits]]}}.{{supported limits/maxBindGroups}}. | ||
| - |dynamicOffsets|.[=list/size=] must equal |dynamicOffsetCount|. | ||
| - |this|.{{GPUBindingCommandsMixin/[[inheritedBindGroupState]]}} must not [=map/contain=] |index|. | ||
| </div> | ||
| 1. If |bindGroup| is `null`: | ||
| 1. [=map/Remove=] |this|.{{GPUBindingCommandsMixin/[[bind_groups]]}}[|index|]. | ||
|
|
@@ -11046,6 +11054,7 @@ It must only be included by interfaces which also include those mixins. | |
| - If |bindGroupLayout| is `null`, [=iteration/continue=]. | ||
| - Let |bindGroup| be |encoder|.{{GPUBindingCommandsMixin/[[bind_groups]]}}[|index|]. | ||
| - Let |dynamicOffsets| be |encoder|.{{GPUBindingCommandsMixin/[[dynamic_offsets]]}}[|index|]. | ||
| - Let |inheritedState| be |encoder|.{{GPUBindingCommandsMixin/[[inheritedBindGroupState]]}}[|index|]. | ||
| - |bindGroup| must not be `null`. | ||
| - |bindGroup|.{{GPUBindGroup/[[layout]]}} must be [=group-equivalent=] with |bindGroupLayout|. | ||
| - Let |dynamicOffsetIndex| be 0. | ||
|
|
@@ -11062,8 +11071,13 @@ It must only be included by interfaces which also include those mixins. | |
| |dynamicOffsets|[|dynamicOffsetIndex|]. | ||
| - Increment |dynamicOffsetIndex| by 1. | ||
| - If |bindGroupEntry|.{{GPUBindGroupEntry/[[prevalidatedSize]]}} is `false`: | ||
| - [$effective buffer binding size$](|bound|) must be ≥ [=minimum buffer binding size=] | ||
| of the binding variable in |pipeline|'s shader that corresponds to |bindGroupEntry|. | ||
| - Let |minimumBindingSize| be the [=minimum buffer binding size=] of the binding variable in | ||
| |pipeline|'s shader that corresponds to |bindGroupEntry|. | ||
| - If |inheritedState| [=map/exists=]: | ||
| - Set |inheritedState|.{{InheritedBindGroupState/[[minimumBufferBindingSize]]}}[|bindGroupEntry|.{{GPUBindGroupEntry/binding}}] | ||
| to the maximum of |minimumBindingSize| and |inheritedState|.{{InheritedBindGroupState/[[minimumBufferBindingSize]]}}[|bindGroupEntry|.{{GPUBindGroupEntry/binding}}] | ||
| - Otherwise: | ||
| - [$effective buffer binding size$](|bound|) must be ≥ |minimumBindingSize|. | ||
| - [$Encoder bind groups alias a writable resource$](|encoder|, |pipeline|) must be `false`. | ||
| </div> | ||
|
|
||
|
|
@@ -13185,10 +13199,11 @@ attachments used by this encoder. | |
| Executes the commands previously recorded into the given {{GPURenderBundle}}s as part of | ||
| this render pass. | ||
|
|
||
| When a {{GPURenderBundle}} is executed, it does not inherit the render pass's pipeline, bind | ||
| groups, or vertex and index buffers. After a {{GPURenderBundle}} has executed, the render | ||
| pass's pipeline, bind group, and vertex/index buffer state is cleared | ||
| (to the initial, empty values). | ||
| When a {{GPURenderBundle}} is executed, it does not inherit the render pass's pipeline or | ||
| vertex and index buffers. Bind groups are not inherited unless explicitly indicated at | ||
| bundle creation time. See [=inherited bundle state=]. After a {{GPURenderBundle}} has | ||
| executed, the render pass's pipeline, vertex/index buffer, and non-inherited bind group | ||
| state are cleared (to the initial, empty values). | ||
|
|
||
| Note: The state is cleared, not restored to the previous state. | ||
| This occurs even if zero {{GPURenderBundle|GPURenderBundles}} are executed. | ||
|
|
@@ -13222,6 +13237,14 @@ attachments used by this encoder. | |
| - |this|.{{GPURenderCommandsMixin/[[layout]]}} must equal |bundle|.{{GPURenderBundle/[[layout]]}}. | ||
| - If |this|.{{GPURenderCommandsMixin/[[depthReadOnly]]}} is true, |bundle|.{{GPURenderBundle/[[depthReadOnly]]}} must be true. | ||
| - If |this|.{{GPURenderCommandsMixin/[[stencilReadOnly]]}} is true, |bundle|.{{GPURenderBundle/[[stencilReadOnly]]}} must be true. | ||
| - For each ({{GPUIndex32}} |group|, [=InheritedBindGroupState=] |inheritedState|) in |bundle|.{{GPURenderBundle/[[inheritedBindGroupState]]}}: | ||
| - Let |bindGroup| be |this|.{{GPUBindingCommandsMixin/[[bind_groups]]}}[|group|]. | ||
| - |bindGroup|.{{GPUBindGroup/[[layout]]}} must be [=group-equivalent=] with |inheritedState|.{{InheritedBindGroupState/[[layout]]}}. | ||
| - For each ({{GPUIndex32}} |binding|, {{GPUSize64}} |minimumBindingSize|) in |inheritedState|.{{InheritedBindGroupState/[[minimumBufferBindingSize]]}}: | ||
| - Let |bindGroupEntry| be the entry in |bindGroup|.{{GPUBindGroup/[[entries]]}} where |bindGroupEntry|.{{GPUBindGroupEntry/binding}} is |binding|. | ||
| - Let |bound| be a copy of |bindGroupEntry|.{{GPUBindGroupEntry/resource}}. | ||
| - [=Assert=] |bound| is a {{GPUBufferBinding}}. | ||
| - [$effective buffer binding size$](|bound|) must be ≥ |minimumBindingSize|. | ||
| </div> | ||
|
|
||
| 1. For each |bundle| in |bundles|: | ||
|
|
@@ -13234,23 +13257,28 @@ attachments used by this encoder. | |
| <div data-timeline=queue> | ||
| [=Queue timeline=] steps: | ||
|
|
||
| 1. For each ({{GPUIndex32}} |group|, [=InheritedBindGroupState=] |inheritedState|) in |bundle|.{{GPURenderBundle/[[inheritedBindGroupState]]}}: | ||
| 1. Substitue the [=placeholder bind group=] at index |group| used when encoding |bundle| | ||
| with |this|.{{GPUBindingCommandsMixin/[[bind_groups]]}}[|group|]. | ||
|
|
||
| 1. Execute each command in |bundle|.{{GPURenderBundle/[[command_list]]}} | ||
| with |renderState|. | ||
|
|
||
| Note: |renderState| cannot be changed by executing render bundles. Binding state was | ||
| already captured at bundle encoding time, and so isn't used when executing bundles. | ||
| </div> | ||
|
|
||
| 1. [$Reset the render pass binding state$] of |this|. | ||
| 1. [$Reset the render pass binding state$] of |this| for |bundle|. | ||
| </div> | ||
| </div> | ||
| </dl> | ||
|
|
||
| <div algorithm data-timeline=device> | ||
| To <dfn abstract-op>Reset the render pass binding state</dfn> of {{GPURenderPassEncoder}} |encoder| run | ||
| the following [=device timeline=] steps: | ||
| To <dfn abstract-op>Reset the render pass binding state</dfn> of {{GPURenderPassEncoder}} |encoder| for | ||
| {{GPURenderBundle}} |bundle| run the following [=device timeline=] steps: | ||
|
|
||
| 1. [=map/Clear=] |encoder|.{{GPUBindingCommandsMixin/[[bind_groups]]}}. | ||
| 1. For each {{GPUBindGroup}} group at |index| in |encoder|.{{GPUBindingCommandsMixin/[[bind_groups]]}}. | ||
| 1. If |bundle|.{{GPURenderBundle/[[inheritedBindGroupState]]}} does not [=map/contain=] |index|: | ||
| 1. [=map/Remove=] |encoder|.{{GPUBindingCommandsMixin/[[bind_groups]]}}[|index|] | ||
| 1. Set |encoder|.{{GPURenderCommandsMixin/[[pipeline]]}} to `null`. | ||
| 1. Set |encoder|.{{GPURenderCommandsMixin/[[index_buffer]]}} to `null`. | ||
| 1. [=map/Clear=] |encoder|.{{GPURenderCommandsMixin/[[vertex_buffers]]}}. | ||
|
|
@@ -13301,6 +13329,10 @@ GPURenderBundle includes GPUObjectBase; | |
| : <dfn>\[[drawCount]]</dfn>, of type {{GPUSize64}} | ||
| :: | ||
| The number of draw commands in this {{GPURenderBundle}}. | ||
|
|
||
| : <dfn>\[[inheritedBindGroupState]]</dfn>, of type [=ordered map=]<{{GPUIndex32}}, [=InheritedBindGroupState=]}}>, initially empty | ||
| :: | ||
| State for the bind groups this render bundle will inherit from the render pass when executing. | ||
| </dl> | ||
|
|
||
| ### Render Bundle Creation ### {#render-bundle-creation} | ||
|
|
@@ -13372,12 +13404,22 @@ GPURenderBundleEncoder includes GPURenderCommandsMixin; | |
| - A non-`null` value in | ||
| |descriptor|.{{GPURenderPassLayout/colorFormats}}, or | ||
| - A |descriptor|.{{GPURenderPassLayout/depthStencilFormat}}. | ||
| - If |descriptor|.{{GPURenderBundleEncoderDescriptor/inheritedBindGroups}} is not [=list/is empty|empty=]: | ||
| - {{GPUFeatureName/"interited-bundle-bind-groups"}} must be [=enabled for=] |this|. | ||
| </div> | ||
| 1. Set |e|.{{GPURenderCommandsMixin/[[layout]]}} to a copy of |descriptor|'s included {{GPURenderPassLayout}} interface. | ||
| 1. Set |e|.{{GPURenderCommandsMixin/[[depthReadOnly]]}} to |descriptor|.{{GPURenderBundleEncoderDescriptor/depthReadOnly}}. | ||
| 1. Set |e|.{{GPURenderCommandsMixin/[[stencilReadOnly]]}} to |descriptor|.{{GPURenderBundleEncoderDescriptor/stencilReadOnly}}. | ||
| 1. Set |e|.{{GPUCommandsMixin/[[state]]}} to "[=encoder state/open=]". | ||
| 1. Set |e|.{{GPURenderCommandsMixin/[[drawCount]]}} to 0. | ||
| 1. For each {{GPURenderBundleInheritedBindGroupEntry}} |inheritedBindGroup| in | ||
| |descriptor|.{{GPURenderBundleEncoderDescriptor/inheritedBindGroups}}: | ||
| 1. Let |group| be |inheritedBindGroup|.{{GPURenderBundleInheritedBindGroupEntry/group}}. | ||
| 1. Let |layout| be |inheritedBindGroup|.{{GPURenderBundleInheritedBindGroupEntry/layout}}. | ||
| 1. Let |inheritedState| be a new [=InheritedBindGroupState=] object. | ||
| 1. Set |inheritedState|.{{InheritedBindGroupState/[[layout]]}} to |layout|. | ||
| 1. Set |e|.{{GPUBindingCommandsMixin/[[inheritedBindGroupState]]}}[|group|] to be |inheritedState|. | ||
| 1. Set |e|.{{GPUBindingCommandsMixin/[[bind_groups]]}}[|group|] to be a new [=placeholder bind group=] that satisfies |layout|. | ||
| </div> | ||
| </div> | ||
| </dl> | ||
|
|
@@ -13389,6 +13431,9 @@ dictionary GPURenderBundleEncoderDescriptor | |
| : GPURenderPassLayout { | ||
| boolean depthReadOnly = false; | ||
| boolean stencilReadOnly = false; | ||
|
|
||
| // Requires "interited-bundle-bind-groups" feature. | ||
| sequence<GPURenderBundleInheritedBindGroupEntry> inheritedBindGroups = []; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alternatively we could match |
||
| }; | ||
| </script> | ||
|
|
||
|
|
@@ -13408,6 +13453,77 @@ dictionary GPURenderBundleEncoderDescriptor | |
| in. | ||
|
|
||
| See [=read-only depth-stencil=]. | ||
|
|
||
| : <dfn>inheritedBindGroups</dfn> | ||
| :: | ||
| An list of entries describing which bind groups, if any, should be inherited from the | ||
| render pass the render bundle is executed in. | ||
|
|
||
| See [=inherited bundle state=]. | ||
|
|
||
| Requires the {{GPUFeatureName/"interited-bundle-bind-groups"}} feature to be enabled. | ||
| </dl> | ||
|
|
||
| ### Inherited Bundle State ### {#render-bundle-inherited-state} | ||
|
|
||
| By default render bundles [$Reset the render pass binding state|reset the binding state$] when | ||
| executing to ensure that the bundle will operate the same way regardless of the context in which | ||
| it's executed. Render bundles can explicitly request, however, that some bindings be | ||
| <dfn>inherited bundle state</dfn> from the executing render pass. [=Inherited bundle state=] is | ||
| defined at bundle creation time and prevents the identified bindings from being reset before and | ||
| after the bundle execution. This allows bundles to be used in more flexible situations. For example: | ||
| Inheriting a bind group containing view information to more easily render the bundle content from | ||
| multiple viewports in a single frame. | ||
|
|
||
| At this time only {{GPUBindGroup}}s may be inhertited from the render pass. | ||
|
toji marked this conversation as resolved.
|
||
|
|
||
| <script type=idl> | ||
| dictionary GPURenderBundleInheritedBindGroupEntry { | ||
| required GPUIndex32 group; | ||
| required GPUBindGroupLayout layout; | ||
| }; | ||
| </script> | ||
|
|
||
| <dl dfn-type=dict-member dfn-for=GPURenderBundleInheritedBindGroupEntry> | ||
| : <dfn>group</dfn> | ||
| :: | ||
| The index of a bind group to be inherited from the render pass the render bundle is executed | ||
| in. Must be < {{supported limits/maxBindGroups}}. | ||
|
|
||
| : <dfn>layout</dfn> | ||
| :: | ||
| The layout of the {{GPUBindGroup}} that must be set at index {{GPURenderBundleInheritedBindGroupEntry/group}} | ||
| when the render bundle is executed in order for the bundle execution to be valid. | ||
| </dl> | ||
|
|
||
| <div class=note heading> | ||
| Render bundles that make use of inherited bind groups have the following behavior differences: | ||
|
|
||
| - Bind groups indices marked as inherited cannot be changed by the render bundle. | ||
| - Inherited bind groups are not [$Reset the render pass binding state|reset$] | ||
| when the render bundle is finished executing. All other bind groups continue to be reset as | ||
| usual. | ||
| </div> | ||
|
|
||
| A <dfn>placeholder bind group</dfn> is a {{GPUBindGroup}} that satisfies a given {{GPUBindGroupLayout}} | ||
| for purposes of validation but does not contain any actual resources. They are a conceptual mechanism | ||
| intended to simplify spec prose regarding [=inherited bundle state=]. | ||
|
|
||
| During encoding the state of inherited bind groups is tracked using a list of internal | ||
| <dfn dfn>InheritedBindGroupState</dfn> objects. | ||
|
|
||
| An [=InheritedBindGroupState=] object has the following [=device timeline properties=]: | ||
|
|
||
| <dl dfn-type=attribute dfn-for=InheritedBindGroupState data-timeline=device> | ||
| : <dfn>\[[layout]]</dfn>, of type {{GPUBindGroup}} | ||
| :: | ||
| The layout of the {{GPUBindGroup}} that will be inherited when the render bundle is | ||
| executed. | ||
|
|
||
| : <dfn>\[[minimumBufferBindingSize]]</dfn>, of type [=ordered map=]<{{GPUIndex32}}, {{GPUSize64}}>, initially empty. | ||
| :: | ||
| The [=minimum buffer binding size=] for each buffer {{GPUBindGroupEntry/binding}} | ||
| required for that buffer to be valid for the all draw calls in the render bundle. | ||
| </dl> | ||
|
|
||
| ### Finalization ### {#render-bundle-finalization} | ||
|
|
@@ -13457,6 +13573,8 @@ dictionary GPURenderBundleEncoderDescriptor | |
| |this|.{{GPURenderCommandsMixin/[[usage scope]]}}. | ||
| 1. Set |renderBundle|.{{GPURenderBundle/[[drawCount]]}} to | ||
| |this|.{{GPURenderCommandsMixin/[[drawCount]]}}. | ||
| 1. Set |renderBundle|.{{GPURenderBundle/[[inheritedBindGroupState]]}} to | ||
| |this|.{{GPUBindingCommandsMixin/[[inheritedBindGroupState]]}} | ||
| </div> | ||
| </div> | ||
| </dl> | ||
|
|
@@ -16732,6 +16850,17 @@ expose real values whenever the feature is available on the adapter: | |
| - New WGSL extensions: | ||
| - [=extension/subgroups=] | ||
|
|
||
| <h3 id=interited-bundle-bind-groups data-dfn-type=enum-value data-dfn-for=GPUFeatureName>`"interited-bundle-bind-groups"` | ||
| <span id=dom-gpufeaturename-interited-bundle-bind-groups></span> | ||
| </h3> | ||
|
|
||
| Allows {{GPUBindGroup}}s to be [=inherited bundle state=] for {{GPURenderBundle}}s. | ||
|
|
||
| This feature adds the following [=optional API surfaces=]: | ||
|
|
||
| - New {{GPURenderBundleEncoderDescriptor}} dictionary members: | ||
| - {{GPURenderBundleEncoderDescriptor/inheritedBindGroups}} | ||
|
|
||
| # Appendices # {#appendices} | ||
|
|
||
| ## Texture Format Capabilities ## {#texture-format-caps} | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.