Struct-chaining is a C API pattern using linked lists and dynamic typing to extend existing structs with new members, while maintaining API and ABI compatibility. For example:
An extensible struct is statically typed. It is the root of a linked list, containing a pointer to the next struct in the chain:
Each extension struct is a "subtype" of WGPUChainedStruct; that is, its first member is a WGPUChainedStruct, so that it can be safely cast to WGPUChainedStruct. This allows the implementation to read its WGPUChainedStruct::sType, which is some value of WGPUSType ("Struct Type") that dynamically identifies the struct's type. (The sType
may come from an implementation-specific extension; WGPUSType is an "open" enum.)
Once the implementation identifies the struct by its sType
, it casts the pointer back to the appropriate struct type in order to access its contents. Setting sType
incorrectly (or pointing to any type that isn't a subtype of WGPUChainedStruct) causes undefined behavior.
This is used like so:
The pointer links in a struct chain are all mutable pointers. Whether the structs in the chain are actually mutated depends on the function they are passed to (whether the struct chain is passed as an input or an output). Some structs (e.g. WGPULimits) may be either an input or an output depending on the function being called.
A struct-chaining error occurs if a struct chain is incorrectly constructed (in a detectable way). They occur if and only if:
sType
of a struct in the chain is not valid in the context of the chain root's static type.sType
value are seen in the same struct chain. (Note this also detects and disallows cycles.)Struct chains which are used in device-timeline validation/operations (e.g. WGPUBufferDescriptor in wgpuDeviceCreateBuffer) have their chain errors surfaced asynchronously, like any other validation error.
Struct chains which are used in content-timeline operations (e.g. Out-Struct-Chain Error) have their chain errors surfaced synchronously, like other content-timeline validation errors.
Operations which take out-struct-chains (e.g. WGPULimits, in wgpuAdapterGetLimits and wgpuDeviceGetLimits, but not in WGPUDeviceDescriptor) handle struct-chaining errors as follows:
FreeMembers
functions do not traverse the struct chain and must be called separately on each struct (that has a FreeMembers
function) in the chain. See Returned with Ownership.