-
Notifications
You must be signed in to change notification settings - Fork 386
Add GPUCommandEncoder.updateBuffer for embedding small buffer updates. #650
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2391,6 +2391,13 @@ interface GPUCommandEncoder { | |
| GPUTextureCopyView destination, | ||
| GPUExtent3D copySize); | ||
|
|
||
| void inlineUpdateBuffer( | ||
| ArrayBuffer source, | ||
| GPUSize64 sourceOffset, | ||
| GPUBuffer destination, | ||
| GPUSize64 destinationOffset, | ||
| GPUSize64 size); | ||
|
|
||
| void pushDebugGroup(DOMString groupLabel); | ||
| void popDebugGroup(); | ||
| void insertDebugMarker(DOMString markerLabel); | ||
|
|
@@ -2517,6 +2524,52 @@ dictionary GPUImageBitmapCopyView { | |
| </div> | ||
| </div> | ||
|
|
||
| ### <dfn method for=GPUCommandEncoder>inlineUpdateBuffer(source, sourceOffset, destination, destinationOffset, size)</dfn> ### {#GPUCommandEncoder-inlineUpdateBuffer} | ||
|
|
||
| It's often useful for applications to update buffer data prior to draw or compute operations. | ||
| For example, updating model-view and projection matrices before or interleaved with rendering of a scene. | ||
| When these uploads are small, it's viable to inline the update data into the command buffer. | ||
| This does require more copies than other upload paths, but for small data sizes this overhead is negligible. | ||
| Implementations are expected to warn against using this for medium-to-large buffer updates. (e.g. >64k) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem with warnings here is that this size could easily be unknown at build/development time. Say, the developer loads a mesh and updates some vertices using this function, and everything works on their machine. But then later an user loads a bigger mesh, and not only they get a warning spam, it's also animating suspiciously slow, because of how many copies the data needs to go through (i.e. 4 on this path, as estimated by @Kangz). |
||
|
|
||
| In Vulkan, this is similar to |vkCmdUpdateBuffer|. | ||
| In D3D12, implementations can leverage |ID3D12GraphicsCommandList2::WriteBufferImmediate|. | ||
|
kvark marked this conversation as resolved.
|
||
| Metal might use |makeBuffer(bytesNoCopy:length:options:deallocator:)| around some section of shared command buffer serialization memory. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder how this would work in practice. It requires page-size alignment for both the pointer and the size, and also:
|
||
|
|
||
| <div algorithm="GPUCommandEncoder.inlineUpdateBuffer"> | ||
|
|
||
| **Arguments:** | ||
| - {{ArrayBuffer}} |source| | ||
| - {{GPUSize64}} |sourceOffset| | ||
| - {{GPUBuffer}} |destination| | ||
| - {{GPUSize64}} |destinationOffset| | ||
| - {{GPUSize64}} |size| | ||
|
|
||
| **Returns:** void | ||
|
|
||
| Embed a copy of |source| from |sourceOffset| to |size| into the {{GPUCommandEncoder}}. | ||
| Encode a command into the {{GPUCommandEncoder}} that copies |size| bytes of data from embedded copy to the |destinationOffset| of another {{GPUBuffer}} |destination|. | ||
|
|
||
| <div class=validusage dfn-for=GPUCommandEncoder.inlineUpdateBuffer> | ||
| <dfn abstract-op>Valid Usage</dfn> | ||
|
|
||
| Given a {{GPUCommandEncoder}} |encoder| and the arguments {{ArrayBuffer}} |source|, {{GPUSize64}} |sourceOffset|, {{GPUBuffer}} |destination|, {{GPUSize64}} |destinationOffset|, {{GPUSize64}} |size|, the following validation rules apply: | ||
|
|
||
| - |encoder| must be a [=valid=] {{GPUCommandEncoder}}. | ||
| - |encoder|.{{GPUCommandEncoder/inlineUpdateBuffer()}} must not be called when a {{GPURenderPassEncoder}} is active on |encoder|. | ||
| - |encoder|.{{GPUCommandEncoder/inlineUpdateBuffer()}} must not be called when a {{GPUComputePassEncoder}} is active on |encoder|. | ||
| - |destination| must be a [=valid=] {{GPUBuffer}}. | ||
| - The {{GPUBuffer/[[usage]]}} of |destination| must contain {{GPUBufferUsage/COPY_DST}}. | ||
| - |size| must be a multiple of 4. | ||
| - |sourceOffset| must be a multiple of 4. | ||
| - |destinationOffset| must be a multiple of 4. | ||
| - (|sourceOffset| + |size|) must not overflow a {{GPUSize64}}. | ||
| - (|destinationOffset| + |size|) must not overflow a {{GPUSize64}}. | ||
| - The {{ArrayBuffer/byteLength}} of |source| must be greater than or equal to (|sourceOffset| + |size|). | ||
| - The {{GPUBuffer/[[size]]}} of |destination| must be greater than or equal to (|destinationOffset| + |size|). | ||
| </div> | ||
| </div> | ||
|
|
||
| ## Programmable Passes ## {#programmable-passes} | ||
|
|
||
| <script type=idl> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where do we draw the line of the "suboptimal" behavior? I.e. what if an application updates 64k of different multiple buffers? what if it updates 64k of data of the same buffer? does it matter if the updated range is the same? etc