Update WHLSL to Metal tester with semantics
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Oct 2018 00:23:56 +0000 (00:23 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 10 Oct 2018 00:23:56 +0000 (00:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=190416
<rdar://problem/45145139>

Reviewed by Myles Maxfield.

A few small changes to the WHLSL to Metal tools:
- Make it compile by adding some missing JS files :)
- Add semantics to the default shader
- Add FIXMEs to the other shaders
- Create an in-browser test for the WHLSLToMetal codepath
- Fix typos in the semantics checker

* WebGPUShadingLanguageRI/Checker.js:
(Checker.prototype._checkSemantics.checkSemanticTypes):
(Checker.prototype._checkSemantics.checkSemanticForShaderType):
* WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Compiler.m:
* WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Demo shaders/Default.whlsl:
* WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Demo shaders/Julia.whlsl:
* WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Demo shaders/Mandelbrot.whlsl:
* WebGPUShadingLanguageRI/Metal/WHLSL Tests/WHLSL Tests.xcodeproj/project.pbxproj:
* WebGPUShadingLanguageRI/Metal/WhlslToMsl.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@236992 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/WebGPUShadingLanguageRI/Checker.js
Tools/WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Compiler.m
Tools/WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Demo shaders/Default.whlsl
Tools/WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Demo shaders/Julia.whlsl
Tools/WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Demo shaders/Mandelbrot.whlsl
Tools/WebGPUShadingLanguageRI/Metal/WHLSL Tests/WHLSL Tests.xcodeproj/project.pbxproj
Tools/WebGPUShadingLanguageRI/Metal/WhlslToMsl.html [new file with mode: 0644]

index 8a11f46..08205c8 100644 (file)
@@ -1,3 +1,28 @@
+2018-10-09  Dean Jackson  <dino@apple.com>
+
+        Update WHLSL to Metal tester with semantics
+        https://bugs.webkit.org/show_bug.cgi?id=190416
+        <rdar://problem/45145139>
+
+        Reviewed by Myles Maxfield.
+
+        A few small changes to the WHLSL to Metal tools:
+        - Make it compile by adding some missing JS files :)
+        - Add semantics to the default shader
+        - Add FIXMEs to the other shaders
+        - Create an in-browser test for the WHLSLToMetal codepath
+        - Fix typos in the semantics checker
+
+        * WebGPUShadingLanguageRI/Checker.js:
+        (Checker.prototype._checkSemantics.checkSemanticTypes):
+        (Checker.prototype._checkSemantics.checkSemanticForShaderType):
+        * WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Compiler.m:
+        * WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Demo shaders/Default.whlsl:
+        * WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Demo shaders/Julia.whlsl:
+        * WebGPUShadingLanguageRI/Metal/WHLSL Tests/Core/Demo shaders/Mandelbrot.whlsl:
+        * WebGPUShadingLanguageRI/Metal/WHLSL Tests/WHLSL Tests.xcodeproj/project.pbxproj:
+        * WebGPUShadingLanguageRI/Metal/WhlslToMsl.html: Added.
+
 2018-10-09  Jer Noble  <jer.noble@apple.com>
 
         Crash when closing WKWebView during enter fullscreen animation
index 1e99327..518ffe6 100644 (file)
@@ -177,7 +177,7 @@ class Checker extends Visitor {
         function checkSemanticTypes(items) {
             for (let item of items) {
                 if (item.semantic && !item.semantic.isAcceptableType(item.type, program))
-                    throw new WTypeError(node.origin.originString, `Semantic ${item.semantic} is unnacceptable type ${item.type}`);
+                    throw new WTypeError(node.origin.originString, `Semantic ${item.semantic} is unacceptable type ${item.type}`);
             }
         }
         checkSemanticTypes(inputGatherer.result);
@@ -186,7 +186,7 @@ class Checker extends Visitor {
         function checkSemanticForShaderType(items, direction) {
             for (let item of items) {
                 if (item.semantic && !item.semantic.isAcceptableForShaderType(direction, node.shaderType))
-                    throw new WTypeError(node.origin.originString, `Semantic ${item.semantic} is unnacceptable as an ${direction} of shader type ${node.shaderType}`);
+                    throw new WTypeError(node.origin.originString, `Semantic ${item.semantic} is unacceptable as an ${direction} of shader type ${node.shaderType}`);
             }
         }
         checkSemanticForShaderType(inputGatherer.result, "input");
index 703d0c2..be28420 100644 (file)
@@ -75,7 +75,7 @@
 {
     JSValue *compileFunction = [self.context objectForKeyedSubscript:@"whlslToMsl"];
     if (compileFunction) {
-        JSValue * result = [compileFunction callWithArguments:@[whlslSource]];
+        JSValue *result = [compileFunction callWithArguments:@[whlslSource]];
         if (result) {
             if ([result hasProperty:@"_error"] && [result hasProperty:@"_metalShaderLanguageSource"] && [result hasProperty:@"_originalFunctionNameToMangledNames"]) {
                 if ([[result valueForProperty:@"_error"] isNull]) {
index 2419df7..fc2ebf9 100644 (file)
@@ -1,26 +1,30 @@
 struct VertexInput {
-    float2 position;
-    float2 uv;
+    float2 position : attribute(0);
+    float2 uv : attribute(1);
 }
 
 struct VertexOutput {
-    float4 wsl_Position;
-    float4 color;
+    float4 position : SV_Position;
+    float4 color : attribute(0);
+}
+
+struct FragmentInput {
+    float4 color : attribute(0);
 }
 
 struct FragmentOutput {
-    float4 wsl_Color;
+    float4 color : SV_Target0;
 }
 
 vertex VertexOutput vertexShader(VertexInput vertexInput) {
     VertexOutput result;
-    result.wsl_Position = float4(vertexInput.position, 0., 1.);
+    result.position = float4(vertexInput.position, 0., 1.);
     result.color = float4(vertexInput.uv, 0.0, 1.0);
     return result;
 }
 
-fragment FragmentOutput fragmentShader(VertexOutput stageIn) {
+fragment FragmentOutput fragmentShader(FragmentInput fragmentInput) {
     FragmentOutput result;
-    result.wsl_Color = stageIn.color;
+    result.color = fragmentInput.color;
     return result;
 }
index 9ef8ae0..c4adf6c 100644 (file)
@@ -7,6 +7,15 @@
        objects = {
 
 /* Begin PBXBuildFile section */
+               31F11709216BFE92009A36D5 /* FuncAttribute.js in Resources */ = {isa = PBXBuildFile; fileRef = 31F116C4216BFE90009A36D5 /* FuncAttribute.js */; };
+               31F1170A216BFE92009A36D5 /* BuiltInSemantic.js in Resources */ = {isa = PBXBuildFile; fileRef = 31F116C5216BFE90009A36D5 /* BuiltInSemantic.js */; };
+               31F11732216BFE93009A36D5 /* ResourceSemantic.js in Resources */ = {isa = PBXBuildFile; fileRef = 31F11704216BFE90009A36D5 /* ResourceSemantic.js */; };
+               31F11733216BFE93009A36D5 /* FuncNumThreadsAttribute.js in Resources */ = {isa = PBXBuildFile; fileRef = 31F11705216BFE91009A36D5 /* FuncNumThreadsAttribute.js */; };
+               31F11734216BFE93009A36D5 /* Semantic.js in Resources */ = {isa = PBXBuildFile; fileRef = 31F11706216BFE91009A36D5 /* Semantic.js */; };
+               31F11735216BFE93009A36D5 /* CheckNativeFuncStages.js in Resources */ = {isa = PBXBuildFile; fileRef = 31F11707216BFE92009A36D5 /* CheckNativeFuncStages.js */; };
+               31F11736216BFE93009A36D5 /* SpecializationConstantSemantic.js in Resources */ = {isa = PBXBuildFile; fileRef = 31F11708216BFE92009A36D5 /* SpecializationConstantSemantic.js */; };
+               31F11776216BFEEC009A36D5 /* StageInOutSemantic.js in Resources */ = {isa = PBXBuildFile; fileRef = 31F11737216BFEEB009A36D5 /* StageInOutSemantic.js */; };
+               31F1179F216BFF07009A36D5 /* MSLInsertTrapParameter.js in Resources */ = {isa = PBXBuildFile; fileRef = 31F1179E216BFF07009A36D5 /* MSLInsertTrapParameter.js */; };
                E906B04621139B7700AD1C5E /* Julia.whlsl in Resources */ = {isa = PBXBuildFile; fileRef = E906B04521139B7700AD1C5E /* Julia.whlsl */; };
                E921D6362138C02600775099 /* OperatorAnderIndexer.js in Resources */ = {isa = PBXBuildFile; fileRef = E921D6322138C02600775099 /* OperatorAnderIndexer.js */; };
                E921D6372138C02600775099 /* MatrixType.js in Resources */ = {isa = PBXBuildFile; fileRef = E921D6332138C02600775099 /* MatrixType.js */; };
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
+               31F116C4216BFE90009A36D5 /* FuncAttribute.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = FuncAttribute.js; path = ../../../FuncAttribute.js; sourceTree = "<group>"; };
+               31F116C5216BFE90009A36D5 /* BuiltInSemantic.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = BuiltInSemantic.js; path = ../../../BuiltInSemantic.js; sourceTree = "<group>"; };
+               31F11704216BFE90009A36D5 /* ResourceSemantic.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = ResourceSemantic.js; path = ../../../ResourceSemantic.js; sourceTree = "<group>"; };
+               31F11705216BFE91009A36D5 /* FuncNumThreadsAttribute.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = FuncNumThreadsAttribute.js; path = ../../../FuncNumThreadsAttribute.js; sourceTree = "<group>"; };
+               31F11706216BFE91009A36D5 /* Semantic.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = Semantic.js; path = ../../../Semantic.js; sourceTree = "<group>"; };
+               31F11707216BFE92009A36D5 /* CheckNativeFuncStages.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = CheckNativeFuncStages.js; path = ../../../CheckNativeFuncStages.js; sourceTree = "<group>"; };
+               31F11708216BFE92009A36D5 /* SpecializationConstantSemantic.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = SpecializationConstantSemantic.js; path = ../../../SpecializationConstantSemantic.js; sourceTree = "<group>"; };
+               31F11737216BFEEB009A36D5 /* StageInOutSemantic.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = StageInOutSemantic.js; path = ../../../StageInOutSemantic.js; sourceTree = "<group>"; };
+               31F1179E216BFF07009A36D5 /* MSLInsertTrapParameter.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = MSLInsertTrapParameter.js; path = ../../MSLInsertTrapParameter.js; sourceTree = "<group>"; };
                E906B04521139B7700AD1C5E /* Julia.whlsl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Julia.whlsl; sourceTree = "<group>"; };
                E921D6322138C02600775099 /* OperatorAnderIndexer.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = OperatorAnderIndexer.js; path = ../../../OperatorAnderIndexer.js; sourceTree = "<group>"; };
                E921D6332138C02600775099 /* MatrixType.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = MatrixType.js; path = ../../../MatrixType.js; sourceTree = "<group>"; };
                                E95569B020F56CD600F5CF34 /* Break.js */,
                                E921D6342138C02600775099 /* BuiltinMatrixGetter.js */,
                                E921D6352138C02600775099 /* BuiltinMatrixSetter.js */,
+                               31F116C5216BFE90009A36D5 /* BuiltInSemantic.js */,
                                E941ACB92134A5BB00392BA9 /* BuiltinVectorGetter.js */,
                                E941ACBC2134A5BB00392BA9 /* BuiltinVectorSetter.js */,
                                E95569BF20F56CD700F5CF34 /* CallExpression.js */,
                                E95569C120F56CD700F5CF34 /* Checker.js */,
                                E95569B620F56CD600F5CF34 /* CheckLiteralTypes.js */,
                                E95569B320F56CD600F5CF34 /* CheckLoops.js */,
+                               31F11707216BFE92009A36D5 /* CheckNativeFuncStages.js */,
                                E94C06FA20F56CA300672992 /* CheckRecursion.js */,
                                E95569BB20F56CD600F5CF34 /* CheckRecursiveTypes.js */,
                                E95569B220F56CD600F5CF34 /* CheckReturns.js */,
                                E95569EB20F56D0500F5CF34 /* FoldConstexprs.js */,
                                E9FCEB5A20F56D93009B3629 /* ForLoop.js */,
                                E9FCEB5520F56D92009B3629 /* Func.js */,
+                               31F116C4216BFE90009A36D5 /* FuncAttribute.js */,
                                E95569E820F56D0500F5CF34 /* FuncDef.js */,
+                               31F11705216BFE91009A36D5 /* FuncNumThreadsAttribute.js */,
                                E95569E920F56D0500F5CF34 /* FuncParameter.js */,
                                E95569E620F56D0500F5CF34 /* FunctionLikeBlock.js */,
                                E94C06FB20F56CA300672992 /* HighZombieFinder.js */,
                                E92789AC213F3364001EA73E /* MSLFunctionDeclaration.js */,
                                E92789AB213F3364001EA73E /* MSLFunctionDefinition.js */,
                                E973E5C7213F3385005D79FC /* MSLFunctionForwardDeclaration.js */,
+                               31F1179E216BFF07009A36D5 /* MSLInsertTrapParameter.js */,
                                E97ED7E1214B822900AD1140 /* MSLNameMangler.js */,
                                E97ED7E4214B822900AD1140 /* MSLNativeFunctionCall.js */,
                                E973E5C8213F3385005D79FC /* MSLStatementEmitter.js */,
                                E92D103820F56E4F00D776B2 /* ResolveOverloadImpl.js */,
                                E92D103620F56E4F00D776B2 /* ResolveProperties.js */,
                                E92D103720F56E4F00D776B2 /* ResolveTypeDefs.js */,
+                               31F11704216BFE90009A36D5 /* ResourceSemantic.js */,
                                E92D103E20F56E6100D776B2 /* Return.js */,
                                E92D104020F56E6200D776B2 /* ReturnChecker.js */,
                                E92D104220F56E6200D776B2 /* ReturnException.js */,
                                E92D104120F56E6200D776B2 /* Rewriter.js */,
                                E9D7CB9D214B82B800F1C918 /* Sampler.js */,
+                               31F11706216BFE91009A36D5 /* Semantic.js */,
+                               31F11708216BFE92009A36D5 /* SpecializationConstantSemantic.js */,
+                               31F11737216BFEEB009A36D5 /* StageInOutSemantic.js */,
                                E92D103F20F56E6200D776B2 /* StandardLibrary.js */,
                                E92D104820F56E7300D776B2 /* StatementCloner.js */,
                                E92D104920F56E7300D776B2 /* StructLayoutBuilder.js */,
                        isa = PBXNativeTarget;
                        buildConfigurationList = E94C06EA20F56A4200672992 /* Build configuration list for PBXNativeTarget "WHLSL Tests" */;
                        buildPhases = (
-                               E925653C21234AA1001A89D9 /* ShellScript */,
                                E94C06BC20F56A4000672992 /* Sources */,
                                E94C06BD20F56A4000672992 /* Frameworks */,
                                E94C06BE20F56A4000672992 /* Resources */,
                        };
                        buildConfigurationList = E94C06BB20F56A4000672992 /* Build configuration list for PBXProject "WHLSL Tests" */;
                        compatibilityVersion = "Xcode 9.3";
-                       developmentRegion = en;
+                       developmentRegion = English;
                        hasScannedForEncodings = 0;
                        knownRegions = (
                                en,
                                E92D111F20F7060E00D776B2 /* Break.js in Resources */,
                                E921D6382138C02600775099 /* BuiltinMatrixGetter.js in Resources */,
                                E921D6392138C02600775099 /* BuiltinMatrixSetter.js in Resources */,
+                               31F1170A216BFE92009A36D5 /* BuiltInSemantic.js in Resources */,
                                E941ACCA2134A5BC00392BA9 /* BuiltinVectorGetter.js in Resources */,
                                E941ACCD2134A5BC00392BA9 /* BuiltinVectorSetter.js in Resources */,
                                E92D112020F7060E00D776B2 /* CallExpression.js in Resources */,
                                E92D112320F7060E00D776B2 /* Checker.js in Resources */,
                                E92D112420F7060E00D776B2 /* CheckLiteralTypes.js in Resources */,
                                E92D112520F7060E00D776B2 /* CheckLoops.js in Resources */,
+                               31F11735216BFE93009A36D5 /* CheckNativeFuncStages.js in Resources */,
                                E92D112620F7060E00D776B2 /* CheckRecursion.js in Resources */,
                                E92D112720F7060E00D776B2 /* CheckRecursiveTypes.js in Resources */,
                                E92D112820F7060E00D776B2 /* CheckReturns.js in Resources */,
                                E92D114B20F7060E00D776B2 /* FoldConstexprs.js in Resources */,
                                E92D114C20F7060E00D776B2 /* ForLoop.js in Resources */,
                                E92D114D20F7060E00D776B2 /* Func.js in Resources */,
+                               31F11709216BFE92009A36D5 /* FuncAttribute.js in Resources */,
                                E92D114E20F7060E00D776B2 /* FuncDef.js in Resources */,
+                               31F11733216BFE93009A36D5 /* FuncNumThreadsAttribute.js in Resources */,
                                E92D115020F7060E00D776B2 /* FuncParameter.js in Resources */,
                                E92D115120F7060E00D776B2 /* FunctionLikeBlock.js in Resources */,
                                E92D115220F7060E00D776B2 /* HighZombieFinder.js in Resources */,
                                E973E5DE213F341D005D79FC /* MSLFunctionDeclaration.js in Resources */,
                                E973E5DF213F341D005D79FC /* MSLFunctionDefinition.js in Resources */,
                                E973E5CE213F3385005D79FC /* MSLFunctionForwardDeclaration.js in Resources */,
+                               31F1179F216BFF07009A36D5 /* MSLInsertTrapParameter.js in Resources */,
                                E9D7CBA8214B9E5F00F1C918 /* MSLNameMangler.js in Resources */,
                                E9D7CBA9214B9E5F00F1C918 /* MSLNativeFunctionCall.js in Resources */,
                                E973E5CF213F3385005D79FC /* MSLStatementEmitter.js in Resources */,
                                E92D118320F7060E00D776B2 /* ResolveOverloadImpl.js in Resources */,
                                E92D118420F7060E00D776B2 /* ResolveProperties.js in Resources */,
                                E92D118520F7060E00D776B2 /* ResolveTypeDefs.js in Resources */,
+                               31F11732216BFE93009A36D5 /* ResourceSemantic.js in Resources */,
                                E92D118620F7060E00D776B2 /* Return.js in Resources */,
                                E92D118720F7060E00D776B2 /* ReturnChecker.js in Resources */,
                                E92D118820F7060E00D776B2 /* ReturnException.js in Resources */,
                                E92D118920F7060E00D776B2 /* Rewriter.js in Resources */,
                                E9D7CBA3214B82B800F1C918 /* Sampler.js in Resources */,
+                               31F11734216BFE93009A36D5 /* Semantic.js in Resources */,
+                               31F11736216BFE93009A36D5 /* SpecializationConstantSemantic.js in Resources */,
+                               31F11776216BFEEC009A36D5 /* StageInOutSemantic.js in Resources */,
                                E92D118A20F7060E00D776B2 /* StandardLibrary.js in Resources */,
                                E92D118B20F7060E00D776B2 /* StatementCloner.js in Resources */,
                                E92D118C20F7060E00D776B2 /* StructLayoutBuilder.js in Resources */,
                };
 /* End PBXResourcesBuildPhase section */
 
-/* Begin PBXShellScriptBuildPhase section */
-               E925653C21234AA1001A89D9 /* ShellScript */ = {
-                       isa = PBXShellScriptBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                       );
-                       inputFileListPaths = (
-                       );
-                       inputPaths = (
-                       );
-                       outputFileListPaths = (
-                       );
-                       outputPaths = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-                       shellPath = /bin/sh;
-                       shellScript = "# Type a script or drag a script file from your workspace to insert its path.\ncd \"$SRCROOT/..\"\ntsc\n";
-               };
-/* End PBXShellScriptBuildPhase section */
-
 /* Begin PBXSourcesBuildPhase section */
                E94C06BC20F56A4000672992 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
diff --git a/Tools/WebGPUShadingLanguageRI/Metal/WhlslToMsl.html b/Tools/WebGPUShadingLanguageRI/Metal/WhlslToMsl.html
new file mode 100644 (file)
index 0000000..59f93d7
--- /dev/null
@@ -0,0 +1,296 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style type="text/css">
+body {
+    padding: 0;
+    margin: 0;
+    font-family: -apple-system;
+}
+h1 {
+    padding: 20px 20px;
+    text-align: center;
+    font-size: 50px;
+}
+main {
+    margin: 0 auto;
+    padding: 20px;
+    display: grid;
+    grid-template-columns: 45% 45%;
+    grid-column-gap: 10px;
+    grid-template-rows: auto 500px auto;
+    grid-row-gap: 10px;
+    justify-content: center;
+}
+textarea {
+    padding: 5px;
+    margin: 0;
+    font-family: monospace;
+    font-size: 20px;
+    overflow: scroll;
+}
+#output {
+    padding: 5px;
+    margin: 0;
+    font-family: monospace;
+    overflow: scroll;
+    border: 1px solid #888;
+    box-sizing: border-box;
+    font-size: 20px;
+}
+#controls {
+    padding: 5px;
+    margin: 0;
+    text-align: center;
+}
+button {
+    width: 200px;
+    font-size: 20px;
+    background: linear-gradient(to bottom, #aae, #aaf);
+    border: 1px solid #ccd;
+    border-radius: 3px;
+}
+button:active {
+    background: linear-gradient(to bottom, #dde, #eef);
+    color: black;
+}
+</style>
+<script src="../Node.js"></script>
+<script src="../Type.js"></script>
+<script src="../ReferenceType.js"></script>
+<script src="../Value.js"></script>
+<script src="../Expression.js"></script>
+<script src="../Rewriter.js"></script>
+<script src="../Visitor.js"></script>
+<script src="../CreateLiteral.js"></script>
+<script src="../CreateLiteralType.js"></script>
+<script src="../PropertyAccessExpression.js"></script>
+<script src="../NativeType.js"></script>
+<script src="../Semantic.js"></script>
+<script src="../AddressSpace.js"></script>
+<script src="../AllocateAtEntryPoints.js"></script>
+<script src="../AnonymousVariable.js"></script>
+<script src="../ArrayRefType.js"></script>
+<script src="../ArrayType.js"></script>
+<script src="../Assignment.js"></script>
+<script src="../AutoWrapper.js"></script>
+<script src="../Block.js"></script>
+<script src="../BoolLiteral.js"></script>
+<script src="../Break.js"></script>
+<script src="../BuiltInSemantic.js"></script>
+<script src="../BuiltinMatrixGetter.js"></script>
+<script src="../BuiltinMatrixSetter.js"></script>
+<script src="../BuiltinVectorGetter.js"></script>
+<script src="../BuiltinVectorSetter.js"></script>
+<script src="../CallExpression.js"></script>
+<script src="../CallFunction.js"></script>
+<script src="../Casts.js"></script>
+<script src="../Check.js"></script>
+<script src="../CheckLiteralTypes.js"></script>
+<script src="../CheckLoops.js"></script>
+<script src="../CheckNativeFuncStages.js"></script>
+<script src="../CheckRecursion.js"></script>
+<script src="../CheckRecursiveTypes.js"></script>
+<script src="../CheckReturns.js"></script>
+<script src="../CheckTypesWithArguments.js"></script>
+<script src="../CheckUnreachableCode.js"></script>
+<script src="../CheckWrapped.js"></script>
+<script src="../Checker.js"></script>
+<script src="../CloneProgram.js"></script>
+<script src="../CommaExpression.js"></script>
+<script src="../ConstexprFolder.js"></script>
+<script src="../Continue.js"></script>
+<script src="../ConvertPtrToArrayRefExpression.js"></script>
+<script src="../DoWhileLoop.js"></script>
+<script src="../DotExpression.js"></script>
+<script src="../DereferenceExpression.js"></script>
+<script src="../EArrayRef.js"></script>
+<script src="../EBuffer.js"></script>
+<script src="../EBufferBuilder.js"></script>
+<script src="../EPtr.js"></script>
+<script src="../EnumLiteral.js"></script>
+<script src="../EnumMember.js"></script>
+<script src="../EnumType.js"></script>
+<script src="../EvaluationCommon.js"></script>
+<script src="../Evaluator.js"></script>
+<script src="../ExpressionFinder.js"></script>
+<script src="../ExternalOrigin.js"></script>
+<script src="../Field.js"></script>
+<script src="../FindHighZombies.js"></script>
+<script src="../FlattenedStructOffsetGatherer.js"></script>
+<script src="../FloatLiteral.js"></script>
+<script src="../FloatLiteralType.js"></script>
+<script src="../FoldConstexprs.js"></script>
+<script src="../ForLoop.js"></script>
+<script src="../Func.js"></script>
+<script src="../FuncAttribute.js"></script>
+<script src="../FuncDef.js"></script>
+<script src="../FuncNumThreadsAttribute.js"></script>
+<script src="../FuncParameter.js"></script>
+<script src="../FunctionLikeBlock.js"></script>
+<script src="../HighZombieFinder.js"></script>
+<script src="../IdentityExpression.js"></script>
+<script src="../IfStatement.js"></script>
+<script src="../IndexExpression.js"></script>
+<script src="../InferTypesForCall.js"></script>
+<script src="../Inline.js"></script>
+<script src="../Inliner.js"></script>
+<script src="../IntLiteral.js"></script>
+<script src="../IntLiteralType.js"></script>
+<script src="../Intrinsics.js"></script>
+<script src="../LayoutBuffers.js"></script>
+<script src="../Lexer.js"></script>
+<script src="../LexerToken.js"></script>
+<script src="../LiteralTypeChecker.js"></script>
+<script src="../LogicalExpression.js"></script>
+<script src="../LogicalNot.js"></script>
+<script src="../LoopChecker.js"></script>
+<script src="../MakeArrayRefExpression.js"></script>
+<script src="../MakePtrExpression.js"></script>
+<script src="../MatrixType.js"></script>
+<script src="../NameContext.js"></script>
+<script src="../NameFinder.js"></script>
+<script src="../NameResolver.js"></script>
+<script src="../NativeFunc.js"></script>
+<script src="../NormalUsePropertyResolver.js"></script>
+<script src="../NullLiteral.js"></script>
+<script src="../NullType.js"></script>
+<script src="../OperatorAnderIndexer.js"></script>
+<script src="../OperatorArrayRefLength.js"></script>
+<script src="../OriginKind.js"></script>
+<script src="../OverloadResolutionFailure.js"></script>
+<script src="../Parse.js"></script>
+<script src="../Prepare.js"></script>
+<script src="../PropertyResolver.js"></script>
+<script src="../Program.js"></script>
+<script src="../ProgramWithUnnecessaryThingsRemoved.js"></script>
+<script src="../PtrType.js"></script>
+<script src="../ReadModifyWriteExpression.js"></script>
+<script src="../RecursionChecker.js"></script>
+<script src="../RecursiveTypeChecker.js"></script>
+<script src="../ResolveNames.js"></script>
+<script src="../ResolveOverloadImpl.js"></script>
+<script src="../ResolveProperties.js"></script>
+<script src="../ResolveTypeDefs.js"></script>
+<script src="../ResourceSemantic.js"></script>
+<script src="../Return.js"></script>
+<script src="../ReturnChecker.js"></script>
+<script src="../ReturnException.js"></script>
+<script src="../Sampler.js"></script>
+<script src="../SpecializationConstantSemantic.js"></script>
+<script src="../StageInOutSemantic.js"></script>
+<script src="../StandardLibrary.js"></script>
+<script src="../StatementCloner.js"></script>
+<script src="../StructLayoutBuilder.js"></script>
+<script src="../StructType.js"></script>
+<script src="../SwitchCase.js"></script>
+<script src="../SwitchStatement.js"></script>
+<script src="../SynthesizeArrayOperatorLength.js"></script>
+<script src="../SynthesizeEnumFunctions.js"></script>
+<script src="../SynthesizeStructAccessors.js"></script>
+<script src="../SynthesizeCopyConstructorOperator.js"></script>
+<script src="../SynthesizeDefaultConstructorOperator.js"></script>
+<script src="../TernaryExpression.js"></script>
+<script src="../Texture.js"></script>
+<script src="../TextureOperations.js"></script>
+<script src="../TrapStatement.js"></script>
+<script src="../TypeDef.js"></script>
+<script src="../TypeDefResolver.js"></script>
+<script src="../TypeRef.js"></script>
+<script src="../TypeOverloadResolutionFailure.js"></script>
+<script src="../TypedValue.js"></script>
+<script src="../UintLiteral.js"></script>
+<script src="../UintLiteralType.js"></script>
+<script src="../UnificationContext.js"></script>
+<script src="../UnreachableCodeChecker.js"></script>
+<script src="../VariableDecl.js"></script>
+<script src="../VariableRef.js"></script>
+<script src="../VectorType.js"></script>
+<script src="../VisitingSet.js"></script>
+<script src="../WLexicalError.js"></script>
+<script src="../WSyntaxError.js"></script>
+<script src="../WTrapError.js"></script>
+<script src="../WTypeError.js"></script>
+<script src="../WhileLoop.js"></script>
+<script src="../WrapChecker.js"></script>
+
+<script src="MSLBackend.js"></script>
+<script src="MSLCompileResult.js"></script>
+<script src="MSLConstexprEmitter.js"></script>
+<script src="MSLFunctionDeclaration.js"></script>
+<script src="MSLFunctionDefinition.js"></script>
+<script src="MSLFunctionForwardDeclaration.js"></script>
+<script src="MSLInsertTrapParameter.js"></script>
+<script src="MSLNameMangler.js"></script>
+<script src="MSLNativeFunctionCall.js"></script>
+<script src="MSLStatementEmitter.js"></script>
+<script src="MSLTypeAttributesMap.js"></script>
+<script src="MSLTypeAttributes.js"></script>
+<script src="MSLTypeUnifier.js"></script>
+<script src="TypeOf.js"></script>
+<script src="WhlslToMsl.js"></script>
+<script>
+function init() {
+    let b = document.querySelector("button");
+    b.addEventListener("click", compile);
+}
+
+function compile() {
+    let source = document.querySelector("textarea").value;
+    let output = document.querySelector("#output");
+    output.textContent = "Compiling...";
+    let result = whlslToMsl(source);
+    output.textContent = JSON.stringify(result);
+}
+
+window.addEventListener("load", init, false);
+</script>
+</head>
+<body>
+<header>
+<h1>WHLSL to MSL</h1>   
+</header>
+<main>
+<h2>WHSL Source</h2>
+<h2>Compiled Output</h2>
+<textarea id="source">
+struct VertexInput {
+    float2 position : attribute(0);
+    float2 uv : attribute(1);
+}
+
+struct VertexOutput {
+    float4 position : SV_Position;
+    float4 color : attribute(0);
+}
+
+struct FragmentInput {
+    float4 color : attribute(0);
+}
+
+struct FragmentOutput {
+    float4 color : SV_Target0;
+}
+
+vertex VertexOutput vertexShader(VertexInput vertexInput) {
+    VertexOutput result;
+    result.position = float4(vertexInput.position, 0., 1.);
+    result.color = float4(vertexInput.uv, 0.0, 1.0);
+    return result;
+}
+
+fragment FragmentOutput fragmentShader(FragmentInput fragmentInput) {
+    FragmentOutput result;
+    result.color = fragmentInput.color;
+    return result;
+}
+</textarea>
+<div id="output">
+No compiled output.
+</div>
+<div id="controls">
+<button>Compile</button>
+</div>
+</main>
+</body>
+</html>
\ No newline at end of file