8000 More function overloading in output by laurentlb · Pull Request #465 · laurentlb/shader-minifier · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

More function overloading in output #465

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

Merged
merged 5 commits into from
Apr 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Minifier/ast.fs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ and Expr =
and TypeSpec =
| TypeName of string
| TypeBlock of StructOrInterfaceBlock
with override t.ToString() =
match t with
| TypeName n -> n
| TypeBlock b -> b.ToString()

// An interface block followed by an instance name (in a TLDecl), like structs, declares an instance.
// An interface block without an instance name (in a TypeDecl), unlike structs, introduces a set of external global variables.
Expand Down
4 changes: 4 additions & 0 deletions Minifier/options.fs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type CliArguments =
| [<CustomCommandLine("--no-renaming-list")>] NoRenamingList of string
| [<CustomCommandLine("--no-sequence")>] NoSequence
| [<CustomCommandLine("--no-remove-unused")>] NoRemoveUnused
| [<CustomCommandLine("--no-overloading")>] NoOverloading
| [<CustomCommandLine("--move-declarations")>] MoveDeclarations
| [<CustomCommandLine("--preprocess")>] Preprocess
| [<CustomCommandLine("--export-kkp-symbol-maps")>] ExportKkpSymbolMaps
Expand All @@ -58,6 +59,7 @@ type CliArguments =
| NoRenaming -> "Do not rename anything"
| NoRenamingList _ -> "Comma-separated list of functions to preserve"
| NoSequence -> "Do not use the comma operator trick"
| NoOverloading -> "When renaming functions, do not introduce new overloads"
| NoRemoveUnused -> "Do not remove unused code"
| MoveDeclarations -> "Move declarations to group them"
| Preprocess -> "Evaluate some of the file preprocessor directives"
Expand All @@ -76,6 +78,7 @@ type Options = {
preserveAllGlobals: bool
hlsl: bool
noInlining: bool
noOverloading: bool
aggroInlining: bool
noSequence: bool
noRenaming: bool
Expand Down Expand Up @@ -115,6 +118,7 @@ let private initPrivate argv =
preserveAllGlobals = args.Contains(PreserveAllGlobals)
hlsl = args.Contains(Hlsl)
noInlining = args.Contains(NoInlining)
noOverloading = args.Contains(NoOverloading)
aggroInlining = args.Contains(AggroInlining) && not (args.Contains(NoInlining))
noSequence = args.Contains(NoSequence)
noRenaming = args.Contains(NoRenaming)
Expand Down
34 changes: 18 additions & 16 deletions Minifier/renamer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ open Ast
type private Env = {
// Map from an old variable name to the new one.
varRenames: Map<string, string>
// Map from a new function name and function arity to the old name.
funRenames: Map<string, Map<int, string>>
// Map from a new function name and function signature to the old name.
funRenames: Map<string, Map<string, string>>
// List of names that are still available.
availableNames: string list

exportedNames: Ast.ExportedName list ref

// Whether multiple functions can have the same name (but different arity).
// Whether multiple functions can have the same name (but different signature).
allowOverloading: bool
// Function that decides a name (and returns the modified Env).
newName: Env -> Ident -> Env
Expand Down Expand Up @@ -182,25 +182,27 @@ type private RenamerImpl(options: Options.Options) =
if not id.IsUniqueId then
env.exportedNames.Value <- {prefix = prefix; name = id.OldName; newName = id.Name} :: env.exportedNames.Value

let renFunction env nbArgs (id: Ident) =
let renFunction env (args: Decl list) (id: Ident) =
let signature = String.concat "," [for ty, _ in args -> ty.name.ToString()]

// we're looking for a function name, already used before,
// but not with the same number of arg, and which is not in options.noRenamingList.
let isFunctionNameAvailableForThisArity (x: KeyValuePair<string, Map<int,string>>) =
not (x.Value.ContainsKey nbArgs || List.contains x.Key options.noRenamingList)
// but not with the same signature, and which is not in options.noRenamingList.
let isFunctionNameAvailableForThisSignature(x: KeyValuePair<string, Map<string,string>>) =
not (x.Value.ContainsKey signature || List.contains x.Key options.noRenamingList)

match env.funRenames |> Seq.tryFind isFunctionNameAvailableForThisArity with
match env.funRenames |> Seq.tryFind isFunctionNameAvailableForThisSignature with
| Some res when env.allowOverloading ->
// overload an existing function name used with a different arity
// overload an existing function name used with a different signature
let newName = res.Key
let funRenames = env.funRenames.Add (res.Key, res.Value.Add(nbArgs, id.Name))
let funRenames = env.funRenames.Add (res.Key, res.Value.Add(signature, id.Name))
let env = env.Update(env.varRenames.Add(id.Name, newName), funRenames, env.availableNames)
id.Rename(newName)
env
| _ ->
// find a new function name
let prevName = id.Name
let env = env.newName env id
let funRenames = env.funRenames.Add (id.Name, Map.empty.Add(nbArgs, prevName))
let funRenames = env.funRenames.Add (id.Name, Map.empty.Add(signature, prevName))
let env = env.Update(env.varRenames, funRenames, env.availableNames)
env

Expand All @@ -212,10 +214,10 @@ type private RenamerImpl(options: Options.Options) =
else
match env.varRenames.TryFind(f.fName.Name) with
| Some name ->
f.fName.Rename(name)
f.fName.Rename(name) // bug, may cause conflicts
env
| None ->
let newEnv = renFunction env (List.length f.args) f.fName
let newEnv = renFunction env f.args f.fName
if f.isExternal(options) then export env ExportPrefix.HlslFunction f.fName
newEnv

Expand Down Expand Up @@ -389,16 +391,16 @@ type private RenamerImpl(options: Options.Options) =
let text = [for shader in shaders -> Printer.print shader.code] |> String.concat "\0"
let names = computeListOfNames text
|> List.filter (fun x -> not <| List.contains x forbiddenNames)

let allowOverloading = not options.noOverloading
let mutable env =
if Array.length shaders > 1 then
// Env.Create(names, true, bijectiveRenaming names, shadowVariables)
let exportsRenames = Seq.zip [for export in exportedNames -> export.name] names |> dict
let contextTable = computeContextTable text
Env.Create(names, true, multiFileRenaming contextTable exportsRenames, shadowVariables)
Env.Create(names, allowOverloading, multiFileRenaming contextTable exportsRenames, shadowVariables)
else
let contextTable = computeContextTable text
Env.Create(names, true, optimizeContext contextTable, shadowVariables)
Env.Create(names, allowOverloading, optimizeContext contextTable, shadowVariables)
env <- dontRenameList env options.noRenamingList
env.exported 6D47 Names.Value <- exportedNames
renameAsts shaders env
Expand Down
49 changes: 27 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,47 +97,48 @@ $ mono shader_minifier.exe # Linux, Mac...
```

```
USAGE: Shader Minifier [--help] [-o <string>] [-v] [--hlsl]
USAGE: Shader Minifier [--help] [--version] [-o <string>] [-v] [--debug] [--hlsl]
[--format <text|indented|c-variables|c-array|js|nasm|rust>]
[--field-names <rgba|xyzw|stpq>] [--preserve-externals]
[--preserve-all-globals] [--no-inlining]
[--aggressive-inlining] [--no-renaming]
[--no-renaming-list <string>] [--no-sequence]
[--no-remove-unused]
[--move-declarations] [<filename>...]
[--no-remove-unused] [--no-overloading] [--move-declarations]
[--preprocess] [--export-kkp-symbol-maps] [<filename>...]

FILENAMES:

<filename>... List of files to minify

OPTIONS:

--version Display the version and exit
-o <string> Set the output filename (default is shader_code.h)
-v Verbose, display additional information
--debug Debug, display more additional information
--hlsl Use HLSL (default is GLSL)
--format <text|indented|c-variables|c-array|js|nasm|rust>
Choose to format the output (use 'text' if you want
just the shader)
Choose to format the output (use 'text' if you want just
the shader)
--field-names <rgba|xyzw|stpq>
Choose the field names for vectors: 'rgba', 'xyzw',
or 'stpq'
Choose the field names for vectors: 'rgba', 'xyzw', or
'stpq'
--preserve-externals Do not rename external values (e.g. uniform)
--preserve-all-globals
Do not rename functions and global variables
--no-inlining Do not automatically inline variables, functions
and arguments
--aggressive-inlining Aggressively inline constants. This can reduce output
size due to better constant folding. It can also
increase output size due to repeated inlined
constants, but this increased redundancy can be
beneficial to compression, leading to a smaller final
compressed size anyway. Does nothing if inlining is
disabled.
--no-inlining Do not automatically inline variables and functions
--aggressive-inlining Aggressively inline constants. This can reduce output size
due to better constant folding. It can also increase
output size due to repeated inlined constants, but this
increased redundancy can be beneficial to compression,
leading to a smaller final compressed size anyway. Does
nothing if inlining is disabled.
--no-renaming Do not rename anything
--no-renaming-list <string>
Comma-separated list of functions to preserve
--no-sequence Do not use the comma operator trick
--no-remove-unused Do not remove unused code
--no-overloading When renaming functions, do not introduce new overloads
--move-declarations Move declarations to group them
--preprocess Evaluate some of the file preprocessor directives
--export-kkp-symbol-maps
Expand Down Expand Up @@ -274,13 +275,17 @@ layout(local_size_x = 32) in;

### Overloading

At this time, do not use overloaded functions (two functions with the same name
but different arguments) in the input. The output probably won't compile.
When renaming functions, Shader Minifier will try to introduce as much
overloading as possible. This reduces the number of identifiers used by the
shader and makes it more compression-friendly.

Shader Minifier works best when the input code doesn't use function overloading
(two functions with the same name and different arguments). Function overloading
might confuse the analysis and lead to an output that doesn't compile. Use the
flag `--no-overloading` if you don't want Shader Minifier to introduce function
overloading, it's probably safer. Please also file issues related to function
overloading, as we don't have enough test coverage at the moment.

On the other hand, Shader Minifier will aggressively use function overloading in
the output. If two functions have a different number of arguments, they may have
the same name in the output. This reduces the number of identifiers used by the
shader and make it more compression friendly.

### kkpView symbol maps

Expand Down
1 change: 1 addition & 0 deletions tests/commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
-o tests/real/oscars_chair.frag.expected tests/real/oscars_chair.frag
-o tests/real/the_real_party_is_in_your_pocket.frag.expected tests/real/the_real_party_is_in_your_pocket.frag
--no-remove-unused --no-inlining -o tests/unit/function_overload.expected tests/unit/function_overload.frag
--no-remove-unused --no-inlining --no-overloading -o tests/unit/function_overload.no.expected tests/unit/function_overload.frag
--no-remove-unused -o tests/unit/function_overload2.expected tests/unit/function_overload.frag
-o tests/unit/overload.expected tests/unit/overload.frag
--no-remove-unused -o tests/unit/externals.expected tests/unit/externals.frag
Expand Down
46 changes: 23 additions & 23 deletions tests/compression_results.log
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
clod.frag (and others) 8692 => 1483.915
mouton/mouton.vert (and others) 16569 => 2403.743
audio-flight-v2.frag 4466 => 873.500
clod.frag (and others) 8692 => 1480.576
mouton/mouton.vert (and others) 16569 => 2402.720
audio-flight-v2.frag 4466 => 863.455
buoy.frag 3976 => 598.113
controllable-machinery.frag 7671 => 1220.647
ed-209.frag 7661 => 1340.206
elevated.hlsl 3405 => 604.101
endeavour.frag 2567 => 530.460
from-the-seas-to-the-stars.frag 14169 => 2275.913
frozen-wasteland.frag 4455 => 791.550
kinder_painter.frag 2832 => 442.132
leizex.frag 2252 => 506.309
lunaquatic.frag 5222 => 1047.812
mandelbulb.frag 2309 => 533.408
ohanami.frag 3179 => 703.261
orchard.frag 5380 => 1000.024
oscars_chair.frag 4648 => 986.069
robin.frag 6183 => 1038.390
slisesix.frag 4429 => 890.365
terrarium.frag 3565 => 745.926
the_real_party_is_in_your_pocket.frag 11964 => 1762.787
valley_ball.glsl 4306 => 881.929
yx_long_way_from_home.frag 2885 => 586.201
Total: 132785 => 23246.758
controllable-machinery.frag 7671 => 1212.215
ed-209.frag 7661 => 1330.885
elevated.hlsl 3405 => 602.340
endeavour.frag 2567 => 522.812
from-the-seas-to-the-stars.frag 14169 => 2272.104
frozen-wasteland.frag 4455 => 772.630
kinder_painter.frag 2832 => 446.282
leizex.frag 2252 => 502.674
lunaquatic.frag 5222 => 1040.171
mandelbulb.frag 2309 => 530.410
ohanami.frag 3179 => 699.259
orchard.frag 5380 => 996.917
oscars_chair.frag 4648 => 979.875
robin.frag 6183 => 1030.289
slisesix.frag 4429 => 882.573
terrarium.frag 3565 => 743.327
the_real_party_is_in_your_pocket.frag 11964 => 1744.283
valley_ball.glsl 4306 => 877.540
yx_long_way_from_home.frag 2885 => 581.527
Total: 132785 => 23112.976
22 changes: 11 additions & 11 deletions tests/real/elevated.hlsl.expected
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
# define VAR_t1 "m"
# define VAR_t2 "y"
# define VAR_v "z"
# define F_m0 "l"
# define F_m1 "l"
# define F_m2 "p"
# define F_m0 "D"
# define F_m1 "p"
# define F_m2 "D"
# define F_m3 "e"
# define F_m4 "s"
# define F_m4 "l"

const char *elevated_hlsl =
"sampler f,m,y;"
Expand Down Expand Up @@ -40,18 +40,18 @@ const char *elevated_hlsl =
"float m=D(f,x);"
"return normalize(float3(t[2].w*(m-D(f+float2(y,0),x)),y,t[2].w*(m-D(f+float2(0,y),x))));"
"}"
"float3 l(float3 f,float3 y,float3 z)"
"float3 D(float3 f,float3 y,float3 z)"
"{"
"float x=mul(z,t[3]),m=lerp(x,mul(y,t[3]),.5+.5*t[2].x);"
"return float3(.13,.18,.22)*(y.y+.25*saturate(-m)-.1*D(1024*f.xz).y)+float3(1.4,1,.7)*saturate(m)*saturate(2*x);"
"}"
"float4 l(float4 f:position,out float4 x:color):position"
"float4 D(float4 f:position,out float4 x:color):position"
"{"
"f.z=t[2].w*D(f.yx,8);"
"x=f.yzxw;"
"return mul(z,x);"
"}"
"float4 l(float2 s:vpos):color"
"float4 p(float2 s:vpos):color"
"{"
"float2 x=t[0]+s.x*.37;"
"float3 y;"
Expand All @@ -65,7 +65,7 @@ const char *elevated_hlsl =
"y.z+=.002*D(x+.1);"
"return float4(y,.3*cos(w*2));"
"}"
"float4 p(float4 f:color):color"
"float4 D(float4 f:color):color"
"{"
"return f;"
"}"
Expand All @@ -86,7 +86,7 @@ const char *elevated_hlsl =
"r=(.1+.75*t[2].x)*(.8+.2*s);"
"r=lerp(r,lerp(float3(.8,.85,.9),float3(.45,.45,.2)*(.8+.2*s),t[2].x),smoothstep(.5-.8*x.y,1-1.1*x.y,w*.15));"
"r=lerp(r,lerp(float3(.37,.23,.08),float3(.42,.4,.2),t[2].x)*(.5+.5*s),smoothstep(0,1,50*(x.y-1)+(w+t[2].x)/.4));"
"r*=l(y,x,D(y.xz,.001*f,5));"
"r*=D(y,x,D(y.xz,.001*f,5));"
"}"
"else"
"{"
Expand All @@ -96,14 +96,14 @@ const char *elevated_hlsl =
"r=.12*(float3(.4,1,1)-float3(.2,.6,.4)*saturate(w*16));"
"r*=.3+.7*t[2].x;"
"r+=pow(1-mul(-x,z),4)*(pow(mul(t[3],reflect(-x,z)),32)*float3(.32,.31,.3)+.1);"
"r=lerp(r,l(y,z,z),smoothstep(1,0,t[2].x+w*60-D(666*y.xz+saturate(w*60)*float2(t[3].w,0)*2,5))*.5);"
"r=lerp(r,D(y,z,z),smoothstep(1,0,t[2].x+w*60-D(666*y.xz+saturate(w*60)*float2(t[3].w,0)*2,5))*.5);"
"}"
"r=r*(.7+.3*smoothstep(0,1,256*abs(w)))*exp(-.042*f);"
"r+=(1-exp(-.1*f))*(float3(.52,.59,.65)+pow(saturate(mul(x,t[3])),8)*float3(.6,.4,.1));"
"}"
"return float4(r,0);"
"}"
"float4 s(float2 x:texcoord):color"
"float4 l(float2 x:texcoord):color"
"{"
"float2 s=x+.5/1280;"
"float4 r=tex2D(m,s);"
Expand Down
Loading
0