Sitelet https://github.com/gpuweb/gpuweb/pull/761/files
Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 129 additions & 78 deletions spec/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,9 @@ GPUBuffer includes GPUObjectBase;
so they can be detached when {{unmap}} is called.
</dl>

Issue: {{GPUBuffer/[[usage]]}} is differently named from {{GPUTexture/[[textureUsage]]}}.
We should make it consistent.

Each {{GPUBuffer}} has a current <dfn dfn>buffer state</dfn> on the [=Content timeline=]
which is one of the following:

Expand Down Expand Up @@ -3109,19 +3112,19 @@ dictionary GPUCommandEncoderDescriptor : GPUObjectDescriptorBase {

## Copy Commands ## {#copy-commands}

### <dfn dictionary>GPUBufferCopyView</dfn> ### {#gpu-buffer-copy-view}
### <dfn dictionary>GPUTextureDataLayout</dfn> ### {#gpu-texture-data-layout}

<script type=idl>
dictionary GPUBufferCopyView {
required GPUBuffer buffer;
dictionary GPUTextureDataLayout {
GPUSize64 offset = 0;
required GPUSize32 bytesPerRow;
GPUSize32 rowsPerImage = 0;
};
</script>

A {{GPUBufferCopyView}} is a view of a [=buffer=] as an array of <dfn dfn>images</dfn>,
used when copying data between a [=texture=] and a [=buffer=].
A {{GPUTextureDataLayout}} is a layout of <dfn dfn>images</dfn> within some linear memory.
It's used when copying data between a [=texture=] and a [=buffer=], or when scheduling a
write into a [=texture=] from the {{GPUQueue}}.

- For {{GPUTextureDimension/2d}} textures, data is copied between one or multiple contiguous [=images=] and [=array layers=].
- For {{GPUTextureDimension/3d}} textures, data is copied between one or multiple contiguous [=images=] and depth [=slices=].
Expand All @@ -3130,25 +3133,39 @@ Issue: Define images more precisely. In particular, define them as being compris

Issue: Define the exact copy semantics, by reference to common algorithms shared by the copy methods.

<dl dfn-type=dict-member dfn-for=GPUBufferCopyView>
<dl dfn-type=dict-member dfn-for=GPUTextureDataLayout>
: <dfn>bytesPerRow</dfn>
::
The stride, in bytes, between the beginning of each row of [=texel blocks=] and the subsequent row.

: <dfn>rowsPerImage</dfn>
::
{{GPUBufferCopyView/rowsPerImage}} &divide; [=texel block height=] &times;
{{GPUBufferCopyView/bytesPerRow}} is the stride, in bytes, between the beginning of each [=image=]
{{GPUTextureDataLayout/rowsPerImage}} &divide; [=texel block height=] &times;
{{GPUTextureDataLayout/bytesPerRow}} is the stride, in bytes, between the beginning of each [=image=]
of data and the subsequent [=image=].
</dl>

### <dfn dictionary>GPUBufferCopyView</dfn> ### {#gpu-buffer-copy-view}

<script type=idl>
dictionary GPUBufferCopyView : GPUTextureDataLayout {
required GPUBuffer buffer;
};
</script>

A {{GPUBufferCopyView}} contains the actual [=texture=] data placed in a [=buffer=] according to {{GPUTextureDataLayout}}.

<div algorithm class=validusage>
<dfn abstract-op>validating GPUBufferCopyView</dfn>

**Arguments:**
- {{GPUBufferCopyView}} |bufferCopyView|

<dfn abstract-op>GPUBufferCopyView Valid Usage</dfn>
**Returns:** boolean

Given a {{GPUBufferCopyView}} |bufferCopyView|, the following validation rules apply:
- |bufferCopyView|.{{GPUBufferCopyView/buffer}} must be a [=valid=] {{GPUBuffer}}.
- |bufferCopyView|.{{GPUBufferCopyView/bytesPerRow}} must be a multiple of 256.
Return true if and only if all of the following conditions apply:
- |bufferCopyView|.{{GPUBufferCopyView/buffer}} must be a [=valid=] {{GPUBuffer}}.
- |bufferCopyView|.{{GPUTextureDataLayout/bytesPerRow}} must be a multiple of 256.

</div>

Expand All @@ -3168,14 +3185,18 @@ offset {{GPUOrigin3D}} in texels, used when copying data from or to a {{GPUTextu
* {{GPUTextureCopyView/origin}}: If unspecified, defaults to `[0, 0, 0]`.

<div algorithm class=validusage>
<dfn abstract-op>validating GPUTextureCopyView</dfn>

**Arguments:**
- {{GPUTextureCopyView}} |textureCopyView|

<dfn abstract-op>GPUTextureCopyView Valid Usage</dfn>
**Returns:** boolean

Given a {{GPUTextureCopyView}} |textureCopyView|, let
Let:
- |blockWidth| be the [=texel block width=] of |textureCopyView|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}.
- |blockHeight| be the [=texel block height=] of |textureCopyView|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}.

The following validation rules apply:
Return true if and only if all of the following conditions apply:
- |textureCopyView|.{{GPUTextureCopyView/texture}} must be a [=valid=] {{GPUTexture}}.
- |textureCopyView|.{{GPUTextureCopyView/mipLevel}} must be less than the {{GPUTexture/[[mipLevelCount]]}} of
|textureCopyView|.{{GPUTextureCopyView/texture}}.
Expand Down Expand Up @@ -3266,49 +3287,52 @@ and {{GPUCommandEncoder/copyTextureToBuffer()}}.

</div>

<div algorithm class=validusage>
Issue: define this as an algorithm with (texture, mipmapLevel) parameters and use the call syntax instead of referring to the definition by label.

<dfn dfn>Valid Buffer Copy Range</dfn>

Given a {{GPUBufferCopyView}} |bufferCopyView|, a {{GPUTextureFormat}} |format| and a {{GPUExtent3D}}
|copySize|, let
- |blockWidth| be the [=texel block width=] of |format|.
- |blockHeight| be the [=texel block height=] of |format|.
- |blockSize| be the [=texel block size=] of |format|.
- |bytesInACompleteRow| be |blockSize| &times; |copySize|.[=Extent3D/width=] &div; |blockWidth|.
- |bytesInACompleteImage| be |bytesInACompleteRow| &times; |copySize|.[=Extent3D/height=] &div; |blockHeight|.
- |requiredBytesInCopy| be calculated with the following algorithm assuming all the parameters are [=valid=]:
```
if (copySize.width == 0 || copySize.height == 0 || copySize.depth == 0) {
requiredBytesInCopy = 0;
} else {
GPUSize64 texelBlockRowsPerImage = bufferCopyView.rowsPerImage / blockHeight;
GPUSize64 bytesPerImage = bufferCopyView.bytesPerRow * texelBlockRowsPerImage;
GPUSize64 bytesInLastSlice =
bufferCopyView.bytesPerRow * (copySize.height / blockHeight - 1) + (copySize.width / blockWidth * blockSize);
requiredBytesInCopy = bytesPerImage * (copySize.depth - 1) + bytesInLastSlice;
}
```

The following validation rules apply:

For the copy being in-bounds:
- If |bufferCopyView|.{{GPUBufferCopyView/rowsPerImage}} is not 0, it must be greater than or equal to
|copySize|.[=Extent3D/height=].
- (|bufferCopyView|.{{GPUBufferCopyView/offset}} + |requiredBytesInCopy|) must not overflow a {{GPUSize64}}.
- (|bufferCopyView|.{{GPUBufferCopyView/offset}} + |requiredBytesInCopy|) must be smaller than or equal to
|bufferCopyView|.{{GPUBufferCopyView/buffer}}.{{GPUBuffer/[[size]]}}.

For the texel block alignments:
- |bufferCopyView|.{{GPUBufferCopyView/rowsPerImage}} must be a multiple of |blockHeight|.
- |bufferCopyView|.{{GPUBufferCopyView/offset}} must be a multiple of |blockSize|.

For other members in |bufferCopyView|:
- If |copySize|.[=Extent3D/height=] is greater than 1:
- |bufferCopyView|.{{GPUBufferCopyView/bytesPerRow}} must be greater than or equal to the number of |bytesInACompleteRow|.
- If |copySize|.[=Extent3D/depth=] is greater than 1:
- |bufferCopyView|.{{GPUBufferCopyView/rowsPerImage}} must be greater than or equal to the number of |bytesInACompleteImage|.
<div algorithm class=validusage>
<dfn abstract-op>validating linear texture data</dfn>(layout, byteSize, format, copyExtent)
Comment thread
kainino0x marked this conversation as resolved.

**Arguments:**
- {{GPUTextureDataLayout}} |layout| of the linear texture data
- {{GPUSize64}} |byteSize| - total size of the linear data, in bytes
- {{GPUTextureFormat}} |format| of the texture
- {{GPUExtent3D}} |copyExtent| - extent of the texture to copy

Let:
- |blockWidth| be the [=texel block width=] of |format|.
- |blockHeight| be the [=texel block height=] of |format|.
- |blockSize| be the [=texel block size=] of |format|.
- |bytesInACompleteRow| be |blockSize| &times; |copyExtent|.[=Extent3D/width=] &div; |blockWidth|.
- |requiredBytesInCopy| be calculated with the following algorithm assuming all the parameters are [=valid=]:
```
if (copyExtent.width == 0 || copyExtent.height == 0 || copyExtent.depth == 0) {
requiredBytesInCopy = 0;
} else {
GPUSize64 texelBlockRowsPerImage = layout.rowsPerImage / blockHeight;
GPUSize64 bytesPerImage = layout.bytesPerRow * texelBlockRowsPerImage;
GPUSize64 bytesInLastSlice =
layout.bytesPerRow * (copyExtent.height / blockHeight - 1) + (copyExtent.width / blockWidth * blockSize);
requiredBytesInCopy = bytesPerImage * (copyExtent.depth - 1) + bytesInLastSlice;
}
```

The following validation rules apply:

For the copy being in-bounds:
- If |layout|.{{GPUTextureDataLayout/rowsPerImage}} is not 0, it must be greater than or equal to
|copyExtent|.[=Extent3D/height=].
- (|layout|.{{GPUTextureDataLayout/offset}} + |requiredBytesInCopy|) must not overflow a {{GPUSize64}}.
- (|layout|.{{GPUTextureDataLayout/offset}} + |requiredBytesInCopy|) must be smaller than or equal to |byteSize|.

For the texel block alignments:
- |layout|.{{GPUTextureDataLayout/rowsPerImage}} must be a multiple of |blockHeight|.
- |layout|.{{GPUTextureDataLayout/offset}} must be a multiple of |blockSize|.

For other members in |layout|:
- If |copyExtent|.[=Extent3D/height=] is greater than 1:
- |layout|.{{GPUTextureDataLayout/bytesPerRow}} must be greater than or equal to the number of |bytesInACompleteRow|.
- If |copyExtent|.[=Extent3D/depth=] is greater than 1:
- |layout|.{{GPUTextureDataLayout/rowsPerImage}} must be greater than or equal to |copyExtent|.[=Extent3D/height=].
</div>

<div algorithm class=validusage>
Expand Down Expand Up @@ -3345,6 +3369,8 @@ Issue(gpuweb/gpuweb#537): Additional restrictions on rowsPerImage if needed.
Issue(gpuweb/gpuweb#652): Define the copies with {{GPUTextureFormat/"depth24plus"}} and
{{GPUTextureFormat/"depth24plus-stencil8"}}.

Issue: convert "Valid Texture Copy Range" into an algorithm with parameters, similar to "validating linear texture data"

#### <dfn method for=GPUCommandEncoder>copyBufferToTexture(source, destination, copySize)</dfn> #### {#GPUCommandEncoder-copyBufferToTexture}

<div algorithm="GPUCommandEncoder.copyBufferToTexture">
Expand Down Expand Up @@ -3376,18 +3402,17 @@ Given a {{GPUCommandEncoder}} |encoder| and the arguments {{GPUBufferCopyView}}
- |encoder|.{{GPUCommandEncoder/[[state]]}} must be {{encoder state/open}}.

For |source|:
- |source| must be [=valid=].
- [$validating GPUBufferCopyView$](|source|) returns true.
- |source|.{{GPUBufferCopyView/buffer}}.{{GPUBuffer/[[usage]]}} must contain {{GPUBufferUsage/COPY_SRC}}.

For |destination|:
- |destination| must be [=valid=].
- [$validating GPUTextureCopyView$](|destination|) returns true.
- |destination|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[textureUsage]]}} must contain
{{GPUTextureUsage/COPY_DST}}.
- |destination|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[sampleCount]]}} must be 1.

For the copy ranges:
- [=Valid Buffer Copy Range=] applies to |source|, |destination|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}
and |copySize|.
- [$validating linear texture data$](|source|, |source|.{{GPUBufferCopyView/buffer}}.{{GPUBuffer/[[size]]}}, |destination|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}, |copySize|) succeeds.
- [=Valid Texture Copy Range=] applies to |destination| and |copySize|.

</div>
Expand Down Expand Up @@ -3423,18 +3448,17 @@ Given a {{GPUCommandEncoder}} |encoder| and the arguments {{GPUTextureCopyView}}
- |encoder|.{{GPUCommandEncoder/[[state]]}} must be {{encoder state/open}}.

For |source|:
- |source| must be [=valid=].
- [$validating GPUTextureCopyView$](|source|) returns true.
- |source|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[textureUsage]]}} must contain
{{GPUTextureUsage/COPY_SRC}}.
- |source|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[sampleCount]]}} must be 1.

For |destination|:
- |destination| must be [=valid=].
- [$validating GPUBufferCopyView$](|destination|) returns true.
- |destination|.{{GPUBufferCopyView/buffer}}.{{GPUBuffer/[[usage]]}} must contain {{GPUBufferUsage/COPY_DST}}.

For the copy ranges:
- [=Valid Buffer Copy Range=] applies to |destination|, |source|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}
and |copySize|.
- [$validating linear texture data$](|destination|, |destination|.{{GPUBufferCopyView/buffer}}.{{GPUBuffer/[[size]]}}, |source|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}, |copySize|) succeeds.
- [=Valid Texture Copy Range=] applies to |source| and |copySize|.

</div>
Expand Down Expand Up @@ -3477,12 +3501,12 @@ The following validation rules apply:
- |encoder|.{{GPUCommandEncoder/[[state]]}} must be {{encoder state/open}}.

For |source|:
- |source| must be [=valid=].
- [$validating GPUTextureCopyView$](|source|) returns true.
- |source|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[textureUsage]]}} must contain
{{GPUTextureUsage/COPY_SRC}}.

For |destination|:
- |destination| must be [=valid=].
- [$validating GPUTextureCopyView$](|destination|) returns true.
- |destination|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[textureUsage]]}} must contain
{{GPUTextureUsage/COPY_DST}}.

Expand Down Expand Up @@ -3745,6 +3769,12 @@ interface GPUQueue {
GPUSize64 destinationOffset,
GPUSize64 size);

void writeTexture(
ArrayBuffer sourceData,
GPUTextureDataLayout sourceLayout,
GPUTextureCopyView destination,
GPUExtent3D size);

void copyImageBitmapToTexture(
GPUImageBitmapCopyView source,
GPUTextureCopyView destination,
Expand All @@ -3754,24 +3784,45 @@ GPUQueue includes GPUObjectBase;
</script>

<dl dfn-type="method" dfn-for="GPUQueue">
: <dfn>writeBuffer(sourceData, sourceOffset, destination, destinationOffset, size)</dfn>
<div algorithm>
: <dfn>writeBuffer(|sourceData|, |sourceOffset|, |destination|, |destinationOffset|, |size|)</dfn>
Comment thread
kainino0x marked this conversation as resolved.
::
Takes the `sourceData` contents of size `size`, starting from the byte offset `sourceOffset`,
and schedules a write operation of these contents to the `destination` buffer on the
[=Queue timeline=] starting at `destinationOffset`.
Any subsequent modifications to `sourceData` do not affect what is written
Takes the |sourceData| contents of size |size|, starting from the byte offset |sourceOffset|,
and schedules a write operation of these contents to the |destination| buffer on the
[=Queue timeline=] starting at |destinationOffset|.
Any subsequent modifications to |sourceData| do not affect what is written
at the time that the scheduled operation runs.

The operation throws {{OperationError}} if any of the following is true:
- `destination` buffer isn't in the `"unmapped"` [=buffer state=].
- `destinationOffset` is not a multiple of 4.
- `size` is not a positive multiple of 4.
- `sourceOffset + size` exceeds `sourceData.byteLength`.
- |destination| buffer isn't in the `"unmapped"` [=buffer state=].
- |destinationOffset| is not a multiple of 4.
- |size| is not a positive multiple of 4.
- |sourceOffset| + |size| exceeds |sourceData|.byteLength.

The operation does nothing and produces an error if any of the following is true:
- `destination` buffer wasn't created with {{GPUBufferUsage/COPY_DST}} flag in {{GPUBufferDescriptor/usage}}.
- `destination` buffer is destroyed
- `destinationOffset + size` exceeds the {{GPUBufferDescriptor/size}} of the `destination` buffer.
- |destination|.{{GPUBuffer/[[usage]]}} doesn't include {{GPUBufferUsage/COPY_DST}} flag.
- |destination| buffer is destroyed
- |destinationOffset| + |size| exceeds |destination|.{{GPUBuffer/[[size]]}}.
</div>

<div algorithm>
: <dfn>writeTexture(|sourceData|, |sourceLayout|, |destination|, |size|)</dfn>
::
Takes the |sourceData| contents and schedules a write operation of these contents to the
|destination| texture copy view in the queue.
Any subsequent modifications to |sourceData| do not affect what is written
at the time that the scheduled operation runs.
The operation does nothing and produces an error if any of the following is true:

- |destination|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[textureUsage]]}}
doesn't include {{GPUTextureUsage/COPY_DST}} flag.
- |destination|.{{GPUTextureCopyView/texture}} is destroyed
- [$validating linear texture data$](|sourceLayout|, |sourceData|.byteLength, |destination|.{{GPUTextureCopyView/texture}}.{{GPUTexture/[[format]]}}, |size|) fails.
- [=Valid Texture Copy Range=] fails to apply to |destination| and |size|.

Note: unlike {{GPUCommandEncoder/copyBufferToTexture()|GPUCommandEncoder.copyBufferToTexture}},
there is no alignment requirement on |sourceLayout|.{{GPUTextureDataLayout/bytesPerRow}}.
</div>

: <dfn>copyImageBitmapToTexture(source, destination, copySize)</dfn>
::
Expand Down