WebKit Bugzilla
Attachment 371417 Details for
Bug 195808
: [WHLSL] Implement loop expressions
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch for landing
c-backup.diff (text/plain), 78.88 KB, created by
Saam Barati
on 2019-06-05 10:12:15 PDT
(
hide
)
Description:
patch for landing
Filename:
MIME Type:
Creator:
Saam Barati
Created:
2019-06-05 10:12:15 PDT
Size:
78.88 KB
patch
obsolete
>Index: Source/WebCore/ChangeLog >=================================================================== >--- Source/WebCore/ChangeLog (revision 246112) >+++ Source/WebCore/ChangeLog (working copy) >@@ -1,3 +1,108 @@ >+2019-06-05 Saam Barati <sbarati@apple.com> >+ >+ [WHLSL] Implement loop expressions >+ https://bugs.webkit.org/show_bug.cgi?id=195808 >+ <rdar://problem/50746309> >+ >+ Reviewed by Myles Maxfield. >+ >+ This patch makes continue/break break for "do/while/for" loops >+ in WHLSL. Because of the way we emit code where every expression >+ turns into a Metal statement, it's not convenient to emit native >+ Metal loop constructs. Instead, we model break/continue as if >+ we had goto. >+ >+ For example, this WHLSL program: >+ ``` >+ for (INIT; COND; INC) { >+ if (b) >+ continue; >+ if (b2) >+ break; >+ } >+ ``` >+ would become something like: >+ ``` >+ INIT; >+ while (1) { >+ if (!COND) >+ break; >+ if (b) >+ goto increment; >+ if (b2) >+ goto exit; >+ increment: >+ INC; >+ } >+ exit: >+ ``` >+ >+ However, Metal doesn't have goto, so we model goto using a run-once >+ loop and a variable indicating if we should break out early. This >+ "break out early" variable is initially set to false. We "should >+ break out early" when executing a WHLSL "break" statement. "continue" >+ is modeled as breaking out of the run-once loop, but not touching the >+ "break out early" variable. "break" is modeled as setting the "break >+ out early" variable to true, followed by breaking out of the run-once loop. >+ The above WHLSL will turn into this Metal: >+ ``` >+ bool breakOutOfCurrentLoop = false; >+ INIT; >+ while (1) { >+ if (!COND) >+ break; >+ do { >+ if (b) { >+ // WHLSL 'continue' >+ break; >+ } >+ if (b2) { >+ // WHLSL 'break' >+ breakOutOfCurrentLoop = true; >+ break; >+ } >+ } while (0); >+ if (breakOutOfCurrentLoop) >+ break; >+ INC; >+ } >+ ``` >+ >+ This patch also found a bug with ForLoop where it held a Variant<VariableDeclarationsStatement, Expression>. >+ This is invalid to do since we mutate the AST in place. This means some phase >+ could replace VariableDeclarationsStatement with some other Statement, and >+ we'd be breaking the C++ type system. So this patch migrates ForLoop to hold >+ a statement instead. In general, AST nodes that point to other AST nodes >+ should use broad types unless we know apriori that a certain type will >+ never be replaced. >+ >+ Tests: webgpu/whlsl-do-while-loop-break.html >+ webgpu/whlsl-do-while-loop-continue.html >+ webgpu/whlsl-do-while-loop.html >+ webgpu/whlsl-loops-break.html >+ webgpu/whlsl-loops-continue.html >+ webgpu/whlsl-loops.html >+ webgpu/whlsl-nested-loop.html >+ webgpu/whlsl-while-loop-break.html >+ webgpu/whlsl-while-loop-continue.html >+ >+ * Modules/webgpu/WHLSL/AST/WHLSLForLoop.h: >+ (WebCore::WHLSL::AST::ForLoop::ForLoop): >+ (WebCore::WHLSL::AST::ForLoop::initialization): >+ * Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp: >+ (WebCore::WHLSL::Metal::FunctionDefinitionWriter::visit): >+ (WebCore::WHLSL::Metal::FunctionDefinitionWriter::emitLoop): >+ * Modules/webgpu/WHLSL/WHLSLASTDumper.cpp: >+ (WebCore::WHLSL::ASTDumper::visit): >+ * Modules/webgpu/WHLSL/WHLSLChecker.cpp: >+ (WebCore::WHLSL::Checker::visit): >+ * Modules/webgpu/WHLSL/WHLSLParser.cpp: >+ (WebCore::WHLSL::Parser::parseForLoop): >+ * Modules/webgpu/WHLSL/WHLSLPrepare.cpp: >+ * Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt: >+ * Modules/webgpu/WHLSL/WHLSLVisitor.cpp: >+ (WebCore::WHLSL::Visitor::visit): >+ > 2019-06-05 Truitt Savell <tsavell@apple.com> > > Unreviewed, rolling out r246052. >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp (revision 246112) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp (working copy) >@@ -413,8 +413,8 @@ void ASTDumper::visit(AST::DoWhileLoop& > void ASTDumper::visit(AST::ForLoop& forLoop) > { > m_out.print("for ("); >- WTF::visit(WTF::makeVisitor([&](AST::VariableDeclarationsStatement& variableDeclarationsStatement) { >- visit(variableDeclarationsStatement); >+ WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) { >+ visit(statement); > }, [&](UniqueRef<AST::Expression>& expression) { > visit(expression); > }), forLoop.initialization()); >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp (revision 246112) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp (working copy) >@@ -1189,8 +1189,8 @@ void Checker::visit(AST::DoWhileLoop& do > > void Checker::visit(AST::ForLoop& forLoop) > { >- WTF::visit(WTF::makeVisitor([&](AST::VariableDeclarationsStatement& variableDeclarationsStatement) { >- checkErrorAndVisit(variableDeclarationsStatement); >+ WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) { >+ checkErrorAndVisit(statement); > }, [&](UniqueRef<AST::Expression>& expression) { > checkErrorAndVisit(expression); > }), forLoop.initialization()); >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp (revision 246112) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp (working copy) >@@ -1414,7 +1414,7 @@ auto Parser::parseForLoop() -> Expected< > if (!origin) > return Unexpected<Error>(origin.error()); > >- auto parseRemainder = [&](Variant<AST::VariableDeclarationsStatement, UniqueRef<AST::Expression>>&& initialization) -> Expected<AST::ForLoop, Error> { >+ auto parseRemainder = [&](Variant<UniqueRef<AST::Statement>, UniqueRef<AST::Expression>>&& initialization) -> Expected<AST::ForLoop, Error> { > auto semicolon = consumeType(Lexer::Token::Type::Semicolon); > if (!semicolon) > return Unexpected<Error>(semicolon.error()); >@@ -1453,8 +1453,10 @@ auto Parser::parseForLoop() -> Expected< > auto variableDeclarations = backtrackingScope<Expected<AST::VariableDeclarationsStatement, Error>>([&]() { > return parseVariableDeclarations(); > }); >- if (variableDeclarations) >- return parseRemainder(WTFMove(*variableDeclarations)); >+ if (variableDeclarations) { >+ UniqueRef<AST::Statement> declarationStatement = makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)); >+ return parseRemainder(WTFMove(declarationStatement)); >+ } > > auto effectfulExpression = parseEffectfulExpression(); > if (!effectfulExpression) >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp (revision 246112) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp (working copy) >@@ -57,7 +57,7 @@ namespace WHLSL { > > static constexpr bool dumpASTBeforeEachPass = false; > static constexpr bool dumpASTAfterParsing = false; >-static constexpr bool dumpASTAtEnd = true; >+static constexpr bool dumpASTAtEnd = false; > static constexpr bool alwaysDumpPassFailures = false; > static constexpr bool dumpPassFailure = dumpASTBeforeEachPass || dumpASTAfterParsing || dumpASTAtEnd || alwaysDumpPassFailures; > >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt (revision 246112) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt (working copy) >@@ -384,6 +384,14 @@ native float4 operator.y=(float4, float) > native float4 operator.z=(float4, float); > native float4 operator.w=(float4, float); > >+native float operator+(float, float); >+native float operator-(float, float); >+native int operator+(int, int); >+native uint operator+(uint, uint); >+native bool operator<(int, int); >+native bool operator<(uint, uint); >+native bool operator<(float, float); >+ > native float ddx(float); > native float ddy(float); > native void AllMemoryBarrierWithGroupSync(); >Index: Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp (revision 246112) >+++ Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp (working copy) >@@ -434,8 +434,8 @@ void Visitor::visit(AST::Fallthrough&) > > void Visitor::visit(AST::ForLoop& forLoop) > { >- WTF::visit(WTF::makeVisitor([&](AST::VariableDeclarationsStatement& variableDeclarationsStatement) { >- checkErrorAndVisit(variableDeclarationsStatement); >+ WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) { >+ checkErrorAndVisit(statement); > }, [&](UniqueRef<AST::Expression>& expression) { > checkErrorAndVisit(expression); > }), forLoop.initialization()); >Index: Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h (revision 246112) >+++ Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h (working copy) >@@ -44,7 +44,7 @@ namespace AST { > > class ForLoop : public Statement { > public: >- ForLoop(Lexer::Token&& origin, Variant<VariableDeclarationsStatement, UniqueRef<Expression>>&& initialization, Optional<UniqueRef<Expression>>&& condition, Optional<UniqueRef<Expression>>&& increment, UniqueRef<Statement>&& body) >+ ForLoop(Lexer::Token&& origin, Variant<UniqueRef<Statement>, UniqueRef<Expression>>&& initialization, Optional<UniqueRef<Expression>>&& condition, Optional<UniqueRef<Expression>>&& increment, UniqueRef<Statement>&& body) > : Statement(WTFMove(origin)) > , m_initialization(WTFMove(initialization)) > , m_condition(WTFMove(condition)) >@@ -62,13 +62,13 @@ public: > > bool isForLoop() const override { return true; } > >- Variant<VariableDeclarationsStatement, UniqueRef<Expression>>& initialization() { return m_initialization; } >+ Variant<UniqueRef<Statement>, UniqueRef<Expression>>& initialization() { return m_initialization; } > Expression* condition() { return m_condition ? &*m_condition : nullptr; } > Expression* increment() { return m_increment ? &*m_increment : nullptr; } > Statement& body() { return m_body; } > > private: >- Variant<VariableDeclarationsStatement, UniqueRef<Expression>> m_initialization; >+ Variant<UniqueRef<Statement>, UniqueRef<Expression>> m_initialization; > Optional<UniqueRef<Expression>> m_condition; > Optional<UniqueRef<Expression>> m_increment; > UniqueRef<Statement> m_body; >Index: Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp >=================================================================== >--- Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp (revision 246112) >+++ Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp (working copy) >@@ -35,6 +35,7 @@ > #include "WHLSLTypeNamer.h" > #include "WHLSLVisitor.h" > #include <wtf/HashMap.h> >+#include <wtf/SetForScope.h> > #include <wtf/text/StringBuilder.h> > > namespace WebCore { >@@ -139,6 +140,12 @@ protected: > void visit(AST::TernaryExpression&) override; > void visit(AST::VariableReference&) override; > >+ enum class LoopConditionLocation { >+ BeforeBody, >+ AfterBody >+ }; >+ void emitLoop(LoopConditionLocation, AST::Expression* conditionExpression, AST::Expression* increment, AST::Statement& body); >+ > String constantExpressionString(AST::ConstantExpression&); > > String generateNextVariableName() >@@ -155,6 +162,7 @@ protected: > std::unique_ptr<EntryPointScaffolding> m_entryPointScaffolding; > Layout& m_layout; > unsigned m_variableCount { 0 }; >+ String m_breakOutOfCurrentLoopEarlyVariable; > }; > > void FunctionDefinitionWriter::visit(AST::NativeFunctionDeclaration& nativeFunctionDeclaration) >@@ -224,22 +232,15 @@ void FunctionDefinitionWriter::visit(AST > > void FunctionDefinitionWriter::visit(AST::Break&) > { >+ ASSERT(m_breakOutOfCurrentLoopEarlyVariable.length()); >+ m_stringBuilder.append(makeString(m_breakOutOfCurrentLoopEarlyVariable, " = true;\n")); > m_stringBuilder.append("break;\n"); > } > > void FunctionDefinitionWriter::visit(AST::Continue&) > { >- // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195808 Figure out which loop we're in, and run the increment code >- notImplemented(); >-} >- >-void FunctionDefinitionWriter::visit(AST::DoWhileLoop& doWhileLoop) >-{ >- m_stringBuilder.append("do {\n"); >- checkErrorAndVisit(doWhileLoop.body()); >- checkErrorAndVisit(doWhileLoop.conditional()); >- m_stringBuilder.append(makeString("if (!", m_stack.takeLast(), ") break;\n")); >- m_stringBuilder.append(makeString("} while(true);\n")); >+ ASSERT(m_breakOutOfCurrentLoopEarlyVariable.length()); >+ m_stringBuilder.append("break;\n"); > } > > void FunctionDefinitionWriter::visit(AST::EffectfulExpressionStatement& effectfulExpressionStatement) >@@ -253,25 +254,61 @@ void FunctionDefinitionWriter::visit(AST > m_stringBuilder.append("[[clang::fallthrough]];\n"); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=195808 Make sure this is okay. Alternatively, we could do nothing and just return here instead. > } > >+void FunctionDefinitionWriter::emitLoop(LoopConditionLocation loopConditionLocation, AST::Expression* conditionExpression, AST::Expression* increment, AST::Statement& body) >+{ >+ SetForScope<String> loopVariableScope(m_breakOutOfCurrentLoopEarlyVariable, generateNextVariableName()); >+ >+ m_stringBuilder.append(makeString("bool ", m_breakOutOfCurrentLoopEarlyVariable, " = false;\n")); >+ >+ m_stringBuilder.append("while (true) {\n"); >+ >+ if (loopConditionLocation == LoopConditionLocation::BeforeBody && conditionExpression) { >+ checkErrorAndVisit(*conditionExpression); >+ m_stringBuilder.append(makeString("if (!", m_stack.takeLast(), ") break;\n")); >+ } >+ >+ m_stringBuilder.append("do {\n"); >+ checkErrorAndVisit(body); >+ m_stringBuilder.append("} while(false); \n"); >+ m_stringBuilder.append(makeString("if (", m_breakOutOfCurrentLoopEarlyVariable, ") break;\n")); >+ >+ if (increment) { >+ checkErrorAndVisit(*increment); >+ // Expression results get pushed to m_stack. We don't use the result >+ // of increment, so we dispense of that now. >+ m_stack.takeLast(); >+ } >+ >+ if (loopConditionLocation == LoopConditionLocation::AfterBody && conditionExpression) { >+ checkErrorAndVisit(*conditionExpression); >+ m_stringBuilder.append(makeString("if (!", m_stack.takeLast(), ") break;\n")); >+ } >+ >+ m_stringBuilder.append("} \n"); >+} >+ >+void FunctionDefinitionWriter::visit(AST::DoWhileLoop& doWhileLoop) >+{ >+ emitLoop(LoopConditionLocation::AfterBody, &doWhileLoop.conditional(), nullptr, doWhileLoop.body()); >+} >+ >+void FunctionDefinitionWriter::visit(AST::WhileLoop& whileLoop) >+{ >+ emitLoop(LoopConditionLocation::BeforeBody, &whileLoop.conditional(), nullptr, whileLoop.body()); >+} >+ > void FunctionDefinitionWriter::visit(AST::ForLoop& forLoop) > { >- WTF::visit(WTF::makeVisitor([&](AST::VariableDeclarationsStatement& variableDeclarationsStatement) { >- checkErrorAndVisit(variableDeclarationsStatement); >+ m_stringBuilder.append("{\n"); >+ >+ WTF::visit(WTF::makeVisitor([&](AST::Statement& statement) { >+ checkErrorAndVisit(statement); > }, [&](UniqueRef<AST::Expression>& expression) { > checkErrorAndVisit(expression); > m_stack.takeLast(); // We don't need to do anything with the result. > }), forLoop.initialization()); > >- m_stringBuilder.append("for ( ; ; ) {\n"); >- if (forLoop.condition()) { >- checkErrorAndVisit(*forLoop.condition()); >- m_stringBuilder.append(makeString("if (!", m_stack.takeLast(), ") break;\n")); >- } >- checkErrorAndVisit(forLoop.body()); >- if (forLoop.increment()) { >- checkErrorAndVisit(*forLoop.increment()); >- m_stack.takeLast(); >- } >+ emitLoop(LoopConditionLocation::BeforeBody, forLoop.condition(), forLoop.increment(), forLoop.body()); > m_stringBuilder.append("}\n"); > } > >@@ -333,15 +370,6 @@ void FunctionDefinitionWriter::visit(AST > Visitor::visit(variableDeclarationsStatement); > } > >-void FunctionDefinitionWriter::visit(AST::WhileLoop& whileLoop) >-{ >- m_stringBuilder.append(makeString("while (true) {\n")); >- checkErrorAndVisit(whileLoop.conditional()); >- m_stringBuilder.append(makeString("if (!", m_stack.takeLast(), ") break;\n")); >- checkErrorAndVisit(whileLoop.body()); >- m_stringBuilder.append("}\n"); >-} >- > void FunctionDefinitionWriter::visit(AST::IntegerLiteral& integerLiteral) > { > auto variableName = generateNextVariableName(); >Index: LayoutTests/ChangeLog >=================================================================== >--- LayoutTests/ChangeLog (revision 246112) >+++ LayoutTests/ChangeLog (working copy) >@@ -1,3 +1,30 @@ >+2019-06-05 Saam Barati <sbarati@apple.com> >+ >+ [WHLSL] Implement loop expressions >+ https://bugs.webkit.org/show_bug.cgi?id=195808 >+ <rdar://problem/50746309> >+ >+ Reviewed by Myles Maxfield. >+ >+ * webgpu/whlsl-do-while-loop-break-expected.html: Added. >+ * webgpu/whlsl-do-while-loop-break.html: Added. >+ * webgpu/whlsl-do-while-loop-continue-expected.html: Added. >+ * webgpu/whlsl-do-while-loop-continue.html: Added. >+ * webgpu/whlsl-do-while-loop-expected.html: Added. >+ * webgpu/whlsl-do-while-loop.html: Added. >+ * webgpu/whlsl-loops-break-expected.html: Added. >+ * webgpu/whlsl-loops-break.html: Added. >+ * webgpu/whlsl-loops-continue-expected.html: Added. >+ * webgpu/whlsl-loops-continue.html: Added. >+ * webgpu/whlsl-loops-expected.html: Added. >+ * webgpu/whlsl-loops.html: Added. >+ * webgpu/whlsl-nested-loop-expected.html: Added. >+ * webgpu/whlsl-nested-loop.html: Added. >+ * webgpu/whlsl-while-loop-break-expected.html: Added. >+ * webgpu/whlsl-while-loop-break.html: Added. >+ * webgpu/whlsl-while-loop-continue-expected.html: Added. >+ * webgpu/whlsl-while-loop-continue.html: Added. >+ > 2019-06-05 Shawn Roberts <sroberts@apple.com> > > http/tests/websocket/tests/hybi/handshake-ok-with-legacy-websocket-response-headers.html is a flaky failure on Mojave >Index: LayoutTests/webgpu/whlsl-do-while-loop-break-expected.html >=================================================================== >--- LayoutTests/webgpu/whlsl-do-while-loop-break-expected.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-do-while-loop-break-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "black"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-do-while-loop-break.html >=================================================================== >--- LayoutTests/webgpu/whlsl-do-while-loop-break.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-do-while-loop-break.html (working copy) >@@ -0,0 +1,133 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ >+ bool b = true; >+ do { >+ if (b) { >+ break; >+ } >+ } while ((shade = 1.0, false)); >+ >+ result.position = position; >+ result.shade = shade; >+ >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4", offset: 0}; >+ const attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 0.0; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 0.0; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 0.0; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 0.0; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-do-while-loop-continue-expected.html >=================================================================== >--- LayoutTests/webgpu/whlsl-do-while-loop-continue-expected.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-do-while-loop-continue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-do-while-loop-continue.html >=================================================================== >--- LayoutTests/webgpu/whlsl-do-while-loop-continue.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-do-while-loop-continue.html (working copy) >@@ -0,0 +1,135 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ >+ bool b = true; >+ uint i = 0; >+ do { >+ if (b) { >+ continue; >+ } >+ shade = 0.0; >+ } while ((i = i + 1, shade = shade + 0.1, i < 10)); >+ >+ result.position = position; >+ result.shade = shade; >+ >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4", offset: 0}; >+ const attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 0.0; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 0.0; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 0.0; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 0.0; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-do-while-loop-expected.html >=================================================================== >--- LayoutTests/webgpu/whlsl-do-while-loop-expected.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-do-while-loop-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-do-while-loop.html >=================================================================== >--- LayoutTests/webgpu/whlsl-do-while-loop.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-do-while-loop.html (working copy) >@@ -0,0 +1,130 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ >+ do { >+ shade = 1.0; >+ } while(false); >+ >+ result.position = position; >+ result.shade = shade; >+ >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4", offset: 0}; >+ const attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 0.0; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 0.0; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 0.0; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 0.0; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-loops-break-expected.html >=================================================================== >--- LayoutTests/webgpu/whlsl-loops-break-expected.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-loops-break-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "black"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-loops-break.html >=================================================================== >--- LayoutTests/webgpu/whlsl-loops-break.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-loops-break.html (working copy) >@@ -0,0 +1,134 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ >+ bool b = true; >+ for (uint i = 0; i < 10; (i = i + 1, shade = shade + 1.0)) { >+ if (b) { >+ break; >+ } >+ shade = shade + 1.0; >+ } >+ >+ result.position = position; >+ result.shade = shade; >+ >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4", offset: 0}; >+ const attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 0.0; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 0.0; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 0.0; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 0.0; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-loops-continue-expected.html >=================================================================== >--- LayoutTests/webgpu/whlsl-loops-continue-expected.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-loops-continue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "black"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-loops-continue.html >=================================================================== >--- LayoutTests/webgpu/whlsl-loops-continue.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-loops-continue.html (working copy) >@@ -0,0 +1,134 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ >+ bool b = true; >+ for (uint i = 0; i < 10; i = i + 1) { >+ if (b) { >+ continue; >+ } >+ shade = shade + 1.0; >+ } >+ >+ result.position = position; >+ result.shade = shade; >+ >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4", offset: 0}; >+ const attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 0.0; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 0.0; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 0.0; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 0.0; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-loops-expected.html >=================================================================== >--- LayoutTests/webgpu/whlsl-loops-expected.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-loops-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-loops.html >=================================================================== >--- LayoutTests/webgpu/whlsl-loops.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-loops.html (working copy) >@@ -0,0 +1,130 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ >+ for (uint i = 0; i < 10; i = i + 1) { >+ shade = shade + 0.1; >+ } >+ >+ result.position = position; >+ result.shade = shade; >+ >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4", offset: 0}; >+ const attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 0.1; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 0.1; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 0.1; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 0.1; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-nested-loop-expected.html >=================================================================== >--- LayoutTests/webgpu/whlsl-nested-loop-expected.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-nested-loop-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "black"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-nested-loop.html >=================================================================== >--- LayoutTests/webgpu/whlsl-nested-loop.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-nested-loop.html (working copy) >@@ -0,0 +1,166 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ >+ bool b = true; >+ for (uint i = 0; i < 10; i = i + 1) { >+ while (true) { >+ if (b) { >+ break; >+ } >+ shade = 1.0; >+ } >+ >+ do { >+ if (b) { >+ break; >+ } >+ } while ((shade = 1.0, false)); >+ >+ do { >+ if (b) { >+ continue; >+ } >+ } while ((shade = shade + 1.0, false)); >+ >+ do { >+ if (b) { >+ continue; >+ } >+ } while ((shade = shade - 1.0, false)); >+ >+ while ((shade = shade + 1.0, true)) { >+ if (b) { >+ break; >+ } >+ } >+ >+ while ((shade = shade - 1.0, true)) { >+ if (b) { >+ break; >+ } >+ } >+ } >+ >+ result.position = position; >+ result.shade = shade; >+ >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4", offset: 0}; >+ const attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 0.0; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 0.0; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 0.0; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 0.0; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-while-loop-break-expected.html >=================================================================== >--- LayoutTests/webgpu/whlsl-while-loop-break-expected.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-while-loop-break-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "black"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-while-loop-break.html >=================================================================== >--- LayoutTests/webgpu/whlsl-while-loop-break.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-while-loop-break.html (working copy) >@@ -0,0 +1,136 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ >+ bool b = true; >+ uint i = 0; >+ while (i < 10) { >+ if (b) { >+ break; >+ } >+ shade = shade + 1.0; >+ i = i + 1; >+ } >+ >+ result.position = position; >+ result.shade = shade; >+ >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4", offset: 0}; >+ const attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 0.0; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 0.0; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 0.0; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 0.0; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-while-loop-continue-expected.html >=================================================================== >--- LayoutTests/webgpu/whlsl-while-loop-continue-expected.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-while-loop-continue-expected.html (working copy) >@@ -0,0 +1,19 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+async function start() { >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("2d"); >+ context.fillStyle = "blue"; >+ context.fillRect(0, 0, 400, 400); >+ context.fillStyle = "white"; >+ context.fillRect(100, 100, 200, 200); >+} >+window.addEventListener("load", start); >+</script> >+</body> >+</html> >Index: LayoutTests/webgpu/whlsl-while-loop-continue.html >=================================================================== >--- LayoutTests/webgpu/whlsl-while-loop-continue.html (nonexistent) >+++ LayoutTests/webgpu/whlsl-while-loop-continue.html (working copy) >@@ -0,0 +1,136 @@ >+<!DOCTYPE html> >+<html> >+<head> >+</head> >+<body> >+<canvas id="canvas" width="400" height="400"></canvas> >+<script> >+const shaderSource = ` >+struct VertexOut { >+ float4 position : SV_Position; >+ float shade : attribute(0); >+} >+ >+vertex VertexOut vertexShader(float4 position : attribute(0), float shade : attribute(1)) { >+ VertexOut result; >+ >+ bool b = true; >+ uint i = 0; >+ while ((shade = shade + 0.1, i < 10)) { >+ if (b) { >+ i = i + 1; >+ continue; >+ } >+ shade = 0.0; >+ } >+ >+ result.position = position; >+ result.shade = shade; >+ >+ return result; >+} >+ >+fragment float4 fragmentShader(float shade : attribute(0)) : SV_Target 0 { >+ return float4(shade, shade, shade, 1.0); >+} >+`; >+async function start() { >+ const adapter = await navigator.gpu.requestAdapter(); >+ const device = await adapter.requestDevice(); >+ >+ const shaderModule = device.createShaderModule({code: shaderSource, isWHLSL: true}); >+ const vertexStage = {module: shaderModule, entryPoint: "vertexShader"}; >+ const fragmentStage = {module: shaderModule, entryPoint: "fragmentShader"}; >+ const primitiveTopology = "triangle-strip"; >+ const rasterizationState = {frontFace: "cw", cullMode: "none"}; >+ const alphaBlend = {}; >+ const colorBlend = {}; >+ const colorStates = [{format: "rgba8unorm", alphaBlend, colorBlend, writeMask: 15}]; // GPUColorWriteBits.ALL >+ const depthStencilState = null; >+ >+ const attribute0 = {shaderLocation: 0, format: "float4", offset: 0}; >+ const attribute1 = {shaderLocation: 1, format: "float", offset: 16}; >+ const attributes = [attribute0, attribute1]; >+ const input0 = {stride: 20, attributeSet: attributes}; >+ const inputs = [input0]; >+ const vertexInput = {vertexBuffers: inputs}; >+ >+ const bindGroupLayoutDescriptor = {bindings: [{binding: 0, visibility: 7, type: "uniform-buffer"}]}; >+ const bindGroupLayout = device.createBindGroupLayout(bindGroupLayoutDescriptor); >+ const pipelineLayoutDescriptor = {bindGroupLayouts: [bindGroupLayout]}; >+ const pipelineLayout = device.createPipelineLayout(pipelineLayoutDescriptor); >+ >+ const renderPipelineDescriptor = {vertexStage, fragmentStage, primitiveTopology, rasterizationState, colorStates, depthStencilState, vertexInput, sampleCount: 1, layout: pipelineLayout}; >+ const renderPipeline = device.createRenderPipeline(renderPipelineDescriptor); >+ >+ const vertexBuffer0Descriptor = {size: Float32Array.BYTES_PER_ELEMENT * 5 * 4, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.MAP_WRITE}; >+ const vertexBuffer0 = device.createBuffer(vertexBuffer0Descriptor); >+ const vertexBuffer0ArrayBuffer = await vertexBuffer0.mapWriteAsync(); >+ const vertexBuffer0Float32Array = new Float32Array(vertexBuffer0ArrayBuffer); >+ vertexBuffer0Float32Array[0] = -0.5; >+ vertexBuffer0Float32Array[1] = -0.5; >+ vertexBuffer0Float32Array[2] = 1.0; >+ vertexBuffer0Float32Array[3] = 1.0; >+ vertexBuffer0Float32Array[4] = 0.1; >+ >+ vertexBuffer0Float32Array[5] = -0.5; >+ vertexBuffer0Float32Array[6] = 0.5; >+ vertexBuffer0Float32Array[7] = 1.0; >+ vertexBuffer0Float32Array[8] = 1.0; >+ vertexBuffer0Float32Array[9] = 0.1; >+ >+ vertexBuffer0Float32Array[10] = 0.5; >+ vertexBuffer0Float32Array[11] = -0.5; >+ vertexBuffer0Float32Array[12] = 1.0; >+ vertexBuffer0Float32Array[13] = 1.0; >+ vertexBuffer0Float32Array[14] = 0.1; >+ >+ vertexBuffer0Float32Array[15] = 0.5; >+ vertexBuffer0Float32Array[16] = 0.5; >+ vertexBuffer0Float32Array[17] = 1.0; >+ vertexBuffer0Float32Array[18] = 1.0; >+ vertexBuffer0Float32Array[19] = 0.1; >+ vertexBuffer0.unmap(); >+ >+ const resourceBufferDescriptor = {size: Float32Array.BYTES_PER_ELEMENT, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.MAP_WRITE}; >+ const resourceBuffer = device.createBuffer(resourceBufferDescriptor); >+ const resourceBufferArrayBuffer = await resourceBuffer.mapWriteAsync(); >+ const resourceBufferFloat32Array = new Float32Array(resourceBufferArrayBuffer); >+ resourceBufferFloat32Array[0] = 1; >+ resourceBuffer.unmap(); >+ >+ const bufferBinding = {buffer: resourceBuffer, size: 4}; >+ const bindGroupBinding = {binding: 0, resource: bufferBinding}; >+ const bindGroupDescriptor = {layout: bindGroupLayout, bindings: [bindGroupBinding]}; >+ const bindGroup = device.createBindGroup(bindGroupDescriptor); >+ >+ const canvas = document.getElementById("canvas"); >+ const context = canvas.getContext("gpu"); >+ const swapChainDescriptor = {device, format: "bgra8unorm"}; >+ const swapChain = context.configureSwapChain(swapChainDescriptor); >+ const outputTexture = swapChain.getCurrentTexture(); >+ const outputTextureView = outputTexture.createDefaultView(); >+ >+ const commandEncoder = device.createCommandEncoder(); // {} >+ const red = {r: 0, g: 0, b: 1, a: 1}; >+ const colorAttachments = [{attachment: outputTextureView, resolveTarget: null, loadOp: "clear", storeOp: "store", clearColor: red}]; >+ const depthStencilAttachment = null; >+ const renderPassDescriptor = {colorAttachments, depthStencilAttachment}; >+ const renderPassEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); >+ renderPassEncoder.setPipeline(renderPipeline); >+ renderPassEncoder.setBindGroup(0, bindGroup); >+ renderPassEncoder.setVertexBuffers(0, [vertexBuffer0], [0]); >+ renderPassEncoder.draw(4, 1, 0, 0); >+ renderPassEncoder.endPass(); >+ const commandBuffer = commandEncoder.finish(); >+ device.getQueue().submit([commandBuffer]); >+ >+ if (window.testRunner) >+ testRunner.notifyDone(); >+} >+if (window.testRunner) >+ testRunner.waitUntilDone(); >+window.addEventListener("load", start); >+</script> >+</body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 195808
:
371103
| 371417