Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into ib/fix-warnings
- Loading branch information
Showing
38 changed files
with
1,148 additions
and
530 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# RFC: Dynamic Shader Regeneration | ||
|
||
Being able to specify props that affect the shader source code means that either: | ||
* Changes to these props need to be detected, shaders recompiled and programs relinked | ||
* Or we need to specify in documentation that shaders are only generated on creation | ||
|
||
Apart from the work/extra complexity required to accurately detect when shaders should be recompiled, the big issue is that recompilation and relinking of GLSL shaders tends to be slow (sometimes extremely slow, as in several seconds, or even half a minute or more) and happens synchronously on the main WebGL thread, freezing all rendering or even the entire app. | ||
|
||
If we support dynamic recompilation of shaders based on changing props, we therefore need to be extra careful to avoid (and detect/warn for) "spurious" recompiles. The user might not realize that the supplied props are triggering constant recompiles causing app performance to crater. | ||
|
||
For ideas around working around slow shader compilation, see: | ||
* [Deferring linking till first draw](http://toji.github.io/shader-perf/) | ||
* [KHR_parallel_shader_compile extension](https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/) | ||
* [KHR_parallel_shader_compile discussion](https://github.com/KhronosGroup/WebGL/issues/2690) | ||
* [Intel webGL 2018 presentation](https://docs.google.com/presentation/d/1qeD2xio2dgkqWGQucZs6nezQPePOM4NtV9J54J7si9c/htmlpresent) search for KHR_parallel_shader_compile | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
# RFC: GLSL Function Replacement And Attribute Injection | ||
|
||
* Authors: Ib Green | ||
* Date: March 2019 | ||
* Status: **Draft** | ||
|
||
This RFC is part of the [shadertools roadmap](dev-docs/roadmaps/shadertools-roadmap.md). | ||
|
||
|
||
## Summary | ||
|
||
This RFC proposes a system for shader module users to replace GLSL functions (by supplying a map of function names to strings fragments of GLSL code) as well as injecting new attributes and uniforms. | ||
|
||
This supports use case such as: | ||
* Completely or partially skip CPU side attribute generation | ||
* Work directly on supplied binary data (e.g. binary tables). | ||
* Do additional GPU processing on data, allowing performant custom effects. | ||
|
||
|
||
## Overview | ||
|
||
Let's start with a couple of API examples to illustrate what we want to achieve: | ||
|
||
|
||
### API Example: Using Columnar Binary Data Sirectly | ||
|
||
Columnar binary data systems (like Apache arrow) will often store primitive values (e.g. a Float32) in separate columns, rather than as a `vec2` or `vec3`. This means that even if we exposed these columns as attributes in GLSL, we cannot use them directly as the expected `vec3` attribute for positions. However, if we could just define a snippet of GLSL code to override how the shader extracs a position from attributes (`getPosition`), we could still use these values rather than pre-processing them in JavaScript: | ||
|
||
``` | ||
new Model({ | ||
vs, | ||
fs, | ||
// inject new attributes | ||
glsl: { | ||
attributes: { | ||
x: 'float', | ||
y: 'float' | ||
}, | ||
}, | ||
// Define a custom glsl accessor (string valued accessor will be treated as GLSL) | ||
getPosition: 'return vec3(x, y, 0.);', | ||
// Supply values to the injected attributes | ||
attributes: { | ||
x: new Float32Array(...), | ||
y: new Float32Array(...) | ||
}, | ||
}) | ||
``` | ||
|
||
The input vertex shader would be defined as follows: | ||
|
||
``` | ||
in vec3 instancePosition; | ||
// Shadertools would e.g. do a line-based replacement of getPosition | ||
vec3 getPosition() { return instancePosition; } | ||
main() { | ||
const position = getPosition(); | ||
// Note: shader does not assume that `position = instancePositions`, but calls an overridable GLSL function! | ||
} | ||
``` | ||
|
||
Shadertools would resolve this to: | ||
|
||
``` | ||
in vec3 instancePosition; // Note: no longer used, would be nice if this could be removed but not critical. | ||
in float x; | ||
in float y; | ||
// Shadertools has done a line-based replacement of getPosition | ||
vec3 getPosition() { return vec3(x, y, 0.);; } | ||
main() { | ||
const position = getPosition(); | ||
// Note: layer no longer assumes `position = instancePositions`, but calls overridable GLSL function | ||
} | ||
``` | ||
|
||
|
||
### API Example: Adapting Data to fit layer's Requirement | ||
|
||
Let's say that we load binary data for a point cloud that only contains a single value per point (e.g. `reflectance`), but the shader we want to use only supports specifying an RGBA color per point. While we could certainly write a JavaScript function to generate a complete RGBA color array attribute, this extra time and memory could be avoided: | ||
|
||
``` | ||
new Model({ | ||
vs: POINT_CLOUD_VS, | ||
fs: POINT_CLOUD_FS, | ||
// inject new attributes and uniforms | ||
glsl: { | ||
attributes: { | ||
reflectance | ||
}, | ||
uniforms: { | ||
alpha | ||
} | ||
}, | ||
// Define a custom glsl accessor (string valued accessor will be treated as GLSL) | ||
getColor: 'return vec4(reflectance, reflectance, reflectance, alpha);', | ||
// Supply actual values to the injected attributes and uniforms | ||
attributes: { | ||
reflectance: new Float32Array(...) | ||
}, | ||
uniforms: { | ||
alpha: 0.5 | ||
} | ||
}) | ||
``` | ||
|
||
|
||
## Design Discussions | ||
|
||
### Shader Buy-In | ||
|
||
While it might be possible to use the function replacement system to replace of arbitrary functions in a shader, this can lead to brittle overrides as the base shader is updated. | ||
|
||
The ideal setup is one where the shader is written with the intention of having certain functions be overridable. Often, the readout of attributes would be a typical place to add an overridable function, allowing the shader to be used with different attributes. | ||
|
||
Apart from attribute access, a shader could potentially define additional overridable functions that it would call at the right moments. These would then normally be separately documented. | ||
|
||
|
||
## Open Issues | ||
|
||
### Naming Conflicts | ||
|
||
Define/reinforce naming conventions/prefixes for GLSL functions and variables in shader code to maximize predictability/minimize conflicts with user's GLSL accessor code. | ||
|
||
Since we do not have a true syntax aware parser/string replacement system we also risk replacing unrelated strings. This risk is becoming bigger the more extensive our shader replacement support becomes. | ||
|
||
|
||
### Fragment Shader Support | ||
|
||
This RFC as written does not offer any way for users to modify fragment shaders. | ||
|
||
If it is desirable to offer the ability to redefine GLSL functions in the fragment shader, the GLSL accessor system outlined in this system does not extend well. | ||
* attributes are not available in the fragment shader, and such data needs to be explicitly plumbed through as `varyings` that "eat into" a very limited bank (often only 8 varyings or `vec4`s). | ||
* It may be necessary to implement a "varying compressor" and additonal props with more complicated semantics to describe the data flow. | ||
Naturally, if user-defined GLSL functions in the fragment shaders can only use the data already available, the system should be simpler. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.