Diff
Modified: trunk/LayoutTests/ChangeLog (246120 => 246121)
--- trunk/LayoutTests/ChangeLog 2019-06-05 18:29:34 UTC (rev 246120)
+++ trunk/LayoutTests/ChangeLog 2019-06-05 18:36:29 UTC (rev 246121)
@@ -1,3 +1,30 @@
+2019-06-05 Saam Barati <[email protected]>
+
+ [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 Wenson Hsieh <[email protected]>
Upstream content mode support into open source from WebKitAdditions
Added: trunk/LayoutTests/webgpu/whlsl-do-while-loop-break-expected.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-do-while-loop-break-expected.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-do-while-loop-break-expected.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-do-while-loop-break.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-do-while-loop-break.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-do-while-loop-break.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-do-while-loop-continue-expected.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-do-while-loop-continue-expected.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-do-while-loop-continue-expected.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-do-while-loop-continue.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-do-while-loop-continue.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-do-while-loop-continue.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-do-while-loop-expected.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-do-while-loop-expected.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-do-while-loop-expected.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-do-while-loop.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-do-while-loop.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-do-while-loop.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-loops-break-expected.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-loops-break-expected.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-loops-break-expected.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-loops-break.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-loops-break.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-loops-break.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-loops-continue-expected.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-loops-continue-expected.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-loops-continue-expected.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-loops-continue.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-loops-continue.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-loops-continue.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-loops-expected.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-loops-expected.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-loops-expected.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-loops.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-loops.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-loops.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-nested-loop-expected.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-nested-loop-expected.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-nested-loop-expected.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-nested-loop.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-nested-loop.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-nested-loop.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-while-loop-break-expected.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-while-loop-break-expected.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-while-loop-break-expected.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-while-loop-break.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-while-loop-break.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-while-loop-break.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-while-loop-continue-expected.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-while-loop-continue-expected.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-while-loop-continue-expected.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Added: trunk/LayoutTests/webgpu/whlsl-while-loop-continue.html (0 => 246121)
--- trunk/LayoutTests/webgpu/whlsl-while-loop-continue.html (rev 0)
+++ trunk/LayoutTests/webgpu/whlsl-while-loop-continue.html 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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>
Modified: trunk/Source/WebCore/ChangeLog (246120 => 246121)
--- trunk/Source/WebCore/ChangeLog 2019-06-05 18:29:34 UTC (rev 246120)
+++ trunk/Source/WebCore/ChangeLog 2019-06-05 18:36:29 UTC (rev 246121)
@@ -1,3 +1,108 @@
+2019-06-05 Saam Barati <[email protected]>
+
+ [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 Wenson Hsieh <[email protected]>
Upstream content mode support into open source from WebKitAdditions
Modified: trunk/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h (246120 => 246121)
--- trunk/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h 2019-06-05 18:29:34 UTC (rev 246120)
+++ trunk/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h 2019-06-05 18:36:29 UTC (rev 246121)
@@ -44,7 +44,7 @@
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 @@
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;
Modified: trunk/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp (246120 => 246121)
--- trunk/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp 2019-06-05 18:29:34 UTC (rev 246120)
+++ trunk/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp 2019-06-05 18:36:29 UTC (rev 246121)
@@ -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 @@
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 @@
std::unique_ptr<EntryPointScaffolding> m_entryPointScaffolding;
Layout& m_layout;
unsigned m_variableCount { 0 };
+ String m_breakOutOfCurrentLoopEarlyVariable;
};
void FunctionDefinitionWriter::visit(AST::NativeFunctionDeclaration& nativeFunctionDeclaration)
@@ -224,24 +232,17 @@
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();
+ ASSERT(m_breakOutOfCurrentLoopEarlyVariable.length());
+ m_stringBuilder.append("break;\n");
}
-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"));
-}
-
void FunctionDefinitionWriter::visit(AST::EffectfulExpressionStatement& effectfulExpressionStatement)
{
checkErrorAndVisit(effectfulExpressionStatement.effectfulExpression());
@@ -253,25 +254,61 @@
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 @@
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();
Modified: trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp (246120 => 246121)
--- trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp 2019-06-05 18:29:34 UTC (rev 246120)
+++ trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp 2019-06-05 18:36:29 UTC (rev 246121)
@@ -413,8 +413,8 @@
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());
Modified: trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp (246120 => 246121)
--- trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp 2019-06-05 18:29:34 UTC (rev 246120)
+++ trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp 2019-06-05 18:36:29 UTC (rev 246121)
@@ -1189,8 +1189,8 @@
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());
Modified: trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp (246120 => 246121)
--- trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp 2019-06-05 18:29:34 UTC (rev 246120)
+++ trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp 2019-06-05 18:36:29 UTC (rev 246121)
@@ -1414,7 +1414,7 @@
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 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)
Modified: trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp (246120 => 246121)
--- trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp 2019-06-05 18:29:34 UTC (rev 246120)
+++ trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLPrepare.cpp 2019-06-05 18:36:29 UTC (rev 246121)
@@ -57,7 +57,7 @@
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;
Modified: trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt (246120 => 246121)
--- trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt 2019-06-05 18:29:34 UTC (rev 246120)
+++ trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStandardLibrary.txt 2019-06-05 18:36:29 UTC (rev 246121)
@@ -384,6 +384,14 @@
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();
Modified: trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp (246120 => 246121)
--- trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp 2019-06-05 18:29:34 UTC (rev 246120)
+++ trunk/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp 2019-06-05 18:36:29 UTC (rev 246121)
@@ -434,8 +434,8 @@
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());