Skip to content
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

Supporting logically mutable components #21

Open
tangent-vector-personal opened this issue Oct 4, 2016 · 0 comments
Open

Supporting logically mutable components #21

tangent-vector-personal opened this issue Oct 4, 2016 · 0 comments

Comments

@tangent-vector-personal
Copy link
Collaborator

A lot of existing GLSL/HLSL shaders make use of mutable variables in ways that are convenient, but maybe not essential to their semantics. In broad strokes, there are two cases:

  1. "Local" mutation used to compute a value incrementally from sub-terms.
  2. "Global" mutation used to modify a logical quantity like "position" or "normal" over the course of a shader.

The "local" case is stuff like:

float4 sum = 0.0;
sum += firstThing();
sum += secondThing();

and:

float4 foo = someFunction();
foo.xyz *= foo.a;

In general, we can re-write such component declarations into bigger expressions, or so that they use Spire's support for statement initialization. This is usually mechanical, so I expect most programmers could be trained to write in the Spire-like style.

On the flip side, this kind of local mutation seems really easy for a system like Spire to support (it is basically just what Shade Trees had). If we think of sum or foo above like a variable, that points to a specific shader-graph node, then the subsequent assignment operations can be seen as just creating new shader graph nodes and then pointing the variable at a new node. This same basic logic could be extended to support simple cases of conditional assignment.

The "global" case is more interesting, and probably also more challenging. A lot of large GLSL/HLSL shaders work along the lines of collecting most/all of the shading state into a single struct, and then passing that struct as an inout parameter to one or more functions that will read-modify-write it along the chain.

Within the Spire formulation, these steps along the chain might best be implemented as modules. We already have support for the output of one module to become the input to another module (so if A outputs normal and B expects normal as input, it can get it implicitly). The missing thing right now is that if we want a module that takes normal as input and produces normal as output, we have to carefully manage the names, and do the module wiring more explicitly.

I suspect (but am not sure) that it is reasonable to extend the intuition of the "local" case to the global one, and allow for modules that conceptually have inout parameters. The order of using declarations for modules represents a logical "order of execution" (here referring to the order of execution of shader-graph-building code, and not the runtime code), so that the shader author would still be in control of the final result (just as if they had called a bunch of functions that perform read-modify-write operations in order).

I'm a bit nervous about all of the above, but I also know that porting existing shader code that makes heavy use of mutation tends to result in ugly idioms (lots of distinct names for the same concept), if the target language doesn't support some kind of idiomatic mutation construct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant