Diff
Modified: trunk/Tools/ChangeLog (236454 => 236455)
--- trunk/Tools/ChangeLog 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/ChangeLog 2018-09-25 06:36:04 UTC (rev 236455)
@@ -1,3 +1,44 @@
+2018-09-24 Myles C. Maxfield <[email protected]>
+
+ [WHLSL] Not all functions should be able to run in all shader stages
+ https://bugs.webkit.org/show_bug.cgi?id=189121
+
+ Reviewed by Filip Pizlo.
+
+ ddx() and ddy() can only run in fragment shaders, and the barrier functions can only run in compute shaders.
+ ddx_coarse() & friends are currently implemented as just calling ddx(), so we only need to modify those functions
+ if/when we make them native.
+
+ The texture sampling functions that use implicit derivatives can run in any shader stage - they just use a LOD of
+ 0. Therefore, those functions are unchanged.
+
+ * WebGPUShadingLanguageRI/All.js:
+ * WebGPUShadingLanguageRI/Intrinsics.js:
+ * WebGPUShadingLanguageRI/LateChecker.js:
+ (LateChecker.prototype._checkShaderType):
+ * WebGPUShadingLanguageRI/NativeFunc.js:
+ (NativeFunc):
+ (NativeFunc.prototype.get stage):
+ (NativeFunc.prototype.toDeclString):
+ * WebGPUShadingLanguageRI/Parse.js:
+ (parseFuncDecl):
+ (parseNativeFunc):
+ (parseNative):
+ * WebGPUShadingLanguageRI/Prepare.js:
+ (let.prepare):
+ * WebGPUShadingLanguageRI/SPIRV.html:
+ * WebGPUShadingLanguageRI/StandardLibrary.js:
+ (let.standardLibrary):
+ * WebGPUShadingLanguageRI/StatementCloner.js:
+ (StatementCloner.prototype.visitNativeFunc):
+ * WebGPUShadingLanguageRI/Test.html:
+ * WebGPUShadingLanguageRI/Test.js:
+ (tests.shaderStages):
+ * WebGPUShadingLanguageRI/WSyntaxError.js:
+ (WSyntaxError.prototype.toString):
+ (WSyntaxError):
+ * WebGPUShadingLanguageRI/index.html:
+
2018-09-24 Thomas Denney <[email protected]>
[WHLSL] Implement trap statements in Metal code generation
Modified: trunk/Tools/WebGPUShadingLanguageRI/All.js (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/All.js 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/All.js 2018-09-25 06:36:04 UTC (rev 236455)
@@ -56,6 +56,7 @@
load("Check.js");
load("CheckLiteralTypes.js");
load("CheckLoops.js");
+load("CheckNativeFuncStages.js");
load("CheckRecursion.js");
load("CheckRecursiveTypes.js");
load("CheckReturns.js");
Copied: trunk/Tools/WebGPUShadingLanguageRI/CheckNativeFuncStages.js (from rev 236454, trunk/Tools/WebGPUShadingLanguageRI/NativeFunc.js) (0 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/CheckNativeFuncStages.js (rev 0)
+++ trunk/Tools/WebGPUShadingLanguageRI/CheckNativeFuncStages.js 2018-09-25 06:36:04 UTC (rev 236455)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+"use strict";
+
+function checkNativeFuncStages(program)
+{
+ class CheckNativeFuncStages extends Visitor {
+ constructor(entryPoint) {
+ super();
+ this._entryPoint = entryPoint;
+ }
+
+ visitCallExpression(node)
+ {
+ if ((node.func instanceof NativeFunc) && node.func.stage && node.func.stage != this._entryPoint.shaderType)
+ throw new WTypeError(node.origin, `Cannot call ${node.func.stage} function ${node.func.name} inside ${this._entryPoint.shadeType} entry point`);
+ node.func.visit(this);
+ }
+ }
+ for (let [name, funcDefs] of program.functions) {
+ for (let funcDef of funcDefs) {
+ if (funcDef.isEntryPoint)
+ funcDef.visit(new CheckNativeFuncStages(funcDef));
+ }
+ }
+}
Modified: trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js 2018-09-25 06:36:04 UTC (rev 236455)
@@ -715,13 +715,13 @@
});
this._map.set(
- "native float ddx(float)",
+ "native fragment float ddx(float)",
func => {
func.implementation = ([value]) => EPtr.box(0);
});
this._map.set(
- "native float ddy(float)",
+ "native fragment float ddy(float)",
func => {
func.implementation = ([value]) => EPtr.box(0);
});
@@ -822,19 +822,19 @@
});
this._map.set(
- "native void AllMemoryBarrierWithGroupSync()",
+ "native compute void AllMemoryBarrierWithGroupSync()",
func => {
func.implementation = function() {};
});
this._map.set(
- "native void DeviceMemoryBarrierWithGroupSync()",
+ "native compute void DeviceMemoryBarrierWithGroupSync()",
func => {
func.implementation = function() {};
});
this._map.set(
- "native void GroupMemoryBarrierWithGroupSync()",
+ "native compute void GroupMemoryBarrierWithGroupSync()",
func => {
func.implementation = function() {};
});
Modified: trunk/Tools/WebGPUShadingLanguageRI/LateChecker.js (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/LateChecker.js 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/LateChecker.js 2018-09-25 06:36:04 UTC (rev 236455)
@@ -72,6 +72,8 @@
break;
case "compute":
break;
+ case "compute":
+ break;
case "test":
break;
default:
Modified: trunk/Tools/WebGPUShadingLanguageRI/NativeFunc.js (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/NativeFunc.js 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/NativeFunc.js 2018-09-25 06:36:04 UTC (rev 236455)
@@ -25,9 +25,10 @@
"use strict";
class NativeFunc extends Func {
- constructor(origin, name, returnType, parameters, isCast, shaderType)
+ constructor(origin, name, returnType, parameters, isCast, shaderType, stage = null)
{
super(origin, name, returnType, parameters, isCast, shaderType);
+ this._stage = stage;
this.isRestricted = false;
this.implementation = null;
this._implementationData = null;
@@ -35,6 +36,7 @@
}
get isNative() { return true; }
+ get stage() { return this._stage; }
get implementationData() { return this._implementationData; }
set implementationData(newImplData) { this._implementationData = newImplData; }
@@ -41,7 +43,11 @@
toDeclString()
{
- return "native " + super.toDeclString();
+ let result = "native ";
+ if (this.stage)
+ result += `${this.stage} `;
+ result += super.toDeclString();
+ return result;
}
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/Parse.js (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/Parse.js 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/Parse.js 2018-09-25 06:36:04 UTC (rev 236455)
@@ -1290,7 +1290,7 @@
return result;
}
- function parseNativeFunc()
+ function parseNativeFunc(stage = null)
{
let func = parseFuncDecl();
if (func instanceof WSyntaxError)
@@ -1300,7 +1300,7 @@
let maybeError = consume(";");
if (maybeError instanceof WSyntaxError)
return maybeError;
- return new NativeFunc(func.origin, func.name, func.returnType, func.parameters, func.isCast, func.shaderType);
+ return new NativeFunc(func.origin, func.name, func.returnType, func.parameters, func.isCast, func.shaderType, stage);
}
function parseNative()
@@ -1320,7 +1320,10 @@
return maybeError;
return NativeType.create(origin, name.text, args);
}
- return parseNativeFunc();
+ let stage = tryConsume("vertex", "fragment", "compute");
+ if (stage)
+ stage = stage.text;
+ return parseNativeFunc(stage);
}
function parseRestrictedFuncDef()
Modified: trunk/Tools/WebGPUShadingLanguageRI/Prepare.js (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/Prepare.js 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/Prepare.js 2018-09-25 06:36:04 UTC (rev 236455)
@@ -70,6 +70,7 @@
allocateAtEntryPoints(program);
program.visit(new StructLayoutBuilder());
lateCheckAndLayoutBuffers(program);
+ checkNativeFuncStages(program);
if (shouldInline)
inline(program);
return program;
Modified: trunk/Tools/WebGPUShadingLanguageRI/SPIRV.html (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/SPIRV.html 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/SPIRV.html 2018-09-25 06:36:04 UTC (rev 236455)
@@ -39,6 +39,7 @@
<script src=""
<script src=""
<script src=""
+ <script src=""
<script src=""
<script src=""
<script src=""
Modified: trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js 2018-09-25 06:36:04 UTC (rev 236455)
@@ -803,7 +803,8 @@
// These functions are unary floating-point scalar functions,
// which can also be applied to vectors and matrices component-wise.
(function() {
- let nativeFunctions = [`cos`, `sin`, `tan`, `acos`, `asin`, `atan`, `cosh`, `sinh`, `tanh`, `ceil`, `exp`, `floor`, `log`, `round`, `trunc`, `ddx`, `ddy`];
+ let nativeFunctions = [`cos`, `sin`, `tan`, `acos`, `asin`, `atan`, `cosh`, `sinh`, `tanh`, `ceil`, `exp`, `floor`, `log`, `round`, `trunc`];
+ let nativeFragmentFunctions = [`ddx`, `ddy`];
let nonNativeFunctions = [`sqrt`, `log2`, `log10`, `frac`, `exp2`, `degrees`, `radians`, `rcp`, `rsqrt`, `saturate`, `ddx_coarse`, `ddx_fine`, `ddy_coarse`, `ddy_fine`, `fwidth`];
for (let nativeFunction of nativeFunctions) {
@@ -813,6 +814,13 @@
print(`}`);
}
+ for (let nativeFunction of nativeFragmentFunctions) {
+ print(`native fragment float ${nativeFunction}(float);`);
+ print(`half ${nativeFunction}(half x) {`);
+ print(` return half(${nativeFunction}(float(x)));`);
+ print(`}`);
+ }
+
for (let type of [`half`, `float`]) {
print(`${type} sqrt(${type} x) {`);
print(` return pow(x, 0.5);`);
@@ -860,7 +868,7 @@
print(` return abs(ddx(x)) + abs(ddy(x));`);
print(`}`);
- for (let outputFunction of nativeFunctions.concat(nonNativeFunctions)) {
+ for (let outputFunction of nativeFunctions.concat(nativeFragmentFunctions.concat(nonNativeFunctions))) {
for (let size of [2, 3, 4]) {
print(`${type}${size} ${outputFunction}(${type}${size} x) {`);
print(` ${type}${size} result;`);
@@ -1786,9 +1794,9 @@
}
print();
- print(`native void AllMemoryBarrierWithGroupSync();`);
- print(`native void DeviceMemoryBarrierWithGroupSync();`);
- print(`native void GroupMemoryBarrierWithGroupSync();`);
+ print(`native compute void AllMemoryBarrierWithGroupSync();`);
+ print(`native compute void DeviceMemoryBarrierWithGroupSync();`);
+ print(`native compute void GroupMemoryBarrierWithGroupSync();`);
print();
for (let type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
@@ -1910,6 +1918,8 @@
}
print();
+ // You might think that the sampling functions that rely on implicit derivatives can't be called in vertex shaders.
+ // However, they do work; they just a level of 0.
for (let type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
for (let length of [``, `2`, `3`, `4`]) {
print(`native ${type}${length} Sample(Texture1D<${type}${length}>, sampler, float location);`);
Modified: trunk/Tools/WebGPUShadingLanguageRI/StatementCloner.js (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/StatementCloner.js 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/StatementCloner.js 2018-09-25 06:36:04 UTC (rev 236455)
@@ -46,7 +46,7 @@
node.origin, node.name,
node.returnType.visit(this),
node.parameters.map(parameter => parameter.visit(this)),
- node.isCast, node.shaderType);
+ node.isCast, node.shaderType, node.stage);
result.isRestricted = node.isRestricted;
return result;
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.html (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/Test.html 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.html 2018-09-25 06:36:04 UTC (rev 236455)
@@ -33,6 +33,7 @@
<script src=""
<script src=""
<script src=""
+<script src=""
<script src=""
<script src=""
<script src=""
Modified: trunk/Tools/WebGPUShadingLanguageRI/Test.js (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/Test.js 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/Test.js 2018-09-25 06:36:04 UTC (rev 236455)
@@ -5753,6 +5753,132 @@
checkInt(program, callFunction(program, "foo", []), 354);
}
+tests.shaderStages = function()
+{
+ doPrep(`
+ struct Result {
+ float4 output;
+ }
+ fragment Result foo()
+ {
+ float x = 7;
+ float dx = ddx(x);
+ float dy = ddy(x);
+ Result r;
+ r.output = float4(1, 2, 3, 4);
+ return r;
+ }
+ `);
+ doPrep(`
+ compute void foo()
+ {
+ AllMemoryBarrierWithGroupSync();
+ DeviceMemoryBarrierWithGroupSync();
+ GroupMemoryBarrierWithGroupSync();
+ }
+ `);
+ checkFail(
+ () => doPrep(`
+ struct Result {
+ float4 output;
+ }
+ vertex Result foo()
+ {
+ float x = 7;
+ float dx = ddx(x);
+ float dy = ddy(x);
+ Result r;
+ r.output = float4(1, 2, 3, 4);
+ return r;
+ }
+ `),
+ e => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ struct Result {
+ float4 output;
+ }
+ vertex Result foo()
+ {
+ AllMemoryBarrierWithGroupSync();
+ Result r;
+ r.output = float4(1, 2, 3, 4);
+ return r;
+ }
+ `),
+ e => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ struct Result {
+ float4 output;
+ }
+ fragment Result foo()
+ {
+ AllMemoryBarrierWithGroupSync();
+ Result r;
+ r.output = float4(1, 2, 3, 4);
+ return r;
+ }
+ `),
+ e => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ struct Result {
+ float4 output;
+ }
+ vertex Result foo()
+ {
+ DeviceMemoryBarrierWithGroupSync();
+ Result r;
+ r.output = float4(1, 2, 3, 4);
+ return r;
+ }
+ `),
+ e => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ struct Result {
+ float4 output;
+ }
+ fragment Result foo()
+ {
+ DeviceMemoryBarrierWithGroupSync();
+ Result r;
+ r.output = float4(1, 2, 3, 4);
+ return r;
+ }
+ `),
+ e => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ struct Result {
+ float4 output;
+ }
+ vertex Result foo()
+ {
+ GroupMemoryBarrierWithGroupSync();
+ Result r;
+ r.output = float4(1, 2, 3, 4);
+ return r;
+ }
+ `),
+ e => e instanceof WTypeError);
+ checkFail(
+ () => doPrep(`
+ struct Result {
+ float4 output;
+ }
+ fragment Result foo()
+ {
+ GroupMemoryBarrierWithGroupSync();
+ Result r;
+ r.output = float4(1, 2, 3, 4);
+ return r;
+ }
+ `),
+ e => e instanceof WTypeError);
+}
+
tests.casts = function()
{
let program = doPrep(`
Modified: trunk/Tools/WebGPUShadingLanguageRI/WSyntaxError.js (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/WSyntaxError.js 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/WSyntaxError.js 2018-09-25 06:36:04 UTC (rev 236455)
@@ -31,5 +31,10 @@
this.originString = originString;
this.syntaxErrorMessage = message;
}
+
+ toString()
+ {
+ return this.payload;
+ }
}
Modified: trunk/Tools/WebGPUShadingLanguageRI/index.html (236454 => 236455)
--- trunk/Tools/WebGPUShadingLanguageRI/index.html 2018-09-25 05:12:13 UTC (rev 236454)
+++ trunk/Tools/WebGPUShadingLanguageRI/index.html 2018-09-25 06:36:04 UTC (rev 236455)
@@ -33,6 +33,7 @@
<script src=""
<script src=""
<script src=""
+<script src=""
<script src=""
<script src=""
<script src=""