Skip to content

Commit

Permalink
Add debugging traces (#345)
Browse files Browse the repository at this point in the history
  • Loading branch information
eldritchconundrum authored Apr 16, 2024
1 parent 3e19b38 commit be08f58
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 9 deletions.
6 changes: 5 additions & 1 deletion Checker/checker-linux.fsproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
Expand All @@ -25,4 +25,8 @@
</ProjectReference>
</ItemGroup>

<PropertyGroup>
<RunWorkingDirectory>$(MSBuildProjectDirectory)/..</RunWorkingDirectory>
</PropertyGroup>

</Project>
6 changes: 3 additions & 3 deletions Checker/main.fs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ let canBeCompiled content =
printfn "compilation failed: %s" info
false

let doMinify content =
let arr = ShaderMinifier.minify [|"input", content|] |> fst |> Array.map (fun s -> s.code)
let doMinify file content =
let arr = ShaderMinifier.minify [|file, content|] |> fst |> Array.map (fun s -> s.code)
Printer.print arr.[0]

let testMinifyAndCompile (file: string) =
Expand All @@ -54,7 +54,7 @@ let testMinifyAndCompile (file: string) =
printfn "Invalid input file '%s'" file
false
else
let minified = doMinify content + "\n"
let minified = doMinify file content + "\n"
if not (canBeCompiled minified) then
printfn "Minification broke the file '%s'" file
printfn "%s" minified
Expand Down
11 changes: 9 additions & 2 deletions src/analyzer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,12 @@ module private VariableInlining =
let ident, isConst = def.Value
if not ident.DoNotInline && not ident.ToBeInlined && not ident.VarDecl.Value.isEverWrittenAfterDecl then
match localReferences.TryGetValue(def.Key), allReferences.TryGetValue(def.Key) with
| (_, 1), (_, 1) when isConst -> ident.ToBeInlined <- true
| (_, 0), (_, 0) -> ident.ToBeInlined <- true
| (_, 1), (_, 1) when isConst ->
debug $"inlining variable '{Printer.debugIdent ident}' because it's safe to inline and used only once"
ident.ToBeInlined <- true
| (_, 0), (_, 0) ->
debug $"inlining variable '{Printer.debugIdent ident}' because it's safe to inline and unused"
ident.ToBeInlined <- true
| _ -> ()

let isTrivialExpr = function
Expand Down Expand Up @@ -114,11 +118,13 @@ module private VariableInlining =
// Top-level values are special, in particular in HLSL. Keep them for now.
if not isTopLevel then
// Never-written locals without init should be unused: inline (remove) them.
debug $"inlining (removing) unassigned local '{Printer.debugDecl def}'"
def.name.ToBeInlined <- true
| Some init ->
if canBeInlined init then
// Never-written locals and globals are inlined when their value is "simple enough".
// This can increase non-compressed size but decreases compressed size.
debug $"inlining variable '{Printer.debugDecl def}' because it's never written and has a 'simple' definition"
def.name.ToBeInlined <- true
| _ -> ()

Expand Down Expand Up @@ -322,6 +328,7 @@ module private FunctionInlining =
if not funcInfo.funcType.fName.DoNotInline && verifyArgsUses funcInfo.func callSites then
// Mark both the call site (so that simplifyExpr can remove it) and the function (to remember to remove it).
// We cannot simply rely on unused functions removal, because it might be disabled through its own flag.
debug $"inlining function '{funcInfo.funcType}' into {callSites.Length} call sites"
for callSite in callSites do
callSite.ident.ToBeInlined <- true
funcInfo.funcType.fName.ToBeInlined <- true
Expand Down
1 change: 1 addition & 0 deletions src/api.fs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ let private readFile file =
stream.ReadToEnd()

let minify (files: (string*string)[]) =
let names = files |> Array.map (fun (n,_) -> n) |> String.Concat in debug $"----- minifying {names}"
vprintf "Input file size is: %d\n" (files |> Array.sumBy (fun (_, s) -> s.Length))
let shaders = files |> Array.map (fun (f, c) -> Parse.runParser f c)
vprintf "File parsed. "; printSize shaders
Expand Down
8 changes: 8 additions & 0 deletions src/options.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

open System.IO
open Argu
open System

let version = "1.3.6" // Shader Minifier version
let debugMode = false
Expand All @@ -23,6 +24,7 @@ type FieldSet =
type CliArguments =
| [<CustomCommandLine("-o")>] OutputName of string
| [<CustomCommandLine("-v")>] Verbose
| [<CustomCommandLine("--debug")>] Debug
| [<CustomCommandLine("--hlsl")>] Hlsl
| [<CustomCommandLine("--format")>] FormatArg of OutputFormat
| [<CustomCommandLine("--field-names")>] FieldNames of FieldSet
Expand All @@ -45,6 +47,7 @@ type CliArguments =
match s with
| OutputName _ -> "Set the output filename (default is shader_code.h)"
| Verbose -> "Verbose, display additional information"
| Debug -> "Debug, display more additional information"
| Hlsl -> "Use HLSL (default is GLSL)"
| FormatArg _ -> "Choose to format the output (use 'text' if you want just the shader)"
| FieldNames _ -> "Choose the field names for vectors: 'rgba', 'xyzw', or 'stpq'"
Expand All @@ -66,6 +69,7 @@ type Options() =
member val outputName = "shader_code.h" with get, set
member val outputFormat = CVariables with get, set
member val verbose = false with get, set
member val debug = false with get, set
member val smoothstepTrick = false with get, set
member val canonicalFieldNames = "xyzw" with get, set
member val preserveExternals = false with get, set
Expand All @@ -88,6 +92,9 @@ module Globals =
// like printfn when verbose option is set
let vprintf fmt = fprintf (if options.verbose then stdout else TextWriter.Null) fmt

let forceDebug = Environment.GetEnvironmentVariable("MINIFIER_DEBUG", EnvironmentVariableTarget.Process ||| EnvironmentVariableTarget.User) <> null
let debug str = fprintfn (if options.debug || forceDebug then stdout else IO.TextWriter.Null) "%s" str

open Globals

let helpTextMessage = sprintf "Shader Minifier %s - https://github.com/laurentlb/Shader_Minifier" version
Expand All @@ -111,6 +118,7 @@ let private initPrivate argv needFiles =
options.outputName <- args.GetResult(OutputName, defaultValue = "shader_code.h")
options.outputFormat <- args.GetResult(FormatArg, defaultValue = CVariables)
options.verbose <- args.Contains(Verbose)
options.debug <- args.Contains(Debug)
options.smoothstepTrick <- args.Contains(Smoothstep)
options.canonicalFieldNames <- (sprintf "%A" (args.GetResult(FieldNames, defaultValue = XYZW))).ToLower()
options.preserveExternals <- args.Contains(PreserveExternals) || args.Contains(PreserveAllGlobals)
Expand Down
13 changes: 13 additions & 0 deletions src/printer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -319,3 +319,16 @@ let print tl = printIndented tl |> stripIndentation
let writeSymbols shader = (new PrinterImpl()).WriteSymbols shader
let exprToS x = (new PrinterImpl()).ExprToS 0 x |> stripIndentation
let typeToS ty = (new PrinterImpl()).TypeToS ty |> stripIndentation

let debugDecl (t: DeclElt) =
let size = if t.size = None then "" else $"[{t.size}]"
let init = match t.init with
| Some e -> $" = {exprToS e}"
| None -> ""
let sem = if t.semantics.IsEmpty then "" else $": {t.semantics}" in
$"{t.name.OldName}{size}{init}{sem}"

let debugIdent (ident: Ident) =
match ident.Declaration with
| Declaration.Variable rv -> debugDecl rv.decl
| _ -> ident.OldName.ToString()
12 changes: 9 additions & 3 deletions src/rewriter.fs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ module private RewriterImpl =

// Squeeze top-level declarations, e.g. uniforms
let rec squeezeTLDeclarations = function
| []-> []
| [] -> []
| TLDecl(ty1, li1) :: TLDecl(ty2, li2) :: l when ty1 = ty2 ->
squeezeTLDeclarations (TLDecl(ty1, li1 @ li2) :: l)
| e::l -> e :: squeezeTLDeclarations l
Expand Down Expand Up @@ -549,7 +549,9 @@ module private RewriterImpl =
|> List.map (fun c -> c.prototype)
|> List.contains funcInfo.funcType.prototype) // when in doubt wrt overload resolution, keep the function.
canBeRenamed && not isCalled && not funcInfo.funcType.isExternal
let unused = set [for funcInfo in funcInfos do if isUnused funcInfo then yield funcInfo.func]
let unused = [for funcInfo in funcInfos do if isUnused funcInfo then yield funcInfo]
if not unused.IsEmpty then debug($"removing unused functions: " + String.Join(", ", unused |> List.map (fun fi -> fi.funcType)))
let unused = unused |> List.map (fun fi -> fi.func) |> set
let mutable edited = false
let code = code |> List.filter (function
| Function _ as t -> if Set.contains t unused then edited <- true; false else true
Expand Down Expand Up @@ -615,6 +617,7 @@ module private ArgumentInlining =
let argExprs = callSites |> List.map (fun c -> c.argExprs |> List.item argIndex) |> List.distinct
match argExprs with
| [argExpr] when isInlinableExpr argExpr -> // The argExpr must always be the same at all call sites.
debug $"inlining expression '{Printer.exprToS argExpr}' into argument '{Printer.debugDecl varDecl.decl}' of '{funcInfo.funcType}'"
argInlinings <- {func=funcInfo.func; argIndex=argIndex; varDecl=varDecl; argExpr=argExpr} :: argInlinings
| _ -> ()
| _ -> ()
Expand Down Expand Up @@ -677,7 +680,10 @@ let rec private iterateSimplifyAndInline li =

let li = if options.noInlining then li else ArgumentInlining.apply didInline li

if didInline.Value then iterateSimplifyAndInline li else li
if didInline.Value
then debug $"inlining happened: running analysis again..."
iterateSimplifyAndInline li
else li

let simplify li =
li
Expand Down

0 comments on commit be08f58

Please sign in to comment.