Skip to content
Open
Changes from 1 commit
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
Prev Previous commit
Split "buffer-map-extended-usages" into three features
  • Loading branch information
Jiawei-Shao committed Apr 8, 2025
commit 44266f8236ad2fcc041ba8418240ae3370f830a4
140 changes: 82 additions & 58 deletions spec/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -2882,7 +2882,9 @@ enum GPUFeatureName {
"clip-distances",
"dual-source-blending",
"subgroups",
"buffer-map-extended-usages",
"buffer-map-write-with-extended-usages",
"buffer-map-write-with-extended-usages-and-gpu-data",
"buffer-map-read-with-extended-usages",
};
</script>

Expand Down Expand Up @@ -3041,17 +3043,6 @@ to.
<!-- As needed, compute more allowed usages based on the features enabled on the device. -->
</div>

<div algorithm data-timeline=const>
A {{GPUDevice}}'s <dfn dfn>GPU-writable buffer usages</dfn> are:

- Always allowed:
{{GPUBufferUsage/COPY_DST}},
{{GPUBufferUsage/STORAGE}},
{{GPUBufferUsage/QUERY_RESOLVE}}

<!-- As needed, compute more allowed usages based on the features enabled on the device. -->
</div>

## Example ## {#initialization-examples}

<div class=example>
Expand Down Expand Up @@ -3363,16 +3354,21 @@ The {{GPUBufferUsage}} flags determine how a {{GPUBuffer}} may be used after its
The buffer can be mapped for reading. (Example: calling {{GPUBuffer/mapAsync()}} with
{{GPUMapMode/READ|GPUMapMode.READ}})

May only be combined with {{GPUBufferUsage/COPY_DST}} when
{{GPUFeatureName/buffer-map-extended-usages}} is not enabled.
Unless {{GPUFeatureName/buffer-map-read-with-extended-usages}} is enabled, this may only be
combined with {{GPUBufferUsage/COPY_DST}}.

: <dfn>MAP_WRITE</dfn>
::
The buffer can be mapped for writing. (Example: calling {{GPUBuffer/mapAsync()}} with
{{GPUMapMode/WRITE|GPUMapMode.WRITE}})

May only be combined with {{GPUBufferUsage/COPY_SRC}} when
{{GPUFeatureName/buffer-map-extended-usages}} is not enabled.
Unless {{GPUFeatureName/buffer-map-write-with-extended-usages}} is enabled, this may only be
combined with {{GPUBufferUsage/COPY_SRC}}.

When {{GPUFeatureName/buffer-map-write-with-extended-usages}} is enabled:
- This cannot be combined with {{GPUBufferUsage/INDEX}} or {{GPUBufferUsage/INDIRECT}}.
- This cannot be combined with {{GPUBufferUsage/MAP_READ}} unless
{{GPUFeatureName/buffer-map-read-with-extended-usages}} is enabled.

: <dfn>COPY_SRC</dfn>
::
Expand Down Expand Up @@ -3467,17 +3463,31 @@ The {{GPUBufferUsage}} flags determine how a {{GPUBuffer}} may be used after its
- |descriptor|.{{GPUBufferDescriptor/usage}} must not be 0.
- |descriptor|.{{GPUBufferDescriptor/usage}} must be a subset of the
[=allowed buffer usages=] for |this|.
- If {{GPUFeatureName/buffer-map-extended-usages}} is not enabled on |this|:
- If |descriptor|.{{GPUBufferDescriptor/usage}} contains {{GPUBufferUsage/MAP_READ}}:
- |descriptor|.{{GPUBufferDescriptor/usage}} must contain no other flags
except {{GPUBufferUsage/COPY_DST}}.
- If |descriptor|.{{GPUBufferDescriptor/usage}} contains {{GPUBufferUsage/MAP_WRITE}}:
- |descriptor|.{{GPUBufferDescriptor/usage}} must contain no other flags
except {{GPUBufferUsage/COPY_SRC}}.
- If |descriptor|.{{GPUBufferDescriptor/usage}} contains
{{GPUBufferUsage/MAP_WRITE}}:
- If {{GPUFeatureName/buffer-map-write-with-extended-usages}} is not
enabled on |this|:
- |descriptor|.{{GPUBufferDescriptor/usage}} must contain no other
flags except {{GPUBufferUsage/COPY_SRC}}.
- Else:
- |descriptor|.{{GPUBufferDescriptor/usage}} must not contain
{{GPUBufferUsage/INDEX}} or {{GPUBufferUsage/INDIRECT}}.
- If |descriptor|.{{GPUBufferDescriptor/usage}} contains
{{GPUBufferUsage/MAP_READ}}:
- If {{GPUFeatureName/buffer-map-read-with-extended-usages}} is not
enabled on |this|:
- |descriptor|.{{GPUBufferDescriptor/usage}} must contain no other
flags except {{GPUBufferUsage/COPY_DST}}.
- If |descriptor|.{{GPUBufferDescriptor/size}} must be &le;
|this|.{{GPUObjectBase/[[device]]}}.{{device/[[limits]]}}.{{supported limits/maxBufferSize}}.
</div>

Note: {{GPUBufferUsage/MAP_WRITE}} is not allowed to work with
{{GPUBufferUsage/INDEX}} or {{GPUBufferUsage/INDIRECT}} because the data in the
buffers with {{GPUBufferUsage/INDEX}} or {{GPUBufferUsage/INDIRECT}} usage may be
validated on the GPU, and allowing updating such buffer on the CPU side may cause
potential TOCTOU attacks in a compromised JavaScript process.

Note: If buffer creation fails, and |descriptor|.{{GPUBufferDescriptor/mappedAtCreation}} is `false`,
any calls to {{GPUBuffer/mapAsync()}} will reject, so any resources allocated to enable mapping can
and may be discarded or recycled.
Expand Down Expand Up @@ -3597,42 +3607,32 @@ The {{GPUMapMode}} flags determine how a {{GPUBuffer}} is mapped when calling
<dl dfn-type=const dfn-for=GPUMapMode>
: <dfn>READ</dfn>
::
Only valid with buffers created with the {{GPUBufferUsage/MAP_READ}} usage.
Only valid with {{GPUBuffer}}s created with the {{GPUBufferUsage/MAP_READ}} usage.

Once the buffer is mapped, calls to {{GPUBuffer/getMappedRange()}} will return an
{{ArrayBuffer}} containing the buffer's current values.
Once the {{GPUBuffer}} is mapped, calls to {{GPUBuffer/getMappedRange()}} will return an
{{ArrayBuffer}} containing the {{GPUBuffer}}'s current values.

Changes to the returned {{ArrayBuffer}} will be discarded after {{GPUBuffer/unmap()}} is
called.

: <dfn>WRITE</dfn>
::
Only valid with buffers created with the {{GPUBufferUsage/MAP_WRITE}} usage.

When the buffer is created without [=GPU-writable buffer usages=]:
Once the buffer is mapped, calls to {{GPUBuffer/getMappedRange()}} will return an
{{ArrayBuffer}} containing the buffer’s current values.
Only valid with {{GPUBuffer}}s created with the {{GPUBufferUsage/MAP_WRITE}} usage.

When the buffer is created with [=GPU-writable buffer usages=]:
Once the buffer is mapped, calls to {{GPUBuffer/getMappedRange()}} will return an
{{ArrayBuffer}} containing the default initialized data (zeros) or data written by the
webpage during a previous mapping.
Once the buffer is mapped:
- If {{GPUFeatureName/buffer-map-write-with-extended-usages-and-GPU-data}} is enabled:
- Calls to {{GPUBuffer/getMappedRange()}} will return an {{ArrayBuffer}} containing the
{{GPUBuffer}}'s current values.
- Else:
- Calls to {{GPUBuffer/getMappedRange()}} will return an {{ArrayBuffer}} containing
the default initialized data (zeros) or data written by the webpage during a
previous mapping.

Changes to the returned {{ArrayBuffer}} will be stored in the buffer after
Changes to the returned {{ArrayBuffer}} will be stored in the {{GPUBuffer}} after
{{GPUBuffer/unmap()}} is called.

Note: Write-only mapping will never return values produced by the GPU.

: <dfn>READ|WRITE</dfn>
::
Only valid with buffers created with the {{GPUBufferUsage/MAP_READ}} and
{{GPUBufferUsage/MAP_WRITE}} usage.

Once the buffer is mapped, calls to {{GPUBuffer/getMappedRange()}} will return an
{{ArrayBuffer}} containing the buffer's current values.

Changes to the returned {{ArrayBuffer}} will be stored in the buffer after
{{GPUBuffer/unmap()}} is called.
Note: Write-only mapping will never return values produced by the GPU unless
{{GPUFeatureName/buffer-map-write-with-extended-usages-and-GPU-data}} is enabled.

</dl>

Expand Down Expand Up @@ -3717,8 +3717,7 @@ The {{GPUMapMode}} flags determine how a {{GPUBuffer}} is mapped when calling
- |rangeSize| is a multiple of 4.
- |offset| + |rangeSize| &le; |this|.{{GPUBuffer/size}}
- |mode| contains only bits defined in {{GPUMapMode}}.
- If {{GPUFeatureName/buffer-map-extended-usages}} is not enabled on |this|.device:
- |mode| contains exactly one of {{GPUMapMode/READ}} or {{GPUMapMode/WRITE}}.
- |mode| contains exactly one of {{GPUMapMode/READ}} or {{GPUMapMode/WRITE}}.
- If |mode| contains {{GPUMapMode/READ}} then |this|.{{GPUBuffer/usage}} must contain {{GPUBufferUsage/MAP_READ}}.
- If |mode| contains {{GPUMapMode/WRITE}} then |this|.{{GPUBuffer/usage}} must contain {{GPUBufferUsage/MAP_WRITE}}.
</div>
Expand Down Expand Up @@ -16756,20 +16755,45 @@ expose real values whenever the feature is available on the adapter:
- New WGSL extensions:
- [=extension/subgroups=]

<h3 id=dom-gpufeaturename-buffer-map-extended-usages data-dfn-type=enum-value data-dfn-for=GPUFeatureName>`"buffer-map-extended-usages"`
<h3 id=dom-gpufeaturename-buffer-map-write-with-extended-usages data-dfn-type=enum-value data-dfn-for=GPUFeatureName>`"buffer-map-write-with-extended-usages"`
</h3>

Allows the creation of {{GPUBuffer}}s with {{GPUBufferUsage/MAP_WRITE}} combined with more
{{GPUBufferUsage}} flags besides {{GPUBufferUsage/COPY_SRC}} on the GPUs that support uploading data
to GPU without a staging buffer.

This feature adds the following [=optional API surfaces=]:
- Allows the use of {{GPUBufferUsage/MAP_WRITE}} with any other {{GPUBufferUsage}}s listed below as
|descriptor|.{{GPUBufferDescriptor/usage}} in the creation of {{GPUBuffer}}s:
- {{GPUBufferUsage/COPY_DST}}
- {{GPUBufferUsage/VERTEX}}
- {{GPUBufferUsage/UNIFORM}}
- {{GPUBufferUsage/STORAGE}}
- {{GPUBufferUsage/QUERY_RESOLVE}}

<h3 id=dom-gpufeaturename-buffer-map-write-with-extended-usages-and-GPU-data data-dfn-type=enum-value data-dfn-for=GPUFeatureName>`"buffer-map-write-with-extended-usages-and-GPU-data"`
</h3>

Allows the creation of mappable {{GPUBuffer}}s with any other {{GPUBufferUsage}} flags, and allows
setting both {{GPUMapMode/READ}} and {{GPUMapMode/WRITE}} bits as a valid map mode in
{{GPUBuffer}}.{{GPUBuffer/mapAsync()}}.
Allows the creation of {{GPUBuffer}}s with {{GPUBufferUsage/MAP_WRITE}} combined with more
{{GPUBufferUsage}} flags besides {{GPUBufferUsage/COPY_SRC}}, and directly reading the data on the
GPU with {{GPUBuffer/getMappedRange()}} on the GPUs that support uploading data to GPU without a
staging buffer and take advantage of CPU-cached memory.

This feature adds the following [=optional API surfaces=]:
- Enable {{GPUFeatureName/buffer-map-write-with-extended-usages}}
- Calls to {{GPUBuffer/getMappedRange()}} will return an {{ArrayBuffer}} containing the
{{GPUBuffer}}'s current values.

<h3 id=dom-gpufeaturename-buffer-map-read-with-extended-usages data-dfn-type=enum-value data-dfn-for=GPUFeatureName>`"buffer-map-read-with-extended-usages"`
</h3>

Allows the creation of {{GPUBuffer}}s with {{GPUBufferUsage/MAP_READ}} combined with
{{GPUBufferUsage}} flags besides {{GPUBufferUsage/COPY_DST}} on the GPUs that take advantage of
CPU-cached memory.

This feature adds the following [=optional API surfaces=]:
- Allows the use of {{GPUBufferUsage/MAP_READ}} with any other {{GPUBufferUsage}} flags as
|descriptor|.{{GPUBufferDescriptor/usage}} in the creation of {{GPUBuffer}}s.
- Allows the use of {{GPUBufferUsage/MAP_WRITE}} with any other {{GPUBufferUsage}} flags as
|descriptor|.{{GPUBufferDescriptor/usage}} in the creation of {{GPUBuffer}}s.
- Allows setting both {{GPUMapMode/READ}} and {{GPUMapMode/WRITE}} bits in the `mode` parameter of
{{GPUBuffer}}.{{GPUBuffer/mapAsync()}}.

# Appendices # {#appendices}

Expand Down