这是indexloc提供的服务,不要输入任何密码
Skip to content

[Immediates] Support SetImmediateData() in RenderBundle #5118

@shaoboyan091

Description

@shaoboyan091

(Based on #5117 ).

There are three options.

option 1: Snapshot content

During bundle encoder stage, snapshot the content of [[immediate_data]] before each draw/dispatch call. And when calling executeBundle, replay all of the commands and the contents. It might benefit the case that use the single js array to update immediate data and update array contents between draw/dispatch calls :

// data: {1, 2, 3, 4} => update [[immediate_data]] {1, 2, 3, 4}
let data[] = [1, 2, 3, 4];
bundleEncoder.setImmediateData(0, data, dataSize);
// pipeline has layout with 16 byte immediate data range
bundleEncoder.setPipeline(pipeline0);
// shader access {1, 2, 3, 4}, bundle snapshot the content {1, 2, 3, 4}
bundleEncoder.draw(...);

// data: update to {1, 6, 7, 4} => update [[immediate_data]] {1, 6, 7, 4}
data[1] = 6;
data[2] = 7;
bundleEncoder.setImmediateData(0, data, dataSize);
// pipeline has layout with 16 byte immediate data range
bundleEncoder.setPipeline(pipeline0);
// shader access {1, 6, 7, 4}, bundle snapshot the content {1, 6, 7, 4}
bundleEncoder.draw(...)
const bundle = bundleEncoder.finish();

....
delete data[]; // destroy data.

// And the bundle will apply:
// {1, 2, 3, 4} to make first draw call shader could get {1, 2, 3, 4} through immediate data.
// {1, 6, 7, 4} to make second draw call shader could get {1, 6, 7, 4} through immediate data.
passEncoder.executeBundle(bundle);

option2: Record the command but fetch the latest js array content

During bundle encoder stage, just record the command and the address that fetch CPU data. And when calling executeBundle, replay all of the commands but fetch CPU data from the recorded address. It makes developer could modify js array content to generate different rendering result through bundle (Quite similar to BindGroup in bundle). A typical case would be:

// data0: {1, 2, 3, 4} => update [[immediate_data]] {1, 2, 3, 4}
let data0 [] = [1, 2, 3, 4];
bundleEncoder.setImmediateData(0, data, dataSize);
// pipeline has layout with 16 byte immediate data range
bundleEncoder.setPipeline(pipeline0);
// shader access {1, 2, 3, 4}, bundle snapshot the content {1, 2, 3, 4}
bundleEncoder.draw(...);

// data1:  {1, 6, 7, 4} => update [[immediate_data]] {1, 6, 7, 4}
let data1[] = {1, 6, 7, 4}
bundleEncoder.setImmediateData(0, data1, dataSize);
// pipeline has layout with 16 byte immediate data range
bundleEncoder.setPipeline(pipeline0);
// shader access {1, 6, 7, 4}, bundle snapshot the content {1, 6, 7, 4}
bundleEncoder.draw(...)
const bundle = bundleEncoder.finish();

// update data0 content to {1, 8, 10, 4}
data0[1] = 8;
data0[2] = 10;

// update data1 content to {5, 6, 7, 4}
data1[0] = 5;
// And the bundle will apply:
// fetch data0 content, which are {1, 8, 10, 4} to make first draw call shader could get {1, 8, 10, 4} through immediate data.
// fetch data1 content {5, 6, 7, 4} to make second draw call shader could get {5, 6, 7, 4} through immediate data.
passEncoder.executeBundle(bundle);

option 3: Don't support SetImmediateData() in GPURenderBundle

We don't support SetImmediateData() command as bundle command to avoid above state things.

I prefer option 2 because it is quite similar for what we do now for uniform buffer in bundles.

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiWebGPU APIapi resolvedResolved - waiting for a change to the API specification

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions