Repository navigation
v1.2.0 - matrix folds that were silently left expanded, and output names that fit
What changed
The library was rewritten: grammar (ANTLR) → AST → HLSL → ShaderLab is now the
only route, and src/ShaderRipper.Old is a local reference copy that is no
longer built.
Correctness
- Matrix products whose closing row is not adjacent. fxc schedules the work
that feeds a product's vector components between the rows, so the completing
madsat four instructions after the third row. The scan window grows to
eight instructions but still stops at the first write of the accumulator, so a
wider window cannot swallow an unrelated product. - A component that is overwritten before it is re-read.
ADOFAI_HoldShader
readsr0.xin the first row, overwrites it with the object-to-worldw, then
reads it again in the closing row. Such a component is now pinned into a local
where it still held its old value:This is also why such a shader is deliberately not folded intofloat pin0 = r0.x; r0.x = mul(unity_ObjectToWorld, float4(v0.x, v0.y, v0.z, v0.w)).w; o0.xyzw = mul(unity_MatrixVP, float4(r0.y, pin0, r1.z, r0.x));
UnityObjectToClipPos— its clip position is built from object-spacexyz
plus thewof the object-to-world product, which is a different computation. - Texture names. The asset's texture reflection names what it can; the
registers it does not cover (a[PerRendererData]texture, or a built-in the
variant samples without a property) now take the remaining property names in
declaration order instead of degrading tot1,t2, …. A name already bound
is never handed out twice (redefinition of '_MainTex'). - ShaderLab tag casing. Tag keys and
LightModevalues are canonicalised —
LIGHTMODE/FORWARDBASE→LightMode/ForwardBase. Unity matches the key
case-insensitively but the value exactly, so the value mattered.
Output layout
- Output paths follow one rule: a fixed path wins (Resources container or
bundleAssetBundle.m_Container), else the shader's own name with/→_,
else a_1suffix. Longest file name on the reference corpus dropped from 100
to 59 characters, and the numeric suffix never fires. - Fixed paths claim first, so a shader the build placed at an explicit path keeps
it. - Bundle container paths are read now (
AssetBundle.m_Container, class 142) —
the field existed but was never assigned.
CLI
- Options are position-independent:
--shaderlab out --game <dir>is the same
run as--game <dir> --shaderlab out. Readingargs[0]as the command word
made the first form fail with "unknown option --shaderlab". --gameand--file-bareare registered as value-taking options, so their
values no longer land in the positional list where order decided their meaning.- A mistyped option reports itself instead of printing the usage text.
Packaging
linux-x64publishes embedlibdxcompiler.so/libdxil.so; before this the
Linux build carried only Windows DLLs and could not decompile anything.- Native libraries are embedded per RID again, so each binary carries only what
its platform can load.
Verification
scripts/cmp_logic.pyremoved: every invariant it checked is a subset of
verify_logic.py, and its sample count came from the compiled program (which
fxc merges by coordinate) rather than the source.gen_grammar.pyregenerates all five grammars, not justDxbcAsm.- Corpus (425 shaders / 3,263 programs):
verify_logic.py3195/3195,
scan_unwritten0,scan_nan0 escaping / 0 contained,scan_props0 leaked.