crazylafo / AE_tl_math

An After Effect plugin to code in GLSL directly inside After Effect or to write math expressions to code your own filter
GNU General Public License v3.0
123 stars 7 forks source link

Random "Shader Error" frames in AE 2021 #26

Closed gmatters closed 2 years ago

gmatters commented 2 years ago

AE 2021 in OSX 12.1, AE x64 build on M1 hardware

On CC2017 the output of tl_maths was very stable; if I had an error in my glsl it would render "Shader Error" and once I fixed the error it would render perfectly.

But on my new computer I get rare single "Shader Error" frames when previewing and rendering. It basically makes it impossible to use tl_maths on a real project.

I can repro this by looping any piece of footage, adding tl_maths with the default preset, [apply], choose a color tint so I can visually verify that tl_maths is really running, then render 1 minute of footage. There will be a few single "Shader Error" frames in the output.

The "shader error" frames are not deterministic. If I put the playhead on a bad frame, then change the preview to Half resolution, it goes away. If I purge all cache and put the resolution back to Full, it will render that frame correctly.

gmatters commented 2 years ago

Further observation:

I put tl_maths in an adjustment layer per my original report. Below that, I animate a small solid layer moving across the screen. I do not observe "Shader Error" frames. I add a piece of footage below the moving solid. Now I do get "Shader Error" frames.

Unclear whether this is relevant in any way.

gmatters commented 2 years ago

evalScripts is running for every frame, and sometimes the contents of seqP->Glsl33_VertexShAc is corrupted, with some extra characters inserted. The nature of the corruption is always similar, with 18 characters inserted around offset 200, and the contents of the extra characters are a fragment of glsl code, but the truncating of those extra characters causes a compile error.

seqP->Glsl33_VertexShAc usually contains:

version 330 // glsls version for opengl 3.3

out vec4 fragColorOut; in vec2 out_uvs; vec2 textUvs = vec2(out_uvs.x, 1-out_uvs.y); uniform vec2 resolution; uniform bool cbox_1 ; uniform float slider_1 ; uniform vec3 point_1 ; uniform vec3 color_1 ;

But for roughly 1/100 frames it'll contain something like:

version 330 // glsls version for opengl 3.3

out vec4 fragColorOut; in vec2 out_uvs; vec2 textUvs = vec2(out_uvs.x, 1-out_uvs.y); uniform vec2 resolution; uniform bool cbox_1 ; uniform float slider_1 ; uniform vec3 4 ; uniform vec3 point_1 ; uniform vec3 color_1 ;

and the byte at offset 215 ('4' in the example above) will be different.

gmatters commented 2 years ago

The bug is in this line: copyStrFromJsonToSeqData(arbDataJS, "/composition/layerScale",seqDataP->layerGrpNameAc); which should fill in seqDataP->layerScaleNameAc.

Often seqDataP->layerScaleNameAc bytes are null in which case the generated glsl function has an extra “uniform vec3 ;\n” which compiles correctly. But sometimes the memory is non-null which results in things like “uniform vec3 4 ;” which fail to compile.

Ideally the code should be structured in a way to ensure that elements of seqDataP don’t go uninitialized, and that guarantees the set of controls perfectly matches across CES through JSON to seqData, but I didn’t think deeply about that.

I put assert(!varStr.empty()); at the top of AppendGlslInputVec3d and all the variants, since find(“”) is nonsensical, and that check is enough to catch the uninitialized layerScaleNameAc in this case (although if it were consistently some non-zero garbage data it wouldn’t be caught).