Skip to content

Commit a00caa9

Browse files
authored
C# API (#425)
Fixes #314
1 parent ff1cc94 commit a00caa9

File tree

12 files changed

+140
-70
lines changed

12 files changed

+140
-70
lines changed

Checker/compression_test.fs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module CompressionTests
22

3+
open ShaderMinifier
34
open System.Runtime.InteropServices
45
open System.IO
56
open System.Text
@@ -52,8 +53,8 @@ let compressionTest args filenames =
5253
let minified =
5354
use out = new StringWriter()
5455
let files = [|for f in filenames -> f, File.ReadAllText("tests/real/" + f)|]
55-
let shaders, exportedNames = ShaderMinifier.minify options files
56-
ShaderMinifier.format options out shaders exportedNames
56+
let minifier = Minifier(options, files)
57+
minifier.Format(out)
5758
out.ToString().ToCharArray()
5859

5960
let pointer = &&minified.[0]

Checker/main.fs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ open System.IO
55

66
open Argu
77
open System.Text.RegularExpressions
8+
open ShaderMinifier
89

910
type CliArguments =
1011
| Update_Golden
@@ -135,8 +136,10 @@ let canBeCompiled lang stage content =
135136
canBeCompiledByGlslang lang stage fullsrc && ((lang = "hlsl") || canBeCompiledByDriver stage fullsrc)
136137

137138
let doMinify options file content =
138-
let arr = ShaderMinifier.minify options [|file, content|] |> fst |> Array.map (fun s -> s.code)
139-
ShaderMinifier.print arr.[0]
139+
let minifier = Minifier(options, [|file, content|])
140+
use tw = new System.IO.StringWriter()
141+
minifier.Format(tw)
142+
tw.ToString()
140143

141144
let testMinifyAndCompile options lang (file: string) =
142145
try
@@ -164,7 +167,7 @@ let testPerformance files =
164167
let contents = files |> Array.map File.ReadAllText
165168
let stopwatch = Stopwatch.StartNew()
166169
for str in contents do
167-
let options = Options.init([|"--format"; "text"; "--no-remove-unused"; "fake.frag"|])
170+
let options = Options.init([|"--format"; "text"; "--no-remove-unused"|])
168171
doMinify options "perf test" str |> ignore<string>
169172
let time = stopwatch.Elapsed
170173
printfn "%i files minified in %f seconds." files.Length time.TotalSeconds
@@ -177,29 +180,32 @@ let runCommand argv =
177180
let cleanString (s: string) =
178181
let s = s.Replace("\r\n", "\n").Trim()
179182
versionRegex.Replace(s, "")
180-
let options, filenames = Options.initFiles argv
183+
let options, filenames = Minifier.ParseOptionsWithFiles(argv)
181184
let expected =
182185
try File.ReadAllText options.outputName |> cleanString
183186
with _ when cliArgs.Contains(Update_Golden) -> ""
184187
| _ -> reraise ()
185188
let files = [|for f in filenames -> f, File.ReadAllText(f)|]
186-
let shaders, exportedNames = ShaderMinifier.minify options files
189+
let minifier = Minifier(options, files)
187190
let result =
188191
use out = new StringWriter()
189-
ShaderMinifier.format options out shaders exportedNames
192+
minifier.Format(out)
190193
out.ToString() |> cleanString
194+
191195
let options = { options with outputFormat = Options.OutputFormat.IndentedText; exportKkpSymbolMaps = false}
192-
for shader in shaders do
196+
if filenames.Length = 1 then
197+
let shader = minifier.GetShaders[0]
193198
let resultindented =
194199
use out = new StringWriter()
195-
ShaderMinifier.format options out [|shader|] exportedNames
200+
minifier.Format(out, options)
196201
out.ToString() |> cleanString
197202
let outdir = "tests/out/" + Regex.Replace(options.outputName, @"^tests/(.*)/[^/]*$", @"$1") + "/"
198203
let split = Regex.Match(shader.mangledFilename, @"(^.*)_([^_]+)$").Groups
199204
let name = split[1].Value
200205
let ext = split[2].Value
201206
Directory.CreateDirectory outdir |> ignore
202207
File.WriteAllText(outdir + name + ".minind." + ext, resultindented + "\n")
208+
203209
if result = expected then
204210
printfn "Success: %s" options.outputName
205211
0
@@ -265,7 +271,7 @@ let main argv =
265271
let realTests = Directory.GetFiles("tests/real", "*.frag")
266272
for f in unitTests do
267273
// tests with no #version default to 110
268-
let options = Options.init([|"--format"; "text"; "--no-remove-unused"; "fake.frag"|])
274+
let options = Options.init([|"--format"; "text"; "--no-remove-unused"|])
269275
if not (testMinifyAndCompile options "110" f) then
270276
failures <- failures + 1
271277
testPerformance (Seq.concat [realTests; unitTests] |> Seq.toArray)

Example/Example.csproj

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net7.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<ProjectReference Include="..\Shader Minifier Library.fsproj" />
12+
</ItemGroup>
13+
14+
</Project>

Example/Program.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Example of use of the ShaderMinifier library from C#.
3+
*/
4+
5+
using ShaderMinifier;
6+
7+
var shader = """
8+
out vec4 fragColor;
9+
void main()
10+
{
11+
fragColor = vec4(1., 1., 1., 1.);
12+
}
13+
""";
14+
15+
var file = Tuple.Create("filename.frag", shader);
16+
var options = Minifier.ParseOptions(new[] { "--format", "text" });
17+
var minifier = new Minifier(options, new[] { file });
18+
minifier.Format(System.Console.Out);

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ shader is minified by hand by experienced demosceners, Shader Minifier is often
1414
able to optimize it further. See this [2010
1515
report](https://www.ctrl-alt-test.fr/2010/glsl-minifier-smaller-and-smaller/).
1616

17-
To be notified of new releases, use the watch feature of GitHub.
17+
Shader Minifier is available:
18+
* As an online website: https://ctrl-alt-test.fr/minifier/
19+
* As a command-line tool (download from [Releases](https://github.com/laurentlb/shader-minifier/releases))
20+
* As a .NET library (see [Example](https://github.com/laurentlb/shader-minifier/tree/master/Example))
1821

19-
Try the online version here: https://ctrl-alt-test.fr/minifier/
22+
To be notified of new releases, use the watch feature of GitHub.
2023

2124
## Features
2225

SMBolero.Client/Main.fs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ open Bolero
55
open Bolero.Html
66
open Bolero.Remoting.Client
77
open Bolero.Templating.Client
8+
open ShaderMinifier
89

910
/// Routing endpoints definition.
1011
type Page =
@@ -48,15 +49,15 @@ type Message =
4849
| ClearError
4950

5051
let minify flags content =
51-
let options = Options.init flags
52-
let shaders, exportedNames = ShaderMinifier.minify options [|"input", content|]
52+
let options = Minifier.ParseOptions(flags)
53+
let minifier = Minifier(options, [|"input", content|])
5354
let out = new System.IO.StringWriter()
54-
ShaderMinifier.format options out shaders exportedNames
55+
minifier.Format(out)
5556

5657
let withLoc = new System.IO.StringWriter()
57-
ShaderMinifier.formatWithLocations options withLoc shaders exportedNames
58+
minifier.FormatWithLocations(withLoc)
5859

59-
out.ToString(), ShaderMinifier.getSize shaders, withLoc.ToString()
60+
out.ToString(), minifier.GetSize, withLoc.ToString()
6061

6162
module API =
6263
[<Microsoft.JSInterop.JSInvokableAttribute("minify")>]
@@ -74,7 +75,7 @@ let update (jsRuntime: Microsoft.JSInterop.IJSRuntime) message model =
7475
if not model.flags.inlining then yield "--no-inlining"
7576
if not model.flags.removeUnused then yield "--no-remove-unused"
7677
if not model.flags.renaming then yield "--no-renaming"
77-
yield! model.flags.other.Split(' ')
78+
yield! model.flags.other.Split([|' '|], System.StringSplitOptions.RemoveEmptyEntries)
7879
|]
7980
printfn "Minify %s" (String.concat " " allFlags)
8081
try

Shader Minifier.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "SMBolero.Client", "SMBolero
1616
EndProject
1717
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "SMBolero.Server", "SMBolero.Server\SMBolero.Server.fsproj", "{C1A4652F-0F92-4530-B1C8-2AAC9C383650}"
1818
EndProject
19+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Example", "Example\Example.csproj", "{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}"
20+
EndProject
1921
Global
2022
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2123
Debug|Any CPU = Debug|Any CPU
@@ -84,6 +86,18 @@ Global
8486
{C1A4652F-0F92-4530-B1C8-2AAC9C383650}.Release|x64.Build.0 = Release|Any CPU
8587
{C1A4652F-0F92-4530-B1C8-2AAC9C383650}.Release|x86.ActiveCfg = Release|Any CPU
8688
{C1A4652F-0F92-4530-B1C8-2AAC9C383650}.Release|x86.Build.0 = Release|Any CPU
89+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
90+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
91+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Debug|x64.ActiveCfg = Debug|Any CPU
92+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Debug|x64.Build.0 = Debug|Any CPU
93+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Debug|x86.ActiveCfg = Debug|Any CPU
94+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Debug|x86.Build.0 = Debug|Any CPU
95+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
96+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Release|Any CPU.Build.0 = Release|Any CPU
97+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Release|x64.ActiveCfg = Release|Any CPU
98+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Release|x64.Build.0 = Release|Any CPU
99+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Release|x86.ActiveCfg = Release|Any CPU
100+
{1C6C7E5F-41CF-456E-AEB2-8D501D43D2C5}.Release|x86.Build.0 = Release|Any CPU
87101
EndGlobalSection
88102
GlobalSection(SolutionProperties) = preSolution
89103
HideSolutionNode = FALSE

src/api.fs

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,51 @@
1-
module ShaderMinifier
1+
namespace ShaderMinifier
22

33
open System.IO
44

5-
let getSize (shaders: Ast.Shader[]) =
6-
shaders |> Array.sumBy (fun s -> Printer.print s.code |> String.length)
7-
8-
let minify (options: Options.Options) (files: (string*string)[]) =
9-
// like printfn when verbose option is set
10-
let vprintf fmt = fprintf (if options.verbose then stdout else TextWriter.Null) fmt
11-
12-
let printSize (shaders: Ast.Shader[]) =
13-
if options.verbose then
14-
let length = getSize shaders
15-
vprintf "Shader size is: %d\n" length
16-
17-
let names = String.concat "," [for n, c in files -> $"'{n}' ({c.Length}b)"]
18-
options.trace $"----- minifying {names}"
19-
vprintf "Input file size is: %d\n" (files |> Array.sumBy (fun (_, s) -> s.Length))
20-
21-
let parseAndRewrite (filename, content) =
22-
let shader = Parse.runParser options filename content
23-
let code =
24-
if shader.reorderFunctions then
25-
Rewriter.reorderFunctions options shader.code
26-
else shader.code
27-
{ shader with code = Rewriter.simplify options code }
28-
29-
let shaders = Array.Parallel.map parseAndRewrite files
30-
vprintf "Rewrite tricks applied. "; printSize shaders
31-
32-
if options.noRenaming then
33-
shaders, []
34-
else
35-
let exportedNames = Renamer.rename options shaders
36-
vprintf "Identifiers renamed. "; printSize shaders
37-
shaders, exportedNames
38-
39-
let format = Formatter.print
40-
let formatWithLocations = Formatter.printWithLocations
41-
let print = Printer.print
5+
type Minifier(options, files) =
6+
let getSize (shaders: Ast.Shader[]) =
7+
shaders |> Seq.sumBy (fun s -> Printer.print s.code |> String.length)
8+
9+
let minify (options: Options.Options) (files: (string*string)[]) =
10+
// like printfn when verbose option is set
11+
let vprintf fmt = fprintf (if options.verbose then stdout else TextWriter.Null) fmt
12+
13+
let printSize (shaders: Ast.Shader[]) =
14+
if options.verbose then
15+
let length = getSize shaders
16+
vprintf "Shader size is: %d\n" length
17+
18+
let names = String.concat "," [for n, c in files -> $"'{n}' ({c.Length}b)"]
19+
options.trace $"----- minifying {names}"
20+
vprintf "Input file size is: %d\n" (files |> Array.sumBy (fun (_, s) -> s.Length))
21+
22+
let parseAndRewrite (filename, content) =
23+
let shader = Parse.runParser options filename content
24+
let code =
25+
if shader.reorderFunctions then
26+
Rewriter.reorderFunctions options shader.code
27+
else shader.code
28+
{ shader with code = Rewriter.simplify options code }
29+
30+
let shaders = Array.Parallel.map parseAndRewrite files
31+
vprintf "Rewrite tricks applied. "; printSize shaders
32+
33+
if options.noRenaming then
34+
shaders, [||]
35+
else
36+
let exportedNames = Renamer.rename options (Seq.toArray shaders) |> List.toArray
37+
vprintf "Identifiers renamed. "; printSize shaders
38+
shaders, exportedNames
39+
40+
let shaders, exportedNames = minify options files
41+
42+
static member ParseOptions(flags) = Options.init flags
43+
static member ParseOptionsWithFiles(flags) = Options.initFiles flags
44+
45+
member _.GetSize = getSize shaders
46+
member _.GetShaders = shaders
47+
48+
member _.Format(writer) = Formatter.print options writer shaders exportedNames
49+
member _.Format(writer, options) =
50+
Formatter.print options writer shaders exportedNames
51+
member _.FormatWithLocations(writer) = Formatter.printWithLocations options writer shaders exportedNames

src/formatter.fs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ type private Impl(options: Options.Options, withLocations) =
4949
fprintfn out "#ifndef %s" macroName
5050
fprintfn out "# define %s" macroName
5151

52-
for value: Ast.ExportedName in List.sort exportedNames do
52+
for value: Ast.ExportedName in Seq.sort exportedNames do
5353
fprintfn out "# define %s_%s \"%s\"" ((formatPrefix value.prefix).ToUpper()) value.name value.newName
5454

5555
fprintfn out ""
@@ -70,7 +70,7 @@ type private Impl(options: Options.Options, withLocations) =
7070
fprintfn out "#ifndef SHADER_MINIFIER_HEADER"
7171
fprintfn out "# define SHADER_MINIFIER_HEADER"
7272

73-
for value: Ast.ExportedName in List.sort exportedNames do
73+
for value: Ast.ExportedName in Seq.sort exportedNames do
7474
fprintfn out "# define %s_%s \"%s\"" ((formatPrefix value.prefix).ToUpper()) value.name value.newName
7575

7676
fprintfn out "#endif"
@@ -106,7 +106,7 @@ type private Impl(options: Options.Options, withLocations) =
106106
let printJSHeader out (shaders: Ast.Shader[]) exportedNames =
107107
fprintfn out "// Generated with Shader Minifier %s (https://github.com/laurentlb/Shader_Minifier/)" Options.version
108108

109-
for value: Ast.ExportedName in List.sort exportedNames do
109+
for value: Ast.ExportedName in Seq.sort exportedNames do
110110
fprintfn out "var %s_%s = \"%s\"" (formatPrefix value.prefix) (value.name.ToUpper()) value.newName
111111

112112
fprintfn out ""
@@ -120,7 +120,7 @@ type private Impl(options: Options.Options, withLocations) =
120120

121121
fprintfn out "; Generated with Shader Minifier %s (https://github.com/laurentlb/Shader_Minifier/)" Options.version
122122

123-
for value: Ast.ExportedName in List.sort exportedNames do
123+
for value: Ast.ExportedName in Seq.sort exportedNames do
124124
fprintfn out "_%s_%s: db '%s', 0" (formatPrefix value.prefix) (value.name.ToUpper()) value.newName
125125

126126
fprintfn out ""
@@ -138,7 +138,7 @@ type private Impl(options: Options.Options, withLocations) =
138138
let printRustHeader out (shaders: Ast.Shader[]) exportedNames =
139139
fprintfn out "// Generated with Shader Minifier %s (https://github.com/laurentlb/Shader_Minifier/)" Options.version
140140

141-
for value: Ast.ExportedName in List.sort exportedNames do
141+
for value: Ast.ExportedName in Seq.sort exportedNames do
142142
fprintfn out "pub const %s_%s: &'static [u8] = b\"%s\\0\";" ((formatPrefix value.prefix).ToUpper()) (value.name.ToUpper()) value.newName
143143

144144
for shader in shaders do

src/main.fs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module Main
22

3+
open ShaderMinifier
34
open System.IO
45

56
let readFile file =
@@ -8,21 +9,21 @@ let readFile file =
89
else new StreamReader(file)
910
stream.ReadToEnd()
1011

11-
let minifyFiles (options: Options.Options) filenames =
12+
let minifyFiles (options: Options.Options) filenames out =
1213
let files = [|
1314
for f in filenames do
1415
let content = readFile f
1516
let filename = if f = "" then "stdin" else f
1617
yield filename, content |]
17-
ShaderMinifier.minify options files
18+
let minifier = Minifier(options, files)
19+
minifier.Format(out)
1820

1921
let run (options: Options.Options) filenames =
2022
use out =
2123
if Options.debugMode || options.outputName = "" || options.outputName = "-" then stdout
2224
else new StreamWriter(options.outputName) :> TextWriter
2325
try
24-
let shaders, exportedNames = minifyFiles options filenames
25-
ShaderMinifier.format options out shaders exportedNames
26+
minifyFiles options filenames out
2627
0
2728
with exn ->
2829
printfn "%s" (exn.ToString())

0 commit comments

Comments
 (0)