Change Values and Rewire#

Goal. Retune or rewire a graph without reloading the scene.

Before you start. Types and Values, Chain Nodes.

The Shape#

A value-input is addressable on the Shader prim by its USD name. Write it, publish the edit by advancing the write floor, then step:

main.py, from the runnable blur example#
def set_radius(stage, ordinal: int, radius: int) -> None:
    """Write inputs:radius on both blur nodes and publish the edit.

    The attribute is connected to nothing, so the value on the prim is the value
    the node reads. Each node is written separately because each carries its own
    copy of the attribute.
    """
    value = np.array([radius], dtype=np.int32)
    tensor = ovstage.make_dltensor(
        value, dtype=ovstage.numpy_to_dldatatype(value.dtype, lanes=1), shape=[1], ndim=1
    )
    with ovstage.PathDictionary(stage) as paths:
        attribute = paths.intern_token("inputs:radius")
        for node in BLUR_NODES:
            path_list = paths.create_path_list_from_strings([node])
            with stage.query_from_path_list(path_list) as query:
                stage.write_attribute(
                    query, attribute, ordinal=ordinal, tensors=tensor, is_array=False
                ).wait()
            paths.destroy_path_list(path_list)
    stage.advance_write_floor(ordinal, ovstage.Scope.ALL).wait()

How It Works#

inputs:X is the name that binds. A value-input authored with the older params:X spelling is also addressed as inputs:X; params:X is not an addressable name. Refer to What You Can Author in USD.

An unconnected input takes effect on the next step. Nothing else has to be reset or reloaded. The blur example changes its radius this way and renders again:

main.py, from the runnable blur example#
        # inputs:radius is unconnected, so a write takes effect on the next step
        # with no reset. At 0 the weight table is {1.0} and the blur is exactly
        # the identity, which makes the comparison below byte-exact.
        ordinal += 1
        products = render_at_radius(stage, renderer, ordinal, 0)
        frame = products[RENDER_PRODUCT].frames[0]
        identity_source = read_var(frame, LDR_COLOR_PATH)
        identity = read_var(frame, BLURRED_PATH)
        del frame, products

A connected input ignores a direct write. If inputs:X is connected to another prim, the connection is the source of the value, so writing inputs:X succeeds and changes nothing. Write the source attribute instead, then reset the renderer so the graph picks up the new value.

Each node carries its own copy. Two nodes referencing the same shader definition each have their own inputs:X, so retuning both means writing both.

A changed value can cost more than the value. Anything the launch script derives from it is derived again, and a cached computation keyed on it runs again. That is the intended behaviour, not a cost to avoid: it is how a new radius reaches a new weight table.

Rewiring changes what runs. Execution order comes from connections, so changing a connection can make a node that was idle start running, or stop one that was running. Refer to Order comes from connections.

Verify It Worked#

Choose a value with an exact effect and check it byte for byte, before and after the change, against the same input AOV. A picture that changes but not in the way the value predicts means the write landed somewhere other than the input you meant.

The blur example uses a blur radius of zero, which makes the node the identity, and prints pixels differing from the input: 0. A write that missed leaves the previous radius in place and every pixel differs.

When It Goes Wrong#

  • The write reported success and nothing changed: the input is connected, so the connection is winning. Write the source attribute instead.

  • The attribute would not bind: ovrtx’s default binding mode skips attributes it cannot find rather than reporting them, so a misspelled name is silent. Bind with the mode that requires the attribute to exist while you are debugging.

  • A node stopped running after a rewire: it now feeds nothing that is requested. Refer to Nothing Appears.