Skip to content

Commit a2da5f3

Browse files
authored
Add Read/WriteMappedRange (#494)
* Add Read/WriteMappedRange, and disallow ALL map overlaps * performance docs * Partial revert so that overlaps are unvalidated in native * WriteMappedRange const pointer * clarify that WGPU_WHOLE_MAP_SIZE is not used here * fix lint
1 parent 17f2f1c commit a2da5f3

File tree

3 files changed

+154
-17
lines changed

3 files changed

+154
-17
lines changed

doc/articles/BufferMapping.md

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
# Buffer Mapping {#BufferMapping}
22

3-
## GetMappedRange/GetConstMappedRange Behavior {#GetMappedRangeBehavior}
3+
## Mapped Range Behavior {#MappedRangeBehavior}
44

5-
@ref wgpuBufferGetMappedRange and @ref wgpuBufferGetConstMappedRange...:
5+
The @ref wgpuBufferGetMappedRange, @ref wgpuBufferGetConstMappedRange, @ref wgpuBufferReadMappedRange, and @ref wgpuBufferWriteMappedRange methods:
66

7-
- Return `NULL` with @ref ImplementationDefinedLogging if:
8-
- There is any content-timeline error, as defined in the WebGPU specification for `getMappedRange()` (buffer is not mapped, alignment constraints, overlaps, etc.)
7+
- Fail (return `NULL` or `WGPUStatus_Error`) with @ref ImplementationDefinedLogging if:
8+
- There is any content-timeline error, as defined in the WebGPU specification for `getMappedRange()`, given the same buffer, offset, and size (buffer is not mapped, alignment constraints, overlaps, etc.)
99
- **Except** for overlaps between *const* ranges, which are allowed in C *in non-Wasm targets only*.
10-
(Wasm does not allow this because const ranges do not exist in JS.)
11-
- @ref wgpuBufferGetMappedRange is called, but the buffer is not mapped with @ref WGPUMapMode_Write.
10+
(Wasm does not allow this because const ranges do not exist in JS.
11+
All of these calls are implemented on top of `getMappedRange()`.)
12+
- @ref wgpuBufferGetMappedRange or @ref wgpuBufferWriteMappedRange is called, but the buffer is not mapped with @ref WGPUMapMode_Write.
13+
14+
@ref wgpuBufferGetMappedRange, @ref wgpuBufferGetConstMappedRange additionally:
15+
1216
- Do not guarantee they will return any particular address value relative to another GetMappedRange call.
1317
- Guarantee that the mapped pointer will be aligned to 16 bytes if the `MapAsync` and `GetMappedRange` offsets are also aligned to 16 bytes.
1418

1519
More specifically: `GetMappedRange pointer` and `MapAsync offset + GetMappedRange offset` must be _congruent modulo_ `16`.
1620

17-
- Implementations **should** try to guarantee better alignments (as large as 256 bytes) if possible without significant runtime overhead (e.g. allocating new memory and copying data).
21+
- Implementations **should** try to guarantee better alignments (as large as 256 bytes), if they can do so without significant runtime overhead (i.e. without allocating new memory and copying data).

webgpu.h

+74-4
Original file line numberDiff line numberDiff line change
@@ -4554,6 +4554,11 @@ typedef WGPUBufferUsage (*WGPUProcBufferGetUsage)(WGPUBuffer buffer) WGPU_FUNCTI
45544554
* > @copydoc wgpuBufferMapAsync
45554555
*/
45564556
typedef WGPUFuture (*WGPUProcBufferMapAsync)(WGPUBuffer buffer, WGPUMapMode mode, size_t offset, size_t size, WGPUBufferMapCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE;
4557+
/**
4558+
* Proc pointer type for @ref wgpuBufferReadMappedRange:
4559+
* > @copydoc wgpuBufferReadMappedRange
4560+
*/
4561+
typedef WGPUStatus (*WGPUProcBufferReadMappedRange)(WGPUBuffer buffer, size_t offset, void * data, size_t size) WGPU_FUNCTION_ATTRIBUTE;
45574562
/**
45584563
* Proc pointer type for @ref wgpuBufferSetLabel:
45594564
* > @copydoc wgpuBufferSetLabel
@@ -4564,6 +4569,11 @@ typedef void (*WGPUProcBufferSetLabel)(WGPUBuffer buffer, WGPUStringView label)
45644569
* > @copydoc wgpuBufferUnmap
45654570
*/
45664571
typedef void (*WGPUProcBufferUnmap)(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE;
4572+
/**
4573+
* Proc pointer type for @ref wgpuBufferWriteMappedRange:
4574+
* > @copydoc wgpuBufferWriteMappedRange
4575+
*/
4576+
typedef WGPUStatus (*WGPUProcBufferWriteMappedRange)(WGPUBuffer buffer, size_t offset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE;
45674577
/**
45684578
* Proc pointer type for @ref wgpuBufferAddRef.
45694579
* > @copydoc wgpuBufferAddRef
@@ -5553,34 +5563,94 @@ WGPU_EXPORT void wgpuBufferDestroy(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE;
55535563
/**
55545564
* Returns a const pointer to beginning of the mapped range.
55555565
* It must not be written; writing to this range causes undefined behavior.
5556-
* See @ref GetMappedRangeBehavior for error conditions and guarantees.
5566+
* See @ref MappedRangeBehavior for error conditions and guarantees.
55575567
* This function is safe to call inside spontaneous callbacks (see @ref CallbackReentrancy).
55585568
*
5569+
* In Wasm, if `memcpy`ing from this range, prefer using @ref wgpuBufferReadMappedRange
5570+
* instead for better performance.
5571+
*
55595572
* @param offset
55605573
* Byte offset relative to the beginning of the buffer.
55615574
*
55625575
* @param size
5563-
* Byte size of the range to get. The returned pointer is valid for exactly this many bytes.
5576+
* Byte size of the range to get.
5577+
* If this is @ref WGPU_WHOLE_MAP_SIZE, it defaults to `buffer.size - offset`.
5578+
* The returned pointer is valid for exactly this many bytes.
55645579
*/
55655580
WGPU_EXPORT void const * wgpuBufferGetConstMappedRange(WGPUBuffer buffer, size_t offset, size_t size) WGPU_FUNCTION_ATTRIBUTE;
55665581
WGPU_EXPORT WGPUBufferMapState wgpuBufferGetMapState(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE;
55675582
/**
55685583
* Returns a mutable pointer to beginning of the mapped range.
5569-
* See @ref GetMappedRangeBehavior for error conditions and guarantees.
5584+
* See @ref MappedRangeBehavior for error conditions and guarantees.
55705585
* This function is safe to call inside spontaneous callbacks (see @ref CallbackReentrancy).
55715586
*
5587+
* In Wasm, if `memcpy`ing into this range, prefer using @ref wgpuBufferWriteMappedRange
5588+
* instead for better performance.
5589+
*
55725590
* @param offset
55735591
* Byte offset relative to the beginning of the buffer.
55745592
*
55755593
* @param size
5576-
* Byte size of the range to get. The returned pointer is valid for exactly this many bytes.
5594+
* Byte size of the range to get.
5595+
* If this is @ref WGPU_WHOLE_MAP_SIZE, it defaults to `buffer.size - offset`.
5596+
* The returned pointer is valid for exactly this many bytes.
55775597
*/
55785598
WGPU_EXPORT void * wgpuBufferGetMappedRange(WGPUBuffer buffer, size_t offset, size_t size) WGPU_FUNCTION_ATTRIBUTE;
55795599
WGPU_EXPORT uint64_t wgpuBufferGetSize(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE;
55805600
WGPU_EXPORT WGPUBufferUsage wgpuBufferGetUsage(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE;
5601+
/**
5602+
* @param offset
5603+
* Byte offset relative to beginning of the buffer.
5604+
*
5605+
* @param size
5606+
* Byte size of the region to map.
5607+
* If this is @ref WGPU_WHOLE_MAP_SIZE, it defaults to `buffer.size - offset`.
5608+
*/
55815609
WGPU_EXPORT WGPUFuture wgpuBufferMapAsync(WGPUBuffer buffer, WGPUMapMode mode, size_t offset, size_t size, WGPUBufferMapCallbackInfo callbackInfo) WGPU_FUNCTION_ATTRIBUTE;
5610+
/**
5611+
* Copies a range of data from the buffer mapping into the provided destination pointer.
5612+
* See @ref MappedRangeBehavior for error conditions and guarantees.
5613+
* This function is safe to call inside spontaneous callbacks (see @ref CallbackReentrancy).
5614+
*
5615+
* In Wasm, this is more efficient than copying from a mapped range into a `malloc`'d range.
5616+
*
5617+
* @param offset
5618+
* Byte offset relative to the beginning of the buffer.
5619+
*
5620+
* @param data
5621+
* Destination, to read buffer data into.
5622+
*
5623+
* @param size
5624+
* Number of bytes of data to read from the buffer.
5625+
* (Note @ref WGPU_WHOLE_MAP_SIZE is *not* accepted here.)
5626+
*
5627+
* @returns
5628+
* @ref WGPUStatus_Error if the copy did not occur.
5629+
*/
5630+
WGPU_EXPORT WGPUStatus wgpuBufferReadMappedRange(WGPUBuffer buffer, size_t offset, void * data, size_t size) WGPU_FUNCTION_ATTRIBUTE;
55825631
WGPU_EXPORT void wgpuBufferSetLabel(WGPUBuffer buffer, WGPUStringView label) WGPU_FUNCTION_ATTRIBUTE;
55835632
WGPU_EXPORT void wgpuBufferUnmap(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE;
5633+
/**
5634+
* Copies a range of data from the provided source pointer into the buffer mapping.
5635+
* See @ref MappedRangeBehavior for error conditions and guarantees.
5636+
* This function is safe to call inside spontaneous callbacks (see @ref CallbackReentrancy).
5637+
*
5638+
* In Wasm, this is more efficient than copying from a `malloc`'d range into a mapped range.
5639+
*
5640+
* @param offset
5641+
* Byte offset relative to the beginning of the buffer.
5642+
*
5643+
* @param data
5644+
* Source, to write buffer data from.
5645+
*
5646+
* @param size
5647+
* Number of bytes of data to write to the buffer.
5648+
* (Note @ref WGPU_WHOLE_MAP_SIZE is *not* accepted here.)
5649+
*
5650+
* @returns
5651+
* @ref WGPUStatus_Error if the copy did not occur.
5652+
*/
5653+
WGPU_EXPORT WGPUStatus wgpuBufferWriteMappedRange(WGPUBuffer buffer, size_t offset, void const * data, size_t size) WGPU_FUNCTION_ATTRIBUTE;
55845654
WGPU_EXPORT void wgpuBufferAddRef(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE;
55855655
WGPU_EXPORT void wgpuBufferRelease(WGPUBuffer buffer) WGPU_FUNCTION_ATTRIBUTE;
55865656
/** @} */

webgpu.yml

+69-6
Original file line numberDiff line numberDiff line change
@@ -3572,17 +3572,21 @@ objects:
35723572
type: bitflag.map_mode
35733573
- name: offset
35743574
doc: |
3575-
TODO
3575+
Byte offset relative to beginning of the buffer.
35763576
type: usize
35773577
- name: size
35783578
doc: |
3579-
TODO
3579+
Byte size of the region to map.
3580+
If this is @ref WGPU_WHOLE_MAP_SIZE, it defaults to `buffer.size - offset`.
35803581
type: usize
35813582
- name: get_mapped_range
35823583
doc: |
35833584
Returns a mutable pointer to beginning of the mapped range.
3584-
See @ref GetMappedRangeBehavior for error conditions and guarantees.
3585+
See @ref MappedRangeBehavior for error conditions and guarantees.
35853586
This function is safe to call inside spontaneous callbacks (see @ref CallbackReentrancy).
3587+
3588+
In Wasm, if `memcpy`ing into this range, prefer using @ref wgpuBufferWriteMappedRange
3589+
instead for better performance.
35863590
returns:
35873591
doc: ""
35883592
type: c_void
@@ -3594,14 +3598,19 @@ objects:
35943598
type: usize
35953599
- name: size
35963600
doc: |
3597-
Byte size of the range to get. The returned pointer is valid for exactly this many bytes.
3601+
Byte size of the range to get.
3602+
If this is @ref WGPU_WHOLE_MAP_SIZE, it defaults to `buffer.size - offset`.
3603+
The returned pointer is valid for exactly this many bytes.
35983604
type: usize
35993605
- name: get_const_mapped_range
36003606
doc: |
36013607
Returns a const pointer to beginning of the mapped range.
36023608
It must not be written; writing to this range causes undefined behavior.
3603-
See @ref GetMappedRangeBehavior for error conditions and guarantees.
3609+
See @ref MappedRangeBehavior for error conditions and guarantees.
36043610
This function is safe to call inside spontaneous callbacks (see @ref CallbackReentrancy).
3611+
3612+
In Wasm, if `memcpy`ing from this range, prefer using @ref wgpuBufferReadMappedRange
3613+
instead for better performance.
36053614
returns:
36063615
doc: ""
36073616
type: c_void
@@ -3613,7 +3622,61 @@ objects:
36133622
type: usize
36143623
- name: size
36153624
doc: |
3616-
Byte size of the range to get. The returned pointer is valid for exactly this many bytes.
3625+
Byte size of the range to get.
3626+
If this is @ref WGPU_WHOLE_MAP_SIZE, it defaults to `buffer.size - offset`.
3627+
The returned pointer is valid for exactly this many bytes.
3628+
type: usize
3629+
- name: read_mapped_range
3630+
doc: |
3631+
Copies a range of data from the buffer mapping into the provided destination pointer.
3632+
See @ref MappedRangeBehavior for error conditions and guarantees.
3633+
This function is safe to call inside spontaneous callbacks (see @ref CallbackReentrancy).
3634+
3635+
In Wasm, this is more efficient than copying from a mapped range into a `malloc`'d range.
3636+
returns:
3637+
doc: |
3638+
@ref WGPUStatus_Error if the copy did not occur.
3639+
type: enum.status
3640+
args:
3641+
- name: offset
3642+
doc: |
3643+
Byte offset relative to the beginning of the buffer.
3644+
type: usize
3645+
- name: data
3646+
doc: |
3647+
Destination, to read buffer data into.
3648+
type: c_void
3649+
pointer: mutable
3650+
- name: size
3651+
doc: |
3652+
Number of bytes of data to read from the buffer.
3653+
(Note @ref WGPU_WHOLE_MAP_SIZE is *not* accepted here.)
3654+
type: usize
3655+
- name: write_mapped_range
3656+
doc: |
3657+
Copies a range of data from the provided source pointer into the buffer mapping.
3658+
See @ref MappedRangeBehavior for error conditions and guarantees.
3659+
This function is safe to call inside spontaneous callbacks (see @ref CallbackReentrancy).
3660+
3661+
In Wasm, this is more efficient than copying from a `malloc`'d range into a mapped range.
3662+
returns:
3663+
doc: |
3664+
@ref WGPUStatus_Error if the copy did not occur.
3665+
type: enum.status
3666+
args:
3667+
- name: offset
3668+
doc: |
3669+
Byte offset relative to the beginning of the buffer.
3670+
type: usize
3671+
- name: data
3672+
doc: |
3673+
Source, to write buffer data from.
3674+
type: c_void
3675+
pointer: immutable
3676+
- name: size
3677+
doc: |
3678+
Number of bytes of data to write to the buffer.
3679+
(Note @ref WGPU_WHOLE_MAP_SIZE is *not* accepted here.)
36173680
type: usize
36183681
- name: set_label
36193682
doc: |

0 commit comments

Comments
 (0)