<!DOCTYPE html><html><head><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="AddressSpace.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="CallExpression.js"></script><script src="CallFunction.js"></script><script src="Check.js"></script><script src="CheckLiteralTypes.js"></script><script src="CheckLoops.js"></script><script src="CheckRecursion.js"></script><script src="CheckRecursiveTypes.js"></script><script src="CheckReturns.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="ConstexprTypeParameter.js"></script><script src="Continue.js"></script><script src="ConvertPtrToArrayRefExpression.js"></script><script src="DoWhileLoop.js"></script><script src="DotExpression.js"></script><script src="DoubleLiteral.js"></script><script src="DoubleLiteralType.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="FlattenProtocolExtends.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="FuncDef.js"></script><script src="FuncInstantiator.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="InstantiateImmediates.js"></script><script src="IntLiteral.js"></script><script src="IntLiteralType.js"></script><script src="Intrinsics.js"></script><script src="LateChecker.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="NameContext.js"></script><script src="NameFinder.js"></script><script src="NameResolver.js"></script><script src="NativeFunc.js"></script><script src="NativeFuncInstance.js"></script><script src="NativeType.js"></script><script src="NativeTypeInstance.js"></script><script src="NormalUsePropertyResolver.js"></script><script src="NullLiteral.js"></script><script src="NullType.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="Protocol.js"></script><script src="ProtocolDecl.js"></script><script src="ProtocolFuncDecl.js"></script><script src="ProtocolRef.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="Return.js"></script><script src="ReturnChecker.js"></script><script src="ReturnException.js"></script><script src="StandardLibrary.js"></script><script src="StatementCloner.js"></script><script src="StructLayoutBuilder.js"></script><script src="StructType.js"></script><script src="Substitution.js"></script><script src="SwitchCase.js"></script><script src="SwitchStatement.js"></script><script src="SynthesizeEnumFunctions.js"></script><script src="SynthesizeStructAccessors.js"></script><script src="TrapStatement.js"></script><script src="TypeDef.js"></script><script src="TypeDefResolver.js"></script><script src="TypeOrVariableRef.js"></script><script src="TypeParameterRewriter.js"></script><script src="TypeRef.js"></script><script src="TypeVariable.js"></script><script src="TypeVariableTracker.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="VisitingSet.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><style>#ShaderSource {font-family: monospace;width: 700px;height: 400px;}td {border: 1px solid black;}</style><script>let defaultShaderSource = `struct VertexInput {float2 position;float3 color;}struct VertexOutput {float4 wsl_Position;float3 color;}struct FragmentOutput {float4 wsl_Color;}vertex VertexOutput vertexShader(VertexInput vertexInput) {VertexOutput result;result.wsl_Position = float4(vertexInput.position, 0., 1.);result.color = vertexInput.color;return result;}fragment FragmentOutput fragmentShader(VertexOutput stageIn) {FragmentOutput result;result.wsl_Color = float4(stageIn.color, 1.);return result;}`;let shaderSourceTextarea;let compileButton;let localStorage;let compileLogElement;let vertexShaderSelect;let fragmentShaderSelect;let dataTable;let resultTable;let program;let availableVertexShaders;let availableFragmentShaders;let currentVertexShader;let currentFragmentShader;let inlinedVertexShader;let inlinedFragmentShader;let allArgumentInfos;let argumentEPtrs;let stageInArgumentIndex;window.addEventListener("load", function() {shaderSourceTextarea = document.getElementById("ShaderSource");compileButton = document.getElementById("CompileButton");compileButton.addEventListener("click", compilePresentShaderSource);compileLogElement = document.getElementById("CompileLog");vertexShaderSelect = document.getElementById("VertexShaderSelect");fragmentShaderSelect = document.getElementById("FragmentShaderSelect");vertexShaderSelect.addEventListener("change", selectedShadersChanged);fragmentShaderSelect.addEventListener("change", selectedShadersChanged);dataTable = document.getElementById("DataTable");document.getElementById("RunButton").addEventListener("click", runShaders);resultTable = document.getElementById("ResultTable");shaderSourceTextarea.addEventListener("input", sourceCodeChanged);let shaderSource;try {localStorage = window.localStorage;shaderSource = localStorage.getItem("ShaderSource");} catch (e) {}if (!shaderSource)shaderSource = defaultShaderSource;shaderSourceTextarea.value = shaderSource;window.setTimeout(compilePresentShaderSource, 0);});function clearDataTable(){while (dataTable.lastChild instanceof HTMLTableRowElement)dataTable.removeChild(dataTable.lastChild);}function clearResultTable(){while (resultTable.lastChild instanceof HTMLTableRowElement)resultTable.removeChild(resultTable.lastChild);}function clearShaderSelect(){while (vertexShaderSelect.firstChild)vertexShaderSelect.removeChild(vertexShaderSelect.firstChild);while (fragmentShaderSelect.firstChild)fragmentShaderSelect.removeChild(fragmentShaderSelect.firstChild);}function sourceCodeChanged() {compileLogElement.textContent = "";clearShaderSelect();clearDataTable();clearResultTable();}function presentError(message) {compileLogElement.textContent = message;clearShaderSelect();clearDataTable();clearResultTable();throw new Error(message);}function compilePresentShaderSource() {compileLogElement.textContent = "Compiling...";compileButton.disabled = true;window.setTimeout(doCompilePresentShaderSource, 0);}function doCompilePresentShaderSource() {compileButton.disabled = false;let start = new Date().getTime();let result;try {result = prepare("/internal/test", 0, shaderSourceTextarea.value);} catch (e) {result = e;}let end = new Date().getTime();if (!(result instanceof Program)) {compileLogElement.textContent = result.toString();return;} elsecompileLogElement.textContent = "Compile successful!";try {shaderSource = localStorage.setItem("ShaderSource", shaderSourceTextarea.value);} catch (e) {}program = result;availableVertexShaders = [];availableFragmentShaders = [];for (let functionNames of program.functions.values()) {for (let func of functionNames) {if (func.shaderType == "vertex")availableVertexShaders.push(func);if (func.shaderType == "fragment")availableFragmentShaders.push(func);}}clearShaderSelect();function createOption(textContent) {let option = document.createElement("option");option.textContent = textContent;return option;}for (let i = 0; i < availableVertexShaders.length; ++i)vertexShaderSelect.appendChild(createOption(availableVertexShaders[i].name));for (let i = 0; i < availableFragmentShaders.length; ++i)fragmentShaderSelect.appendChild(createOption(availableFragmentShaders[i].name));selectedShadersChanged(true);}function createTableRow(name, elementCallback) {let row = document.createElement("tr");let variableCell = document.createElement("td");let valueCell = document.createElement("td");variableCell.textContent = name;valueCell.appendChild(elementCallback());row.appendChild(variableCell);row.appendChild(valueCell);return row;dataTable.appendChild(row);}function linkError(message) {compileLogElement.textContent = message + " Fix this by selecting a different pair of shaders below.";clearDataTable();clearResultTable();}function selectedShadersChanged(fromCompilation = false) {if (!fromCompilation)compileLogElement.textContent = "";currentVertexShader = availableVertexShaders[vertexShaderSelect.selectedIndex];currentFragmentShader = availableFragmentShaders[fragmentShaderSelect.selectedIndex];inlinedVertexShader = program.funcInstantiator.getUnique(currentVertexShader, []);_inlineFunction(program, inlinedVertexShader, new VisitingSet(currentVertexShader));allArgumentInfos = [];argumentEPtrs = [];for (let parameter of inlinedVertexShader.parameters) {let ePtr = new EPtr(new EBuffer(parameter.type.size), 0);argumentEPtrs.push({ePtr: ePtr, size: parameter.type.size});let gatherer = new FlattenedStructOffsetGatherer(parameter.name);parameter.visit(gatherer);for (let argumentInfo of gatherer.result) {argumentInfo.ePtr = ePtr;allArgumentInfos.push(argumentInfo);}}clearDataTable();clearResultTable();for (let info of allArgumentInfos) {dataTable.appendChild(createTableRow(info.name, function() {let input = document.createElement("input");input.addEventListener("input", clearResultTable);input.type = "text";return input;}));}let found = false;let index = 0;for (let parameter of currentFragmentShader.parameters) {if (parameter.name == "stageIn") {found = true;if (!parameter.type.equals(currentVertexShader.returnType))linkError("Vertex shader's return type needs to match the stageIn parameter of the fragment shader!");stageInArgumentIndex = index;break;}++index;}if (!found)linkError("Could not find the stageIn argument in the fragment shader!");if (func.parameters.length > 1)linkError("Fragment shaders currently don't know how to have any other arguments other than stageIn.");}function runShaders() {let func = inlinedVertexShader;let index = 0;for (let i = 0; i < dataTable.children.length; ++i) {let childElement = dataTable.children[i];if (!(childElement instanceof HTMLTableRowElement))continue;let value = childElement.children[1].firstChild.value;let argumentInfo = allArgumentInfos[index];let type = argumentInfo.type;switch (type) {case "float32":value = Math.fround(parseFloat(value));argumentInfo.ePtr.set(argumentInfo.offset, value);break;case "float64":value = parseFloat(value);break;case "int32":value = parseInt(value) | 0;break;case "uint32":value = parseInt(value) >>> 0;break;default:presentError("I don't know how to parse values of type " + type);}if (isNaN(value))presentError("Could not parse input data " + index);argumentInfo.ePtr.set(argumentInfo.offset, value);++index;}for (let i = 0; i < func.parameters.length; ++i)func.parameters[i].ePtr.copyFrom(argumentEPtrs[i].ePtr, argumentEPtrs[i].size);let result = new Evaluator(program).runFunc(func);inlinedFragmentShader = program.funcInstantiator.getUnique(currentFragmentShader, []);_inlineFunction(program, inlinedFragmentShader, new VisitingSet(currentFragmentShader));func = inlinedFragmentShader;func.parameters[stageInArgumentIndex].ePtr.copyFrom(result, func.parameters[stageInArgumentIndex].type.size);result = new Evaluator(program).runFunc(func);clearResultTable();let gatherer = new FlattenedStructOffsetGatherer(func.returnType.type.name);func.returnType.type.visit(gatherer);for (let info of gatherer.result) {resultTable.appendChild(createTableRow(info.name, function() {return document.createTextNode(result.get(info.offset));}));}}</script></head><body><h1>WebGPU Shading Language</h1><ol><li>Write a shader!<div><textarea id="ShaderSource"></textarea></div><div id="CompileLog"></div><div><input type="button" value="Compile" id="CompileButton"></div></li><li>Select your shaders<div><label>Vertex Shader <select id="VertexShaderSelect"></select></label></div><div><label>Fragment Shader <select id="FragmentShaderSelect"></select></label></div></li><li>Specify input data<table id="DataTable"><thead><tr><td>Variable</td><td>Value</td></tr></thead></table></li><li><div><input type="button" value="Run" id="RunButton"></div><table id="ResultTable"><thead><tr><td>Variable</td><td>Value</td></tr></thead></table></li></ol></body></html>