benchmarks/JetStream2/WSL/index.html (454 lines of code) (raw):

<!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; } else compileLogElement.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>