Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
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
67 changes: 63 additions & 4 deletions spec/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -2018,6 +2018,8 @@ dictionary GPUTextureViewDescriptor : GPUObjectDescriptorBase {
};
</script>

Issue: derive from `GPUTextureSubresourceRange`

Issue: Make this a standalone algorithm used in the createView algorithm.

Issue: The references to GPUTextureDescriptor here should actually refer to
Expand Down Expand Up @@ -6321,8 +6323,35 @@ dictionary GPURenderBundleEncoderDescriptor : GPUObjectDescriptorBase {
# Queues # {#queues}

<script type=idl>
typedef [EnforceRange] unsigned long long GPUSignalValue;

dictionary GPUTextureSubresourceRange {
GPUTextureAspect aspect = "all";
GPUIntegerCoordinate baseMipLevel = 0;
GPUIntegerCoordinate mipLevelCount;
GPUIntegerCoordinate baseArrayLayer = 0;
GPUIntegerCoordinate arrayLayerCount;
};

dictionary GPUTextureSubresources: GPUTextureSubresourceRange {
required GPUTexture texture;
};

dictionary GPUResourceTransfer {
required GPUQueue receivingQueue;
required sequence<GPUBuffer> buffers;
required sequence<GPUTextureSubresources> textureSubresources;
};

interface GPUQueue {
undefined submit(sequence<GPUCommandBuffer> commandBuffers);
GPUSignalValue signal();
readonly attribute GPUSignalValue lastSignaledValue;

undefined waitFor(GPUQueue queue, optional GPUSignalValue value);

undefined submit(
sequence<GPUCommandBuffer> commandBuffers,
optional sequence<GPUResourceTransfer> transfers = []);
Comment on lines +6352 to +6354
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting the signal value and waiting on it are separate operations on GPUQueue, as opposed to be associated with submissions specifically, because they also need to take into account writeBuffer and writeTexture."

What does the PR description mean when it says "because they also need to take into account writeBuffer and writeTexture?"

I would have expected that after submit returns control to the caller, the developer is free to use the resources in the transfer list on the receiving queue and the WebGPU implementation handles setting up the fences as needed to avoid undefined behavior. What is the advantage of having the developer do this themselves?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what's meant here is: "Getting signal values and waiting on signals are separate queue operations, rather than rolled into the submit() call, because writeBuffer and writeTexture also submit work to the queue. This avoids having to extend all three functions (submit, writeBuffer, and writeTexture) to return signal values and be able to wait on signals."

I would have expected that after submit returns control to the caller, the developer is free to use the resources in the transfer list on the receiving queue and the WebGPU implementation handles setting up the fences as needed to avoid undefined behavior. What is the advantage of having the developer do this themselves?

We shouldn't just implicitly insert a wait() on the receiving queue at whatever arbitrary time the app happens to issue the transferring submit on the sending queue. The app needs to have control over what point in the receiving queue the resources are received, otherwise the receiving queue can stall too early and go idle when it shouldn't have to.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't just implicitly insert a wait() on the receiving queue at whatever arbitrary time the app happens to issue the transferring submit on the sending queue. The app needs to have control over what point in the receiving queue the resources are received, otherwise the receiving queue can stall too early and go idle when it shouldn't have to.

I agree it would be sub-optimal to insert a wait on the receiving queue at the time of the transferring submit. Why can't we insert a wait the first time you submit a command list with the object to the receiving queue? Wouldn't we need to run the same logic to validate the developer hasn't missed a wait? Missing a wait would lead to undefined behavior.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can't we insert a wait the first time you submit a command list with the object to the receiving queue?

Because that would make the graph of synchronization implicit. Missing a wait would cause a validation error and not UB. As said in the meeting I'll detail more what the thought process was for this proposal.


GPUFence createFence(optional GPUFenceDescriptor descriptor = {});
undefined signal(GPUFence fence, GPUFenceValue signalValue);
Expand Down Expand Up @@ -6350,6 +6379,14 @@ GPUQueue includes GPUObjectBase;

{{GPUQueue}} has the following methods:

<dl dfn-type=attribute dfn-for=GPUQueue>
: <dfn>lastSignaledValue</dfn> of type {{GPUSignalValue}}, readonly
::
Returns the integer value that is higher or equal to all the values
previously returned by either {{GPUQueue/lastSignaledValue}} or
{{GPUQueue/signal()}} on this queue.
</dl>

<dl dfn-type=method dfn-for=GPUQueue>
: <dfn>writeBuffer(buffer, bufferOffset, data, dataOffset, size)</dfn>
::
Expand Down Expand Up @@ -6498,8 +6535,10 @@ GPUQueue includes GPUObjectBase;
**Called on:** {{GPUQueue}} this.

**Arguments:**
<pre class=argumentdef for="GPUQueue/submit(commandBuffers)">
|commandBuffers|:
<pre class=argumentdef for="GPUQueue/submit(commandBuffers, transfers)">
|commandBuffers|: list of {{GPUCommandBuffer}} to execute.
|transfers|: list of {{GPUResourceTransfer}} that represent transferring
resource ownership from this {{GPUQueue}} to the others.
</pre>

**Returns:** {{undefined}}
Expand All @@ -6516,9 +6555,30 @@ GPUQueue includes GPUObjectBase;
<div class=queue-timeline>
1. For each |commandBuffer| in |commandBuffers|:
1. Execute each command in |commandBuffer|.{{GPUCommandBuffer/[[command_list]]}}.
1. For each |transfer| in |transfers|:
1. Transfer the |transfer|.{{GPUResourceTransfer/buffers}} to
|transfer|.{{GPUResourceTransfer/receivingQueue}}.
1. Transfer the |transfer|.{{GPUResourceTransfer/textureSubresources}} to
|transfer|.{{GPUResourceTransfer/receivingQueue}}.
</div>
</div>
</div>

: <dfn>waitFor(queue, value)</dfn>
::
Waits for the |queue| reaching |value| on the [=Queue timeline=]. If |value| is undefined,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Wait" sounds like it might cpu-block.
Maybe:

Synchronizes subsequent |this|'s queue operations (e.g. submit, writeBuffer) to happen-after |queue|'s queue operations on, up to and including when |queue.signal| returned |value| (or smaller).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually we should consider renaming wait to synchronizeAfter for clarity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the name wait may be a little misleading, even if it's specified to happen on the queue timeline.
In native API's vkQueueWaitIdle is more of "me wait for the queue" than "queue wait for something else". Therefore, it seems to me that waitFor would make this clear.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for waitFor

the |queue|.{{GPUQueue/lastSignaledValue}} is used instead.

The |value| has to be less or equal to the |queue|.{{GPUQueue/lastSignaledValue}},
or a validation error is produced.

All the resource transitions from |queue| targeting |this| will be considered done on the [=Queue timeline=]
after this call, and relevant resources can be used on |this|.

: <dfn>signal()</dfn>
::
Returns a signal value corresponding to the work submitted to the queue up to this moment on the [=content timeline=].
This value has to be higher or equal to return value of the previous call to {{GPUQueue/signal()}} on this queue.
</dl>

## <dfn interface>GPUFence</dfn> ## {#fence}
Expand Down Expand Up @@ -6601,7 +6661,6 @@ The completion of the fence and the value it completes with can be observed from
: <dfn>onCompletion(completionValue)</dfn>
::
Returns a {{Promise}} that resolves once the fence's completion value &ge; `completionValue`.

<div algorithm="GPUFence.onCompletion">
**Called on:** {{GPUFence}} this.

Expand Down