From 0dd590f47178b5a2f83d61b6bd9f9b804be3b86e Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Tue, 11 Aug 2020 16:49:27 -0400 Subject: [PATCH 1/8] Introduce the internal usages --- spec/index.bs | 87 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 34 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index ccd6471d31..aa8dd9ec95 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -601,20 +601,36 @@ the user behind an `ArrayBuffer`, thus avoiding any data copies. ### Resource Usages ### {#programming-model-resource-usages} -Buffers and textures can be used by the GPU in multiple ways, -which can be split into two groups: - -: Read-only usages -:: Usages like - {{GPUBufferUsage/VERTEX|GPUBufferUsage.VERTEX}} or - {{GPUTextureUsage/SAMPLED|GPUTextureUsage.SAMPLED}} - don't change the contents of a resource. - -: Mutating usages -:: Usages like {{GPUBufferUsage/STORAGE|GPUBufferUsage.STORAGE}} - do change the contents of a resource. - -Issue(gpuweb/gpuweb#296): Consider merging all read-only usages. +A [=physical resource=] can be used on GPU in one of the following internal usages: +
+ : copy-source + :: Source of a copy operation. Preserves the contents. + Allowed by {{GPUBufferUsage/COPY_SRC}} or {{GPUTextureUsage/COPY_SRC}}. + : copy-destination + :: Destination of a copy operation. + Allowed by {{GPUBufferUsage/COPY_DST}} or {{GPUTextureUsage/COPY_DST}}. + : input + :: Buffer with input data for draw or dispatch calls. Preserves the contents. + Allowed by {{GPUBufferUsage/INDEX}}, {{GPUBufferUsage/VERTEX}}, or {{GPUBufferUsage/INDIRECT}}. + : uniform + :: Resource bindings that are uniformly accessed by the shaders. Preserves the contents. + Allowed by {{GPUBufferUsage/UNIFORM}} or {{GPUTextureUsage/SAMPLED}}. + : storage + :: Writable storage resource binding. + Allowed by {{GPUBufferUsage/STORAGE}} or {{GPUTextureUsage/STORAGE}}. + : storage-read + :: Read-only storage resource bindings. Preserves the contents. + Allowed by {{GPUBufferUsage/STORAGE}} or {{GPUTextureUsage/STORAGE}}. + : attachment + :: Texture used as an output attachment in a render pass. + Allowed by {{GPUTextureUsage/OUTPUT_ATTACHMENT}}. + : attachment-read + :: Texture used as a read-only output attachment in a render pass. Preserves the contents. + Allowed by {{GPUTextureUsage/OUTPUT_ATTACHMENT}}. + : query-resolve + :: Query resolve buffer. + Allowed by {{GPUBufferUsage/QUERY_RESOLVE}}. +
Textures may consist of separate [=mipmap levels=] and [=array layers=], which can be used differently at any given time. @@ -622,34 +638,39 @@ Each such subresource is uniquely identified by a [=texture=], [=mipmap level=], and (for {{GPUTextureDimension/2d}} textures only) [=array layer=]. -The **main usage rule** is that any [=subresource=] -at any given time can only be in either: - - a combination of [=read-only usage=]s - - a single [=mutating usage=] - -Enforcing this rule allows the API to limit when data races can occur -when working with memory. That property makes applications written against +Some [=internal usage=]s are compatible with others. +That means an implementation can consider multiple usages active at the same time. +There is a limited set of allowed usage set, where each usage is compatible with the other: + - [=copy-source=], [=input=], [=uniform=], [=storage-read=] - in any combination, including repeating any of the usage + - [=copy-destination=] - singular usage + - [=storage=], [=storage-read=] - in any combination + - [=attachment=] - singular usage + - [=attachment-read=], [=uniform=] - in any combination + - [=query-resolve=] - singular usage + +Enforcing that the usages are only combined into one of the [=allowed usage set=]s +allows the API to limit when data races can occur when working with memory. +That property makes applications written against WebGPU more likely to run without modification on different platforms. Generally, when an implementation processes an operation that uses a [=subresource=] in a different way than its current usage allows, it schedules a transition of the resource into the new state. In some cases, like within an open {{GPURenderPassEncoder}}, such a transition is impossible due to the hardware limitations. -We define these places as usage scopes: -each [=subresource=] must not change usage within the [=usage scope=]. +We define these places as usage scopes. +The **main usage rule** is that each [=subresource=] usage within any [=usage scope=] +must be a subset of one of the [=allowed usage set=]s. -For example, binding the same buffer for {{GPUBufferUsage/STORAGE|GPUBufferUsage.STORAGE}} as well as for -{{GPUBufferUsage/VERTEX|GPUBufferUsage.VERTEX}} within the same {{GPURenderPassEncoder}} would put the encoder -as well as the owning {{GPUCommandEncoder}} into the error state. Since -{{GPUBufferUsage/STORAGE|GPUBufferUsage.STORAGE}} is the only [=mutating usage=] for a buffer -that is valid inside a render pass, if it's present, -this buffer can't be used in any other way within this pass. +For example, binding the same buffer for [=storage=] as well as for +[=input=] within the same {{GPURenderPassEncoder}} would put the encoder +as well as the owning {{GPUCommandEncoder}} into the error state. +There is no [=allowed usage set=] that contains this combination. The [=subresources=] of textures included in the views provided to {{GPURenderPassColorAttachmentDescriptor/attachment|GPURenderPassColorAttachmentDescriptor.attachment}} and {{GPURenderPassColorAttachmentDescriptor/resolveTarget|GPURenderPassColorAttachmentDescriptor.resolveTarget}} -are considered to have {{GPUTextureUsage/OUTPUT_ATTACHMENT}} -for the [=usage scope=] of this render pass. +are considered to have either [=attachment=] or [=attachment-read=] usage for the +[=usage scope=] of this render pass, depending on the descriptor flags. The physical size of a {{GPUTexture}} [=subresource=] is the dimension of the {{GPUTexture}} [=subresource=] in texels that includes the possible extra paddings to form complete [=texel blocks=] in the @@ -667,8 +688,6 @@ the {{GPUTexture}} at [=mipmap level=] 2, the sampling hardware uses {15, 15, 1} while its [=physical size=] is {16, 16, 1} as the block-compression algorithm can only operate on 4x4 [=texel blocks=]. -Issue(gpuweb/gpuweb#514): Document read-only states for depth views. - ### Synchronization ### {#programming-model-synchronization} For each [=subresource=] of a [=physical resource=], its set of @@ -701,7 +720,7 @@ The [=usage scopes=] are validated at {{GPUCommandEncoder/finish()|GPUCommandEnc The implementation performs the usage scope validation by composing the set of all [=usage flags=] of each [=subresource=] used in the [=usage scope=]. A {{GPUValidationError}} is generated in the current scope with an appropriate error message -if that union contains a [=mutating usage=] combined with any other usage. +if that set is not within any of the [=allowed usage set=]s. ## Core Internal Objects ## {#core-internal-objects} From 33fb6dece5620961ec0cc2c5122777994272dd22 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Tue, 11 Aug 2020 17:33:38 -0400 Subject: [PATCH 2/8] Update the usage tracking --- spec/index.bs | 158 ++++++++++++++++++++++++-------------------------- 1 file changed, 75 insertions(+), 83 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index aa8dd9ec95..63883c7025 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -625,31 +625,34 @@ A [=physical resource=] can be used on GPU in one of the following inte :: Texture used as an output attachment in a render pass. Allowed by {{GPUTextureUsage/OUTPUT_ATTACHMENT}}. : attachment-read - :: Texture used as a read-only output attachment in a render pass. Preserves the contents. + :: Texture used as a read-only attachment in a render pass. Preserves the contents. Allowed by {{GPUTextureUsage/OUTPUT_ATTACHMENT}}. - : query-resolve - :: Query resolve buffer. - Allowed by {{GPUBufferUsage/QUERY_RESOLVE}}. +Issue: as copy operations are specified manually +(like, "source buffer has to be different from the destination buffer"), +should we remove the "copy-*" variants, +or try to refactor the copy operations spec to match? + Textures may consist of separate [=mipmap levels=] and [=array layers=], which can be used differently at any given time. -Each such subresource is uniquely identified by a +Each such texture subresource is uniquely identified by a [=texture=], [=mipmap level=], and (for {{GPUTextureDimension/2d}} textures only) [=array layer=]. +We define subresource to be either a whole buffer, or a [=texture subresource=]. + Some [=internal usage=]s are compatible with others. That means an implementation can consider multiple usages active at the same time. There is a limited set of allowed usage set, where each usage is compatible with the other: - - [=copy-source=], [=input=], [=uniform=], [=storage-read=] - in any combination, including repeating any of the usage + - {[=copy-source=] | [=input=] | [=uniform=] | [=storage-read=]} - in any combination - [=copy-destination=] - singular usage - - [=storage=], [=storage-read=] - in any combination + - {[=storage=] | [=storage-read=]} - in any combination - [=attachment=] - singular usage - - [=attachment-read=], [=uniform=] - in any combination - - [=query-resolve=] - singular usage + - {[=attachment-read=] | [=uniform=]} - in any combination Enforcing that the usages are only combined into one of the [=allowed usage set=]s -allows the API to limit when data races can occur when working with memory. +allows the API to limit when data races can occur in working with memory. That property makes applications written against WebGPU more likely to run without modification on different platforms. @@ -658,6 +661,7 @@ in a different way than its current usage allows, it schedules a transition of t into the new state. In some cases, like within an open {{GPURenderPassEncoder}}, such a transition is impossible due to the hardware limitations. We define these places as usage scopes. + The **main usage rule** is that each [=subresource=] usage within any [=usage scope=] must be a subset of one of the [=allowed usage set=]s. @@ -669,14 +673,13 @@ There is no [=allowed usage set=] that contains this combination. The [=subresources=] of textures included in the views provided to {{GPURenderPassColorAttachmentDescriptor/attachment|GPURenderPassColorAttachmentDescriptor.attachment}} and {{GPURenderPassColorAttachmentDescriptor/resolveTarget|GPURenderPassColorAttachmentDescriptor.resolveTarget}} -are considered to have either [=attachment=] or [=attachment-read=] usage for the -[=usage scope=] of this render pass, depending on the descriptor flags. +are considered to be used as [=attachment=] for the [=usage scope=] of this render pass. -The physical size of a {{GPUTexture}} [=subresource=] is the dimension of the {{GPUTexture}} -[=subresource=] in texels that includes the possible extra paddings to form complete [=texel blocks=] in the -[=subresource=]. +The physical size of a [=texture subresource=] is the dimension of the +[=texture subresource=] in texels that includes the possible extra paddings +to form complete [=texel blocks=] in the [=subresource=]. - - For pixel-based {{GPUTextureFormat}}s, the [=physical size=] is always equal to the size of the [=subresource=] + - For pixel-based {{GPUTextureFormat}}s, the [=physical size=] is always equal to the size of the [=texture subresource=] used in the sampling hardwares. - {{GPUTexture}}s in block-based compressed {{GPUTextureFormat}}s always have a [=mipmap level=] 0 whose {{GPUTexture/[[textureSize]]}} is a multiple of the [=texel block size=], but the lower mipmap levels might not be the multiple of the [=texel block size=] and can @@ -684,25 +687,22 @@ The physical size of a {{GPUTexture}} [=subresource=] is the dime
Considering a {{GPUTexture}} in BC format whose {{GPUTexture/[[textureSize]]}} is {60, 60, 1}, when sampling -the {{GPUTexture}} at [=mipmap level=] 2, the sampling hardware uses {15, 15, 1} as the size of the [=subresource=], +the {{GPUTexture}} at [=mipmap level=] 2, the sampling hardware uses {15, 15, 1} as the size of the [=texture subresource=], while its [=physical size=] is {16, 16, 1} as the block-compression algorithm can only operate on 4x4 [=texel blocks=].
### Synchronization ### {#programming-model-synchronization} For each [=subresource=] of a [=physical resource=], its set of -[=usage flags=] is tracked on the [=Queue timeline=]. -Usage flags are {{GPUBufferUsage}} or {{GPUTextureUsage}} flags, -according to the type of the subresource. +[=internal usage=] flags is tracked on the [=Queue timeline=]. Issue: This section will need to be revised to support multiple queues. On the [=Queue timeline=], there is an ordered sequence of [=usage scopes=]. Each item on the timeline is contained within exactly one scope. -For the duration of each scope, the set of [=usage flags=] of any given +For the duration of each scope, the set of [=internal usage=] flags of any given [=subresource=] is constant. -A [=subresource=] may transition to new usages -at the boundaries between [=usage scope=]s. +A [=subresource=] may transition to new usages at the boundaries between [=usage scope=]s. This specification defines the following [=usage scopes=]: 1. an individual command on a {{GPUCommandEncoder}}, such as {{GPUCommandEncoder/copyBufferToTexture()|GPUCommandEncoder.copyBufferToTexture}}. @@ -710,15 +710,15 @@ This specification defines the following [=usage scopes=]: 3. the whole {{GPURenderPassEncoder}}. Note: calling {{GPUProgrammablePassEncoder/setBindGroup(index, bindGroup, dynamicOffsets)|GPUProgrammablePassEncoder.setBindGroup}} -adds the {{GPUBindGroup/[[usedBuffers]]}} and {{GPUBindGroup/[[usedTextures]]}} to the [=usage scope=] +adds the {{GPUBindGroup/[[usedResources]]}} to the [=usage scope=] regardless of whether the shader or {{GPUPipelineLayout}} actually depends on these bindings. Similarly {{GPURenderEncoderBase/setIndexBuffer()|GPURenderEncoderBase.setIndexBuffer}} -add the index buffer to the usage scope (as {{GPUBufferUsage/INDEX|GPUBufferUsage.INDEX}}) +add the index buffer to the usage scope (as [=input=]) regardless of whether the indexed draw calls are used afterwards. The [=usage scopes=] are validated at {{GPUCommandEncoder/finish()|GPUCommandEncoder.finish}} time. The implementation performs the usage scope validation by composing -the set of all [=usage flags=] of each [=subresource=] used in the [=usage scope=]. +the set of all [=internal usage=] flags of each [=subresource=] used in the [=usage scope=]. A {{GPUValidationError}} is generated in the current scope with an appropriate error message if that set is not within any of the [=allowed usage set=]s. @@ -1479,10 +1479,10 @@ interface GPUBufferUsage { - |this| is a [=valid=] {{GPUDevice}}. - |descriptor|.{{GPUBufferDescriptor/usage}} is a subset of |this|.[[allowed buffer usages]]. - If |descriptor|.{{GPUBufferDescriptor/usage}} contains {{GPUBufferUsage/MAP_READ}}: - - |descriptor|.{{GPUBufferDescriptor/usage}} contains no other [=usage flags=] + - |descriptor|.{{GPUBufferDescriptor/usage}} is contains no other flags except {{GPUBufferUsage/COPY_DST}}. - If |descriptor|.{{GPUBufferDescriptor/usage}} contains {{GPUBufferUsage/MAP_WRITE}}: - - |descriptor|.{{GPUBufferDescriptor/usage}} contains no other [=usage flags=] + - |descriptor|.{{GPUBufferDescriptor/usage}} contains no other flags except {{GPUBufferUsage/COPY_SRC}}. - If |descriptor|.{{GPUBufferDescriptor/mappedAtCreation}} is `true`: - |descriptor|.{{GPUBufferDescriptor/size}} is a multiple of 4. @@ -2639,14 +2639,10 @@ A {{GPUBindGroup}} object has the following internal slots: :: The set of {{GPUBindGroupEntry}}s this {{GPUBindGroup}} describes. - : \[[usedBuffers]] of type maplike<{{GPUBuffer}}, {{GPUBufferUsageFlags}}>. - :: - The set of buffers used by this bind group and the corresponding usage flags. - - : \[[usedTextures]] of type maplike<{{GPUTexture}} [=subresource=], {{GPUTextureUsageFlags}}>. + : \[[usedResources]] of type maplike<[=subresource=], setLike<[=internal usage=]>>. :: - The set of texure subresources used by this bind group. Each subresource is - stored with the union of usage flags that apply to it. + The set of buffer and texture [=subresource=]s used by this bind group, + associated with sets of the [=internal usage=] flags.
@@ -2764,41 +2760,36 @@ A {{GPUBindGroup}} object has the following internal slots: |descriptor|.{{GPUBindGroupDescriptor/layout}}. 1. Let |bindGroup|.{{GPUBindGroup/[[entries]]}} = |descriptor|.{{GPUBindGroupDescriptor/entries}}. - 1. Let |bindGroup|.{{GPUBindGroup/[[usedBuffers]]}} = union of the buffer usages - across all entries. - 1. Let |bindGroup|.{{GPUBindGroup/[[usedTextures]]}} = union of the texture - [=subresource=] usages across all entries. + 1. Let |bindGroup|.{{GPUBindGroup/[[usedResources]]}} = {}. 1. For each {{GPUBindGroupEntry}} |bindingDescriptor| in |descriptor|.{{GPUBindGroupDescriptor/entries}}: - 1. If |layoutBinding|.{{GPUBindGroupLayoutEntry/type}} is - {{GPUBindingType/"sampled-texture"}}: - 1. Each texture [=subresource=] seen by |resource| is added - to {{GPUBindGroup/[[usedTextures]]}} with - {{GPUTextureUsage/SAMPLED}} flag. - - 1. If |layoutBinding|.{{GPUBindGroupLayoutEntry/type}} is - {{GPUBindingType/"readonly-storage-texture"}} or - {{GPUBindingType/"writeonly-storage-texture"}}: - 1. Each texture [=subresource=] seen by |resource| is added to - {{GPUBindGroup/[[usedTextures]]}} with {{GPUTextureUsage/STORAGE}} - flag. - - 1. If |layoutBinding|.{{GPUBindGroupLayoutEntry/type}} is - {{GPUBindingType/"uniform-buffer"}}: - 1. The buffer is added to the {{GPUBindGroup/[[usedBuffers]]}} - map with {{GPUBufferUsage/UNIFORM}} flag. - - 1. If |layoutBinding|.{{GPUBindGroupLayoutEntry/type}} is - {{GPUBindingType/"storage-buffer"}} or - {{GPUBindingType/"readonly-storage-buffer"}}: - 1. The buffer is added to the {{GPUBindGroup/[[usedBuffers]]}} - map with {{GPUBufferUsage/STORAGE}} flag. + 1. Let |internalUsage| be the result of [$derive binding usage$](|layoutBinding|.{{GPUBindGroupLayoutEntry/type}}) + 1. Each [=subresource=] seen by |resource| is added to {{GPUBindGroup/[[usedResources]]}} as |internalUsage|. 1. Return |bindGroup|. Issue: define the "effective buffer binding size" separately. + +
+ derive binding usage(type) + + **Arguments:** + - {{GPUBindingType}} |type| + + **Returns:** [=internal usage=] + + 1. If |type| is + {{GPUBindingType/"uniform-buffer"}} or {{GPUBindingType/"sampled-texture"}}: + 1. return [=uniform=] + 1. If |type| is + {{GPUBindingType/"readonly-storage-buffer"}} or {{GPUBindingType/"readonly-storage-texture"}}: + 1. return [=storage-read=] + 1. If |type| is + {{GPUBindingType/"storage-buffer"}} or {{GPUBindingType/"writeonly-storage-texture"}}: + 1. return [=storage=] +
## GPUPipelineLayout ## {#pipeline-layout} @@ -4009,14 +4000,17 @@ dictionary GPUCommandEncoderDescriptor : GPUObjectDescriptorBase { 1. Set |this|.{{GPUCommandEncoder/[[state]]}} to {{encoder state/encoding a render pass}}. 1. For each |colorAttachment| in |descriptor|.{{GPURenderPassDescriptor/colorAttachments}}: - 1. The texture [=subresource=] seen by |colorAttachment|.{{GPURenderPassColorAttachmentDescriptor/attachment}} - is considered to be used as {{GPUTextureUsage/OUTPUT_ATTACHMENT}} for the + 1. The [=texture subresource=] seen by |colorAttachment|.{{GPURenderPassColorAttachmentDescriptor/attachment}} + is considered to be used as [=attachment=] for the duration of the render pass. 1. Let |depthStencilAttachment| be |descriptor|.{{GPURenderPassDescriptor/depthStencilAttachment}}. 1. If |depthStencilAttachment| is not `null`: - 1. The texture [=subresource=] seen by |depthStencilAttachment|.{{GPURenderPassDepthStencilAttachmentDescriptor/attachment}} - is considered to be used as {{GPUTextureUsage/OUTPUT_ATTACHMENT}} for the - duration of the render pass. + 1. if |depthStencilAttachment|.{{GPURenderPassDepthStencilAttachmentDescriptor/depthReadOnly}} and + {{GPURenderPassDepthStencilAttachmentDescriptor/stencilReadOnly}} are set + 1. The [=texture subresource=] seen by |depthStencilAttachment|.{{GPURenderPassDepthStencilAttachmentDescriptor/attachment}} + is considered to be used as [=attachment-read=] for the duration of the render pass. + 1. Else, the [=texture subresource=] seen by |depthStencilAttachment|.{{GPURenderPassDepthStencilAttachmentDescriptor/attachment}} + is considered to be used as [=attachment=] for the duration of the render pass. Issue: specify the behavior of read-only depth/stencil @@ -4121,7 +4115,7 @@ dictionary GPUTextureCopyView { }; -A {{GPUTextureCopyView}} is a view of a sub-region of one or multiple contiguous [=texture=] [=subresources=] with the initial +A {{GPUTextureCopyView}} is a view of a sub-region of one or multiple contiguous [=texture subresources=] with the initial offset {{GPUOrigin3D}} in texels, used when copying data from or to a {{GPUTexture}}. * {{GPUTextureCopyView/origin}}: If unspecified, defaults to `[0, 0, 0]`. @@ -4318,7 +4312,7 @@ Issue: convert "Valid Texture Copy Range" into an algorithm with parameters, sim : copyBufferToTexture(source, destination, copySize) :: Encode a command into the {{GPUCommandEncoder}} that copies data from a sub-region of a - {{GPUBuffer}} to a sub-region of one or multiple continuous {{GPUTexture}} [=subresources=]. + {{GPUBuffer}} to a sub-region of one or multiple continuous [=texture subresources=].
**Called on:** {{GPUCommandEncoder}} |this|. @@ -4326,8 +4320,7 @@ Issue: convert "Valid Texture Copy Range" into an algorithm with parameters, sim **Arguments:**
                 |source|: Combined with |copySize|, defines the region of the source buffer.
-                |destination|: Combined with |copySize|, defines the region of the destination
-                    texture [=subresource=].
+                |destination|: Combined with |copySize|, defines the region of the destination [=texture subresource=].
                 |copySize|:
             
@@ -4354,14 +4347,14 @@ Issue: convert "Valid Texture Copy Range" into an algorithm with parameters, sim : copyTextureToBuffer(source, destination, copySize) :: Encode a command into the {{GPUCommandEncoder}} that copies data from a sub-region of one or - multiple continuous {{GPUTexture}} [=subresources=]to a sub-region of a {{GPUBuffer}}. + multiple continuous [=texture subresources=]to a sub-region of a {{GPUBuffer}}.
**Called on:** {{GPUCommandEncoder}} |this|. **Arguments:**
-                |source|: Combined with |copySize|, defines the region of the source texture [=subresources=].
+                |source|: Combined with |copySize|, defines the region of the source [=texture subresources=].
                 |destination|: Combined with |copySize|, defines the region of the destination buffer.
                 |copySize|:
             
@@ -4389,17 +4382,16 @@ Issue: convert "Valid Texture Copy Range" into an algorithm with parameters, sim : copyTextureToTexture(source, destination, copySize) :: Encode a command into the {{GPUCommandEncoder}} that copies data from a sub-region of one - or multiple contiguous {{GPUTexture}} [=subresources=] to another sub-region of one or - multiple continuous {{GPUTexture}} [=subresources=]. + or multiple contiguous [=texture subresources=] to another sub-region of one or + multiple continuous [=texture subresources=].
**Called on:** {{GPUCommandEncoder}} |this|. **Arguments:**
-                |source|: Combined with |copySize|, defines the region of the source texture [=subresources=].
-                |destination|: Combined with |copySize|, defines the region of the destination
-                    texture [=subresources=].
+                |source|: Combined with |copySize|, defines the region of the source [=texture subresources=].
+                |destination|: Combined with |copySize|, defines the region of the destination [=texture subresources=].
                 |copySize|:
             
@@ -5269,7 +5261,7 @@ dictionary GPURenderPassDepthStencilAttachmentDescriptor { 1. |this|.{{GPURenderPassDepthStencilAttachmentDescriptor/attachment}} must have a renderable depth-and/or-stencil format. 1. |this|.{{GPURenderPassDepthStencilAttachmentDescriptor/attachment}} must be a view of a - single [=subresource=]. + single [=texture subresource=]. 1. |this|.{{GPURenderPassDepthStencilAttachmentDescriptor/attachment}}.{{GPUTexture/[[textureUsage]]}} must contain {{GPUTextureUsage/OUTPUT_ATTACHMENT}}. 1. |this|.{{GPURenderPassDepthStencilAttachmentDescriptor/depthReadOnly}} is `true`, @@ -5354,7 +5346,7 @@ enum GPUStoreOp { - |buffer|.{{GPUBuffer/[[usage]]}} contains {{GPUBufferUsage/INDEX}}. - |offset| + |size| ≤ |buffer|.{{GPUBuffer/[[size]]}}.
- 1. Add |buffer| to the [=usage scope=] as {{GPUBufferUsage/INDEX}}. + 1. Add |buffer| to the [=usage scope=] as [=input=]. 1. Set |this|.{{GPURenderEncoderBase/[[index_buffer]]}} to be |buffer|. 1. Set |this|.{{GPURenderEncoderBase/[[index_format]]}} to be |indexFormat|.
@@ -5389,7 +5381,7 @@ enum GPUStoreOp { Issue: Define the maximum number of vertex buffers.
- 1. Add |buffer| to the [=usage scope=] as {{GPUBufferUsage/VERTEX}}. + 1. Add |buffer| to the [=usage scope=] as [=input=]. 1. Set |this|.{{GPURenderEncoderBase/[[vertex_buffers]]}}[|slot|] to be |buffer|. @@ -5472,7 +5464,7 @@ enum GPUStoreOp { |indirectBuffer|.{{GPUBuffer/[[size]]}}. - |indirectOffset| is a multiple of 4. - 1. Add |indirectBuffer| to the [=usage scope=] as {{GPUBufferUsage/INDIRECT}}. + 1. Add |indirectBuffer| to the [=usage scope=] as [=input=]. @@ -5514,7 +5506,7 @@ enum GPUStoreOp { |indirectBuffer|.{{GPUBuffer/[[size]]}}. - |indirectOffset| is a multiple of 4. - 1. Add |indirectBuffer| to the [=usage scope=] as {{GPUBufferUsage/INDIRECT}}. + 1. Add |indirectBuffer| to the [=usage scope=] as [=input=]. From 9cb21ac35bdd23be8739339600f622248004f25e Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 13 Aug 2020 11:13:51 -0400 Subject: [PATCH 3/8] Address feedback from Corentin and Kai --- spec/index.bs | 64 +++++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index 63883c7025..a6ec8c5800 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -603,17 +603,11 @@ the user behind an `ArrayBuffer`, thus avoiding any data copies. A [=physical resource=] can be used on GPU in one of the following internal usages:
- : copy-source - :: Source of a copy operation. Preserves the contents. - Allowed by {{GPUBufferUsage/COPY_SRC}} or {{GPUTextureUsage/COPY_SRC}}. - : copy-destination - :: Destination of a copy operation. - Allowed by {{GPUBufferUsage/COPY_DST}} or {{GPUTextureUsage/COPY_DST}}. : input :: Buffer with input data for draw or dispatch calls. Preserves the contents. Allowed by {{GPUBufferUsage/INDEX}}, {{GPUBufferUsage/VERTEX}}, or {{GPUBufferUsage/INDIRECT}}. - : uniform - :: Resource bindings that are uniformly accessed by the shaders. Preserves the contents. + : constant + :: Resource bindings that are constant from the shader point of view. Preserves the contents. Allowed by {{GPUBufferUsage/UNIFORM}} or {{GPUTextureUsage/SAMPLED}}. : storage :: Writable storage resource binding. @@ -629,11 +623,6 @@ A [=physical resource=] can be used on GPU in one of the following inte Allowed by {{GPUTextureUsage/OUTPUT_ATTACHMENT}}.
-Issue: as copy operations are specified manually -(like, "source buffer has to be different from the destination buffer"), -should we remove the "copy-*" variants, -or try to refactor the copy operations spec to match? - Textures may consist of separate [=mipmap levels=] and [=array layers=], which can be used differently at any given time. Each such texture subresource is uniquely identified by a @@ -644,12 +633,11 @@ We define subresource to be either a whole buffer, or a [=texture Some [=internal usage=]s are compatible with others. That means an implementation can consider multiple usages active at the same time. -There is a limited set of allowed usage set, where each usage is compatible with the other: - - {[=copy-source=] | [=input=] | [=uniform=] | [=storage-read=]} - in any combination - - [=copy-destination=] - singular usage - - {[=storage=] | [=storage-read=]} - in any combination - - [=attachment=] - singular usage - - {[=attachment-read=] | [=uniform=]} - in any combination +There is a limited set of allowed usage sets, where each usage is compatible with the other: + - {[=internal usage/input=] | [=internal usage/constant=] | [=internal usage/storage-read=]} - in any combination + - {[=internal usage/storage=] | [=internal usage/storage-read=]} - in any combination + - [=internal usage/attachment=] - singular usage + - {[=internal usage/attachment-read=] | [=internal usage/storage-read=] | [=internal usage/constant=]} - in any combination Enforcing that the usages are only combined into one of the [=allowed usage set=]s allows the API to limit when data races can occur in working with memory. @@ -662,18 +650,18 @@ into the new state. In some cases, like within an open {{GPURenderPassEncoder}}, transition is impossible due to the hardware limitations. We define these places as usage scopes. -The **main usage rule** is that each [=subresource=] usage within any [=usage scope=] -must be a subset of one of the [=allowed usage set=]s. +The **main usage rule** is, for any one [=subresource=], its set of [=internal usages=] +within one [=usage scope=] must be a subset of at least one of the [=allowed usage sets=]. -For example, binding the same buffer for [=storage=] as well as for -[=input=] within the same {{GPURenderPassEncoder}} would put the encoder +For example, binding the same buffer for [=internal usage/storage=] as well as for +[=internal usage/input=] within the same {{GPURenderPassEncoder}} would put the encoder as well as the owning {{GPUCommandEncoder}} into the error state. There is no [=allowed usage set=] that contains this combination. The [=subresources=] of textures included in the views provided to {{GPURenderPassColorAttachmentDescriptor/attachment|GPURenderPassColorAttachmentDescriptor.attachment}} and {{GPURenderPassColorAttachmentDescriptor/resolveTarget|GPURenderPassColorAttachmentDescriptor.resolveTarget}} -are considered to be used as [=attachment=] for the [=usage scope=] of this render pass. +are considered to be used as [=internal usage/attachment=] for the [=usage scope=] of this render pass. The physical size of a [=texture subresource=] is the dimension of the [=texture subresource=] in texels that includes the possible extra paddings @@ -713,7 +701,7 @@ Note: calling {{GPUProgrammablePassEncoder/setBindGroup(index, bindGroup, dynami adds the {{GPUBindGroup/[[usedResources]]}} to the [=usage scope=] regardless of whether the shader or {{GPUPipelineLayout}} actually depends on these bindings. Similarly {{GPURenderEncoderBase/setIndexBuffer()|GPURenderEncoderBase.setIndexBuffer}} -add the index buffer to the usage scope (as [=input=]) +add the index buffer to the usage scope (as [=internal usage/input=]) regardless of whether the indexed draw calls are used afterwards. The [=usage scopes=] are validated at {{GPUCommandEncoder/finish()|GPUCommandEncoder.finish}} time. @@ -1479,7 +1467,7 @@ interface GPUBufferUsage { - |this| is a [=valid=] {{GPUDevice}}. - |descriptor|.{{GPUBufferDescriptor/usage}} is a subset of |this|.[[allowed buffer usages]]. - If |descriptor|.{{GPUBufferDescriptor/usage}} contains {{GPUBufferUsage/MAP_READ}}: - - |descriptor|.{{GPUBufferDescriptor/usage}} is contains no other flags + - |descriptor|.{{GPUBufferDescriptor/usage}} contains no other flags except {{GPUBufferUsage/COPY_DST}}. - If |descriptor|.{{GPUBufferDescriptor/usage}} contains {{GPUBufferUsage/MAP_WRITE}}: - |descriptor|.{{GPUBufferDescriptor/usage}} contains no other flags @@ -2639,7 +2627,7 @@ A {{GPUBindGroup}} object has the following internal slots: :: The set of {{GPUBindGroupEntry}}s this {{GPUBindGroup}} describes. - : \[[usedResources]] of type maplike<[=subresource=], setLike<[=internal usage=]>>. + : \[[usedResources]] of type map<[=subresource=], set<[=internal usage=]>>. :: The set of buffer and texture [=subresource=]s used by this bind group, associated with sets of the [=internal usage=] flags. @@ -2782,13 +2770,13 @@ A {{GPUBindGroup}} object has the following internal slots: 1. If |type| is {{GPUBindingType/"uniform-buffer"}} or {{GPUBindingType/"sampled-texture"}}: - 1. return [=uniform=] + 1. return [=internal usage/constant=] 1. If |type| is {{GPUBindingType/"readonly-storage-buffer"}} or {{GPUBindingType/"readonly-storage-texture"}}: - 1. return [=storage-read=] + 1. return [=internal usage/storage-read=] 1. If |type| is {{GPUBindingType/"storage-buffer"}} or {{GPUBindingType/"writeonly-storage-texture"}}: - 1. return [=storage=] + 1. return [=internal usage/storage=] @@ -4001,16 +3989,16 @@ dictionary GPUCommandEncoderDescriptor : GPUObjectDescriptorBase { 1. Set |this|.{{GPUCommandEncoder/[[state]]}} to {{encoder state/encoding a render pass}}. 1. For each |colorAttachment| in |descriptor|.{{GPURenderPassDescriptor/colorAttachments}}: 1. The [=texture subresource=] seen by |colorAttachment|.{{GPURenderPassColorAttachmentDescriptor/attachment}} - is considered to be used as [=attachment=] for the + is considered to be used as [=internal usage/attachment=] for the duration of the render pass. 1. Let |depthStencilAttachment| be |descriptor|.{{GPURenderPassDescriptor/depthStencilAttachment}}. 1. If |depthStencilAttachment| is not `null`: 1. if |depthStencilAttachment|.{{GPURenderPassDepthStencilAttachmentDescriptor/depthReadOnly}} and {{GPURenderPassDepthStencilAttachmentDescriptor/stencilReadOnly}} are set - 1. The [=texture subresource=] seen by |depthStencilAttachment|.{{GPURenderPassDepthStencilAttachmentDescriptor/attachment}} - is considered to be used as [=attachment-read=] for the duration of the render pass. + 1. The [=texture subresources=] seen by |depthStencilAttachment|.{{GPURenderPassDepthStencilAttachmentDescriptor/attachment}} + are considered to be used as [=internal usage/attachment-read=] for the duration of the render pass. 1. Else, the [=texture subresource=] seen by |depthStencilAttachment|.{{GPURenderPassDepthStencilAttachmentDescriptor/attachment}} - is considered to be used as [=attachment=] for the duration of the render pass. + is considered to be used as [=internal usage/attachment=] for the duration of the render pass. Issue: specify the behavior of read-only depth/stencil @@ -5346,7 +5334,7 @@ enum GPUStoreOp { - |buffer|.{{GPUBuffer/[[usage]]}} contains {{GPUBufferUsage/INDEX}}. - |offset| + |size| ≤ |buffer|.{{GPUBuffer/[[size]]}}. - 1. Add |buffer| to the [=usage scope=] as [=input=]. + 1. Add |buffer| to the [=usage scope=] as [=internal usage/input=]. 1. Set |this|.{{GPURenderEncoderBase/[[index_buffer]]}} to be |buffer|. 1. Set |this|.{{GPURenderEncoderBase/[[index_format]]}} to be |indexFormat|. @@ -5381,7 +5369,7 @@ enum GPUStoreOp { Issue: Define the maximum number of vertex buffers. - 1. Add |buffer| to the [=usage scope=] as [=input=]. + 1. Add |buffer| to the [=usage scope=] as [=internal usage/input=]. 1. Set |this|.{{GPURenderEncoderBase/[[vertex_buffers]]}}[|slot|] to be |buffer|. @@ -5464,7 +5452,7 @@ enum GPUStoreOp { |indirectBuffer|.{{GPUBuffer/[[size]]}}. - |indirectOffset| is a multiple of 4. - 1. Add |indirectBuffer| to the [=usage scope=] as [=input=]. + 1. Add |indirectBuffer| to the [=usage scope=] as [=internal usage/input=]. @@ -5506,7 +5494,7 @@ enum GPUStoreOp { |indirectBuffer|.{{GPUBuffer/[[size]]}}. - |indirectOffset| is a multiple of 4. - 1. Add |indirectBuffer| to the [=usage scope=] as [=input=]. + 1. Add |indirectBuffer| to the [=usage scope=] as [=internal usage/input=]. From 9e7f9aa2fc7b25cbebc07ebdb9f9dc2437c5c72d Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Thu, 13 Aug 2020 12:24:25 -0400 Subject: [PATCH 4/8] use the switch list for types in BG validation --- spec/index.bs | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index a6ec8c5800..c92dee04a2 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -3187,23 +3187,29 @@ A {{GPUProgrammableStageDescriptor}} describes the entry point in the user-provi 1. |layout|.{{GPUPipelineLayout/[[bindGroupLayouts]]}}[|bindGroup|] contains a {{GPUBindGroupLayoutEntry}} |entry| whose |entry|.{{GPUBindGroupLayoutEntry/binding}} == |bindIndex|. - 1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is {{GPUBindingType/"sampler"}}, - the |binding| has to be a non-comparison sampler. - 1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is {{GPUBindingType/"comparison-sampler"}}, - the |binding| has to be a comparison sampler. - 1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is {{GPUBindingType/"sampled-texture"}}, - the |binding| has to be a sampled texture with the component type of |entry|.{{GPUBindGroupLayoutEntry/textureComponentType}}, - and it must be multisampled if and only if |entry|.{{GPUBindGroupLayoutEntry/multisampled}} is true. - 1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is {{GPUBindingType/"readonly-storage-texture"}}, - the |binding| has to be a read-only storage texture with format of |entry|.{{GPUBindGroupLayoutEntry/storageTextureFormat}}. - 1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is {{GPUBindingType/"writeonly-storage-texture"}}, - the |binding| has to be a writable storage texture with format of |entry|.{{GPUBindGroupLayoutEntry/storageTextureFormat}}. - 1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is {{GPUBindingType/"uniform-buffer"}}, - the |binding| has to be a uniform buffer. - 1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is {{GPUBindingType/"storage-buffer"}}, - the |binding| has to be a storage buffer. - 1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is {{GPUBindingType/"readonly-storage-buffer"}}, - the |binding| has to be a read-only storage buffer. + 1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is: +
+ + : {{GPUBindingType/"sampler"}} + :: the |binding| has to be a non-comparison sampler + : {{GPUBindingType/"comparison-sampler"}} + :: the |binding| has to be a comparison sampler + : {{GPUBindingType/"sampled-texture"}} + :: + 1. the |binding| has to be a sampled texture with the component type of |entry|.{{GPUBindGroupLayoutEntry/textureComponentType}}. + 2. it must be multisampled if and only if |entry|.{{GPUBindGroupLayoutEntry/multisampled}} is true. + : {{GPUBindingType/"readonly-storage-texture"}} + :: the |binding| has to be a read-only storage texture with format of |entry|.{{GPUBindGroupLayoutEntry/storageTextureFormat}} + : {{GPUBindingType/"writeonly-storage-texture"}} + :: the |binding| has to be a writable storage texture with format of |entry|.{{GPUBindGroupLayoutEntry/storageTextureFormat}} + : {{GPUBindingType/"uniform-buffer"}} + :: the |binding| has to be a uniform buffer + : {{GPUBindingType/"storage-buffer"}} + :: the |binding| has to be a storage buffer + : {{GPUBindingType/"readonly-storage-buffer"}} + :: the |binding| has to be a read-only storage buffer + +
1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is {{GPUBindingType/"sampled-texture"}}, {{GPUBindingType/"readonly-storage-texture"}}, or {{GPUBindingType/"writeonly-storage-texture"}}, the shader view dimension of the texture has to match |entry|.{{GPUBindGroupLayoutEntry/viewDimension}}. 1. If |entry|.{{GPUBindGroupLayoutEntry/minBufferBindingSize}} is not undefined: From b9d898ce3cbee3549b85429077b9e77d01a0232a Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 17 Aug 2020 11:48:53 -0400 Subject: [PATCH 5/8] Switch to a multiset and resolve Kai's feedback --- spec/index.bs | 54 ++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index c92dee04a2..16ce6c39e3 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -633,13 +633,17 @@ We define subresource to be either a whole buffer, or a [=texture Some [=internal usage=]s are compatible with others. That means an implementation can consider multiple usages active at the same time. -There is a limited set of allowed usage sets, where each usage is compatible with the other: +There is a limited set of allowed usage multisets, where each usage is compatible with the other: - {[=internal usage/input=] | [=internal usage/constant=] | [=internal usage/storage-read=]} - in any combination - {[=internal usage/storage=] | [=internal usage/storage-read=]} - in any combination - [=internal usage/attachment=] - singular usage - {[=internal usage/attachment-read=] | [=internal usage/storage-read=] | [=internal usage/constant=]} - in any combination -Enforcing that the usages are only combined into one of the [=allowed usage set=]s +A multi-set differentiates between an `[=internal usage=]` included once versus multiple times. +This difference is critical for [=internal usage/attachment=], +which can't be used multiple times in the same render pass for the same [=texture subresource=]. + +Enforcing that the usages are only combined into one of the [=allowed usage multiset=]s allows the API to limit when data races can occur in working with memory. That property makes applications written against WebGPU more likely to run without modification on different platforms. @@ -651,12 +655,12 @@ transition is impossible due to the hardware limitations. We define these places as usage scopes. The **main usage rule** is, for any one [=subresource=], its set of [=internal usages=] -within one [=usage scope=] must be a subset of at least one of the [=allowed usage sets=]. +within one [=usage scope=] must be a subset of at least one of the [=allowed usage multisets=]. For example, binding the same buffer for [=internal usage/storage=] as well as for [=internal usage/input=] within the same {{GPURenderPassEncoder}} would put the encoder as well as the owning {{GPUCommandEncoder}} into the error state. -There is no [=allowed usage set=] that contains this combination. +There is no [=allowed usage multiset=] that contains this combination. The [=subresources=] of textures included in the views provided to {{GPURenderPassColorAttachmentDescriptor/attachment|GPURenderPassColorAttachmentDescriptor.attachment}} and @@ -708,7 +712,7 @@ The [=usage scopes=] are validated at {{GPUCommandEncoder/finish()|GPUCommandEnc The implementation performs the usage scope validation by composing the set of all [=internal usage=] flags of each [=subresource=] used in the [=usage scope=]. A {{GPUValidationError}} is generated in the current scope with an appropriate error message -if that set is not within any of the [=allowed usage set=]s. +if that set is not within any of the [=allowed usage multiset=]s. ## Core Internal Objects ## {#core-internal-objects} @@ -2761,7 +2765,7 @@ A {{GPUBindGroup}} object has the following internal slots:
- derive binding usage(type) + derive binding usage(|type|) **Arguments:** - {{GPUBindingType}} |type| @@ -3189,26 +3193,24 @@ A {{GPUProgrammableStageDescriptor}} describes the entry point in the user-provi a {{GPUBindGroupLayoutEntry}} |entry| whose |entry|.{{GPUBindGroupLayoutEntry/binding}} == |bindIndex|. 1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is:
- - : {{GPUBindingType/"sampler"}} - :: the |binding| has to be a non-comparison sampler - : {{GPUBindingType/"comparison-sampler"}} - :: the |binding| has to be a comparison sampler - : {{GPUBindingType/"sampled-texture"}} - :: - 1. the |binding| has to be a sampled texture with the component type of |entry|.{{GPUBindGroupLayoutEntry/textureComponentType}}. - 2. it must be multisampled if and only if |entry|.{{GPUBindGroupLayoutEntry/multisampled}} is true. - : {{GPUBindingType/"readonly-storage-texture"}} - :: the |binding| has to be a read-only storage texture with format of |entry|.{{GPUBindGroupLayoutEntry/storageTextureFormat}} - : {{GPUBindingType/"writeonly-storage-texture"}} - :: the |binding| has to be a writable storage texture with format of |entry|.{{GPUBindGroupLayoutEntry/storageTextureFormat}} - : {{GPUBindingType/"uniform-buffer"}} - :: the |binding| has to be a uniform buffer - : {{GPUBindingType/"storage-buffer"}} - :: the |binding| has to be a storage buffer - : {{GPUBindingType/"readonly-storage-buffer"}} - :: the |binding| has to be a read-only storage buffer - + : {{GPUBindingType/"sampler"}} + :: the |binding| is a non-comparison sampler + : {{GPUBindingType/"comparison-sampler"}} + :: the |binding| is a comparison sampler + : {{GPUBindingType/"sampled-texture"}} + :: + 1. the |binding| is a sampled texture with the component type of |entry|.{{GPUBindGroupLayoutEntry/textureComponentType}}. + 2. it must be multisampled if and only if |entry|.{{GPUBindGroupLayoutEntry/multisampled}} is true. + : {{GPUBindingType/"readonly-storage-texture"}} + :: the |binding| is a read-only storage texture with format of |entry|.{{GPUBindGroupLayoutEntry/storageTextureFormat}} + : {{GPUBindingType/"writeonly-storage-texture"}} + :: the |binding| is a writable storage texture with format of |entry|.{{GPUBindGroupLayoutEntry/storageTextureFormat}} + : {{GPUBindingType/"uniform-buffer"}} + :: the |binding| is a uniform buffer + : {{GPUBindingType/"storage-buffer"}} + :: the |binding| is a storage buffer + : {{GPUBindingType/"readonly-storage-buffer"}} + :: the |binding| is a read-only storage buffer
1. If |entry|.{{GPUBindGroupLayoutEntry/type}} is {{GPUBindingType/"sampled-texture"}}, {{GPUBindingType/"readonly-storage-texture"}}, or {{GPUBindingType/"writeonly-storage-texture"}}, the shader view dimension of the texture has to match |entry|.{{GPUBindGroupLayoutEntry/viewDimension}}. From 2e6bc4a4c2e3aef08430f4fbdfdecaa838867f2a Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 17 Aug 2020 13:32:19 -0400 Subject: [PATCH 6/8] Attempt to fix the 'derive binding usage' define --- spec/index.bs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index 16ce6c39e3..63fb419fce 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -610,11 +610,14 @@ A [=physical resource=] can be used on GPU in one of the following inte :: Resource bindings that are constant from the shader point of view. Preserves the contents. Allowed by {{GPUBufferUsage/UNIFORM}} or {{GPUTextureUsage/SAMPLED}}. : storage - :: Writable storage resource binding. - Allowed by {{GPUBufferUsage/STORAGE}} or {{GPUTextureUsage/STORAGE}}. + :: Read-write storage resource binding. + Allowed by {{GPUBufferUsage/STORAGE}}. : storage-read :: Read-only storage resource bindings. Preserves the contents. Allowed by {{GPUBufferUsage/STORAGE}} or {{GPUTextureUsage/STORAGE}}. + : storage-write + :: Write-only storage resource bindings. + Allowed by {{GPUTextureUsage/STORAGE}}. : attachment :: Texture used as an output attachment in a render pass. Allowed by {{GPUTextureUsage/OUTPUT_ATTACHMENT}}. @@ -636,6 +639,7 @@ That means an implementation can consider multiple usages active at the same tim There is a limited set of allowed usage multisets, where each usage is compatible with the other: - {[=internal usage/input=] | [=internal usage/constant=] | [=internal usage/storage-read=]} - in any combination - {[=internal usage/storage=] | [=internal usage/storage-read=]} - in any combination + - {[=internal usage/storage-write=]} - used one or more times - [=internal usage/attachment=] - singular usage - {[=internal usage/attachment-read=] | [=internal usage/storage-read=] | [=internal usage/constant=]} - in any combination @@ -2756,7 +2760,7 @@ A {{GPUBindGroup}} object has the following internal slots: 1. For each {{GPUBindGroupEntry}} |bindingDescriptor| in |descriptor|.{{GPUBindGroupDescriptor/entries}}: - 1. Let |internalUsage| be the result of [$derive binding usage$](|layoutBinding|.{{GPUBindGroupLayoutEntry/type}}) + 1. Let |internalUsage| be the result of [$GPUDevice/derive binding usage$](|layoutBinding|.{{GPUBindGroupLayoutEntry/type}}) 1. Each [=subresource=] seen by |resource| is added to {{GPUBindGroup/[[usedResources]]}} as |internalUsage|.
1. Return |bindGroup|. @@ -2778,9 +2782,10 @@ A {{GPUBindGroup}} object has the following internal slots: 1. If |type| is {{GPUBindingType/"readonly-storage-buffer"}} or {{GPUBindingType/"readonly-storage-texture"}}: 1. return [=internal usage/storage-read=] - 1. If |type| is - {{GPUBindingType/"storage-buffer"}} or {{GPUBindingType/"writeonly-storage-texture"}}: + 1. If |type| is {{GPUBindingType/"storage-buffer"}}: 1. return [=internal usage/storage=] + 1. If |type| is {{GPUBindingType/"writeonly-storage-texture"}}: + 1. return [=internal usage/storage-write=] From 8c41c0f7740fffa80cb64c0804ffb1eeafca71e5 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 17 Aug 2020 21:10:14 -0400 Subject: [PATCH 7/8] Refactor the definition of compatible usage lists --- spec/index.bs | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/spec/index.bs b/spec/index.bs index 63fb419fce..d202b06254 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -634,20 +634,16 @@ Each such texture subresource is uniquely identified by a We define subresource to be either a whole buffer, or a [=texture subresource=]. -Some [=internal usage=]s are compatible with others. -That means an implementation can consider multiple usages active at the same time. -There is a limited set of allowed usage multisets, where each usage is compatible with the other: - - {[=internal usage/input=] | [=internal usage/constant=] | [=internal usage/storage-read=]} - in any combination - - {[=internal usage/storage=] | [=internal usage/storage-read=]} - in any combination - - {[=internal usage/storage-write=]} - used one or more times - - [=internal usage/attachment=] - singular usage - - {[=internal usage/attachment-read=] | [=internal usage/storage-read=] | [=internal usage/constant=]} - in any combination - -A multi-set differentiates between an `[=internal usage=]` included once versus multiple times. -This difference is critical for [=internal usage/attachment=], -which can't be used multiple times in the same render pass for the same [=texture subresource=]. - -Enforcing that the usages are only combined into one of the [=allowed usage multiset=]s +Some [=internal usage=]s are compatible with others. A [=subresource=] can be in a state +that combines multiple usages together. We consider a list |U| to be +a compatible usage list if (and only if) it satisfies any of the following rules: + - Each usage in |U| is [=internal usage/input=], [=internal usage/constant=], or [=internal usage/storage-read=]. + - Each usage in |U| is [=internal usage/storage=] or [=internal usage/storage-read=]. + - Each usage in |U| is [=internal usage/storage-write=]. + - Each usage in |U| is [=internal usage/attachment-read=], [=internal usage/storage-read=], or [=internal usage/constant=]. + - |U| contains exactly one element: [=internal usage/attachment=]. + +Enforcing that the usages are only combined into a [=compatible usage list=] allows the API to limit when data races can occur in working with memory. That property makes applications written against WebGPU more likely to run without modification on different platforms. @@ -658,13 +654,13 @@ into the new state. In some cases, like within an open {{GPURenderPassEncoder}}, transition is impossible due to the hardware limitations. We define these places as usage scopes. -The **main usage rule** is, for any one [=subresource=], its set of [=internal usages=] -within one [=usage scope=] must be a subset of at least one of the [=allowed usage multisets=]. +The **main usage rule** is, for any one [=subresource=], its list of [=internal usages=] +within one [=usage scope=] must be a [=compatible usage list=]. For example, binding the same buffer for [=internal usage/storage=] as well as for [=internal usage/input=] within the same {{GPURenderPassEncoder}} would put the encoder as well as the owning {{GPUCommandEncoder}} into the error state. -There is no [=allowed usage multiset=] that contains this combination. +This combination of usages does not make a [=compatible usage list=]. The [=subresources=] of textures included in the views provided to {{GPURenderPassColorAttachmentDescriptor/attachment|GPURenderPassColorAttachmentDescriptor.attachment}} and @@ -714,9 +710,9 @@ regardless of whether the indexed draw calls are used afterwards. The [=usage scopes=] are validated at {{GPUCommandEncoder/finish()|GPUCommandEncoder.finish}} time. The implementation performs the usage scope validation by composing -the set of all [=internal usage=] flags of each [=subresource=] used in the [=usage scope=]. +the list of all [=internal usage=] flags of each [=subresource=] used in the [=usage scope=]. A {{GPUValidationError}} is generated in the current scope with an appropriate error message -if that set is not within any of the [=allowed usage multiset=]s. +if that list is not a [=compatible usage list=]. ## Core Internal Objects ## {#core-internal-objects} @@ -2635,10 +2631,10 @@ A {{GPUBindGroup}} object has the following internal slots: :: The set of {{GPUBindGroupEntry}}s this {{GPUBindGroup}} describes. - : \[[usedResources]] of type map<[=subresource=], set<[=internal usage=]>>. + : \[[usedResources]] of type map<[=subresource=], list<[=internal usage=]>>. :: The set of buffer and texture [=subresource=]s used by this bind group, - associated with sets of the [=internal usage=] flags. + associated with lists of the [=internal usage=] flags.
From 3be85e2c4eb2710dca3043c0aa3d5deb6b149d15 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Tue, 18 Aug 2020 18:27:16 -0400 Subject: [PATCH 8/8] Wrap the main usage rule in an algorithm --- spec/index.bs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/spec/index.bs b/spec/index.bs index d202b06254..c5a66888f8 100644 --- a/spec/index.bs +++ b/spec/index.bs @@ -634,6 +634,7 @@ Each such texture subresource is uniquely identified by a We define subresource to be either a whole buffer, or a [=texture subresource=]. +
Some [=internal usage=]s are compatible with others. A [=subresource=] can be in a state that combines multiple usages together. We consider a list |U| to be a compatible usage list if (and only if) it satisfies any of the following rules: @@ -642,6 +643,7 @@ a compatible usage list if (and only if) it satisfies any of the - Each usage in |U| is [=internal usage/storage-write=]. - Each usage in |U| is [=internal usage/attachment-read=], [=internal usage/storage-read=], or [=internal usage/constant=]. - |U| contains exactly one element: [=internal usage/attachment=]. +
Enforcing that the usages are only combined into a [=compatible usage list=] allows the API to limit when data races can occur in working with memory.