⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 236455 in webkit


Ignore:
Timestamp:
Sep 24, 2018, 11:36:04 PM (8 years ago)
Author:
mmaxfield@apple.com
Message:

[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

  1. 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:
Location:
trunk/Tools
Files:
14 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r236452 r236455  
     12018-09-24  Myles C. Maxfield  <mmaxfield@apple.com>
     2
     3        [WHLSL] Not all functions should be able to run in all shader stages
     4        https://bugs.webkit.org/show_bug.cgi?id=189121
     5
     6        Reviewed by Filip Pizlo.
     7
     8        ddx() and ddy() can only run in fragment shaders, and the barrier functions can only run in compute shaders.
     9        ddx_coarse() & friends are currently implemented as just calling ddx(), so we only need to modify those functions
     10        if/when we make them native.
     11
     12        The texture sampling functions that use implicit derivatives can run in any shader stage - they just use a LOD of
     13        0. Therefore, those functions are unchanged.
     14
     15        * WebGPUShadingLanguageRI/All.js:
     16        * WebGPUShadingLanguageRI/Intrinsics.js:
     17        * WebGPUShadingLanguageRI/LateChecker.js:
     18        (LateChecker.prototype._checkShaderType):
     19        * WebGPUShadingLanguageRI/NativeFunc.js:
     20        (NativeFunc):
     21        (NativeFunc.prototype.get stage):
     22        (NativeFunc.prototype.toDeclString):
     23        * WebGPUShadingLanguageRI/Parse.js:
     24        (parseFuncDecl):
     25        (parseNativeFunc):
     26        (parseNative):
     27        * WebGPUShadingLanguageRI/Prepare.js:
     28        (let.prepare):
     29        * WebGPUShadingLanguageRI/SPIRV.html:
     30        * WebGPUShadingLanguageRI/StandardLibrary.js:
     31        (let.standardLibrary):
     32        * WebGPUShadingLanguageRI/StatementCloner.js:
     33        (StatementCloner.prototype.visitNativeFunc):
     34        * WebGPUShadingLanguageRI/Test.html:
     35        * WebGPUShadingLanguageRI/Test.js:
     36        (tests.shaderStages):
     37        * WebGPUShadingLanguageRI/WSyntaxError.js:
     38        (WSyntaxError.prototype.toString):
     39        (WSyntaxError):
     40        * WebGPUShadingLanguageRI/index.html:
     41
    1422018-09-24  Thomas Denney  <tdenney@apple.com>
    243
  • trunk/Tools/WebGPUShadingLanguageRI/All.js

    r236390 r236455  
    5757load("CheckLiteralTypes.js");
    5858load("CheckLoops.js");
     59load("CheckNativeFuncStages.js");
    5960load("CheckRecursion.js");
    6061load("CheckRecursiveTypes.js");
  • trunk/Tools/WebGPUShadingLanguageRI/CheckNativeFuncStages.js

    r236454 r236455  
    2121 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    2222 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2424 */
    2525"use strict";
    2626
    27 class NativeFunc extends Func {
    28     constructor(origin, name, returnType, parameters, isCast, shaderType)
    29     {
    30         super(origin, name, returnType, parameters, isCast, shaderType);
    31         this.isRestricted = false;
    32         this.implementation = null;
    33         this._implementationData = null;
    34         this.visitImplementationData = (implementationData, visitor) => null;
     27function checkNativeFuncStages(program)
     28{
     29    class CheckNativeFuncStages extends Visitor {
     30        constructor(entryPoint) {
     31            super();
     32            this._entryPoint = entryPoint;
     33        }
     34
     35        visitCallExpression(node)
     36        {
     37            if ((node.func instanceof NativeFunc) && node.func.stage && node.func.stage != this._entryPoint.shaderType)
     38                throw new WTypeError(node.origin, `Cannot call ${node.func.stage} function ${node.func.name} inside ${this._entryPoint.shadeType} entry point`);
     39            node.func.visit(this);
     40        }
    3541    }
    36 
    37     get isNative() { return true; }
    38 
    39     get implementationData() { return this._implementationData; }
    40     set implementationData(newImplData) { this._implementationData = newImplData; }
    41 
    42     toDeclString()
    43     {
    44         return "native " + super.toDeclString();
     42    for (let [name, funcDefs] of program.functions) {
     43        for (let funcDef of funcDefs) {
     44            if (funcDef.isEntryPoint)
     45                funcDef.visit(new CheckNativeFuncStages(funcDef));
     46        }
    4547    }
    4648}
    47 
  • trunk/Tools/WebGPUShadingLanguageRI/Intrinsics.js

    r236388 r236455  
    716716
    717717        this._map.set(
    718             "native float ddx(float)",
     718            "native fragment float ddx(float)",
    719719            func => {
    720720                func.implementation = ([value]) => EPtr.box(0);
    … …  
    722722
    723723        this._map.set(
    724             "native float ddy(float)",
     724            "native fragment float ddy(float)",
    725725            func => {
    726726                func.implementation = ([value]) => EPtr.box(0);
    … …  
    823823
    824824        this._map.set(
    825             "native void AllMemoryBarrierWithGroupSync()",
     825            "native compute void AllMemoryBarrierWithGroupSync()",
    826826            func => {
    827827                func.implementation = function() {};
    … …  
    829829
    830830        this._map.set(
    831             "native void DeviceMemoryBarrierWithGroupSync()",
     831            "native compute void DeviceMemoryBarrierWithGroupSync()",
    832832            func => {
    833833                func.implementation = function() {};
    … …  
    835835
    836836        this._map.set(
    837             "native void GroupMemoryBarrierWithGroupSync()",
     837            "native compute void GroupMemoryBarrierWithGroupSync()",
    838838            func => {
    839839                func.implementation = function() {};
  • trunk/Tools/WebGPUShadingLanguageRI/LateChecker.js

    r236390 r236455  
    7373        case "compute":
    7474            break;
     75        case "compute":
     76            break;
    7577        case "test":
    7678            break;
  • trunk/Tools/WebGPUShadingLanguageRI/NativeFunc.js

    r235469 r236455  
    2626
    2727class NativeFunc extends Func {
    28     constructor(origin, name, returnType, parameters, isCast, shaderType)
     28    constructor(origin, name, returnType, parameters, isCast, shaderType, stage = null)
    2929    {
    3030        super(origin, name, returnType, parameters, isCast, shaderType);
     31        this._stage = stage;
    3132        this.isRestricted = false;
    3233        this.implementation = null;
    … …  
    3637
    3738    get isNative() { return true; }
     39    get stage() { return this._stage; }
    3840
    3941    get implementationData() { return this._implementationData; }
    … …  
    4244    toDeclString()
    4345    {
    44         return "native " + super.toDeclString();
     46        let result = "native ";
     47        if (this.stage)
     48            result += `${this.stage} `;
     49        result += super.toDeclString();
     50        return result;
    4551    }
    4652}
  • trunk/Tools/WebGPUShadingLanguageRI/Parse.js

    r236390 r236455  
    12911291    }
    12921292
    1293     function parseNativeFunc()
     1293    function parseNativeFunc(stage = null)
    12941294    {
    12951295        let func = parseFuncDecl();
    … …  
    13011301        if (maybeError instanceof WSyntaxError)
    13021302            return maybeError;
    1303         return new NativeFunc(func.origin, func.name, func.returnType, func.parameters, func.isCast, func.shaderType);
     1303        return new NativeFunc(func.origin, func.name, func.returnType, func.parameters, func.isCast, func.shaderType, stage);
    13041304    }
    13051305
    … …  
    13211321            return NativeType.create(origin, name.text, args);
    13221322        }
    1323         return parseNativeFunc();
     1323        let stage = tryConsume("vertex", "fragment", "compute");
     1324        if (stage)
     1325            stage = stage.text;
     1326        return parseNativeFunc(stage);
    13241327    }
    13251328
  • trunk/Tools/WebGPUShadingLanguageRI/Prepare.js

    r236361 r236455  
    7171        program.visit(new StructLayoutBuilder());
    7272        lateCheckAndLayoutBuffers(program);
     73        checkNativeFuncStages(program);
    7374        if (shouldInline)
    7475            inline(program);
  • trunk/Tools/WebGPUShadingLanguageRI/SPIRV.html

    r236390 r236455  
    4040    <script src="CheckLiteralTypes.js"></script>
    4141    <script src="CheckLoops.js"></script>
     42    <script src="CheckNativeFuncStages.js"></script>
    4243    <script src="CheckRecursion.js"></script>
    4344    <script src="CheckRecursiveTypes.js"></script>
  • trunk/Tools/WebGPUShadingLanguageRI/StandardLibrary.js

    r236388 r236455  
    804804        // which can also be applied to vectors and matrices component-wise.
    805805        (function() {
    806             let nativeFunctions = [`cos`, `sin`, `tan`, `acos`, `asin`, `atan`, `cosh`, `sinh`, `tanh`, `ceil`, `exp`, `floor`, `log`, `round`, `trunc`, `ddx`, `ddy`];
     806            let nativeFunctions = [`cos`, `sin`, `tan`, `acos`, `asin`, `atan`, `cosh`, `sinh`, `tanh`, `ceil`, `exp`, `floor`, `log`, `round`, `trunc`];
     807            let nativeFragmentFunctions = [`ddx`, `ddy`];
    807808            let nonNativeFunctions = [`sqrt`, `log2`, `log10`, `frac`, `exp2`, `degrees`, `radians`, `rcp`, `rsqrt`, `saturate`, `ddx_coarse`, `ddx_fine`, `ddy_coarse`, `ddy_fine`, `fwidth`];
    808809       
    … …  
    814815            }
    815816       
     817            for (let nativeFunction of nativeFragmentFunctions) {
     818                print(`native fragment float ${nativeFunction}(float);`);
     819                print(`half ${nativeFunction}(half x) {`);
     820                print(`    return half(${nativeFunction}(float(x)));`);
     821                print(`}`);
     822            }
     823       
    816824            for (let type of [`half`, `float`]) {
    817825                print(`${type} sqrt(${type} x) {`);
    … …  
    861869                print(`}`);
    862870       
    863                 for (let outputFunction of nativeFunctions.concat(nonNativeFunctions)) {
     871                for (let outputFunction of nativeFunctions.concat(nativeFragmentFunctions.concat(nonNativeFunctions))) {
    864872                    for (let size of [2, 3, 4]) {
    865873                        print(`${type}${size} ${outputFunction}(${type}${size} x) {`);
    … …  
    17871795        print();
    17881796       
    1789         print(`native void AllMemoryBarrierWithGroupSync();`);
    1790         print(`native void DeviceMemoryBarrierWithGroupSync();`);
    1791         print(`native void GroupMemoryBarrierWithGroupSync();`);
     1797        print(`native compute void AllMemoryBarrierWithGroupSync();`);
     1798        print(`native compute void DeviceMemoryBarrierWithGroupSync();`);
     1799        print(`native compute void GroupMemoryBarrierWithGroupSync();`);
    17921800        print();
    17931801       
    … …  
    19111919        print();
    19121920
     1921        // You might think that the sampling functions that rely on implicit derivatives can't be called in vertex shaders.
     1922        // However, they do work; they just a level of 0.
    19131923        for (let type of [`uchar`, `ushort`, `uint`, `char`, `short`, `int`, `half`, `float`]) {
    19141924            for (let length of [``, `2`, `3`, `4`]) {
  • trunk/Tools/WebGPUShadingLanguageRI/StatementCloner.js

    r236390 r236455  
    4747            node.returnType.visit(this),
    4848            node.parameters.map(parameter => parameter.visit(this)),
    49             node.isCast, node.shaderType);
     49            node.isCast, node.shaderType, node.stage);
    5050        result.isRestricted = node.isRestricted;
    5151        return result;
  • trunk/Tools/WebGPUShadingLanguageRI/Test.html

    r236390 r236455  
    3434<script src="CheckLiteralTypes.js"></script>
    3535<script src="CheckLoops.js"></script>
     36<script src="CheckNativeFuncStages.js"></script>
    3637<script src="CheckRecursion.js"></script>
    3738<script src="CheckRecursiveTypes.js"></script>
  • trunk/Tools/WebGPUShadingLanguageRI/Test.js

    r236452 r236455  
    57525752    `);
    57535753    checkInt(program, callFunction(program, "foo", []), 354);
     5754}
     5755
     5756tests.shaderStages = function()
     5757{
     5758    doPrep(`
     5759        struct Result {
     5760            float4 output;
     5761        }
     5762        fragment Result foo()
     5763        {
     5764            float x = 7;
     5765            float dx = ddx(x);
     5766            float dy = ddy(x);
     5767            Result r;
     5768            r.output = float4(1, 2, 3, 4);
     5769            return r;
     5770        }
     5771    `);
     5772    doPrep(`
     5773        compute void foo()
     5774        {
     5775            AllMemoryBarrierWithGroupSync();
     5776            DeviceMemoryBarrierWithGroupSync();
     5777            GroupMemoryBarrierWithGroupSync();
     5778        }
     5779    `);
     5780    checkFail(
     5781        () => doPrep(`
     5782            struct Result {
     5783                float4 output;
     5784            }
     5785            vertex Result foo()
     5786            {
     5787                float x = 7;
     5788                float dx = ddx(x);
     5789                float dy = ddy(x);
     5790                Result r;
     5791                r.output = float4(1, 2, 3, 4);
     5792                return r;
     5793            }
     5794        `),
     5795        e => e instanceof WTypeError);
     5796    checkFail(
     5797        () => doPrep(`
     5798            struct Result {
     5799                float4 output;
     5800            }
     5801            vertex Result foo()
     5802            {
     5803                AllMemoryBarrierWithGroupSync();
     5804                Result r;
     5805                r.output = float4(1, 2, 3, 4);
     5806                return r;
     5807            }
     5808        `),
     5809        e => e instanceof WTypeError);
     5810    checkFail(
     5811        () => doPrep(`
     5812            struct Result {
     5813                float4 output;
     5814            }
     5815            fragment Result foo()
     5816            {
     5817                AllMemoryBarrierWithGroupSync();
     5818                Result r;
     5819                r.output = float4(1, 2, 3, 4);
     5820                return r;
     5821            }
     5822        `),
     5823        e => e instanceof WTypeError);
     5824    checkFail(
     5825        () => doPrep(`
     5826            struct Result {
     5827                float4 output;
     5828            }
     5829            vertex Result foo()
     5830            {
     5831                DeviceMemoryBarrierWithGroupSync();
     5832                Result r;
     5833                r.output = float4(1, 2, 3, 4);
     5834                return r;
     5835            }
     5836        `),
     5837        e => e instanceof WTypeError);
     5838    checkFail(
     5839        () => doPrep(`
     5840            struct Result {
     5841                float4 output;
     5842            }
     5843            fragment Result foo()
     5844            {
     5845                DeviceMemoryBarrierWithGroupSync();
     5846                Result r;
     5847                r.output = float4(1, 2, 3, 4);
     5848                return r;
     5849            }
     5850        `),
     5851        e => e instanceof WTypeError);
     5852    checkFail(
     5853        () => doPrep(`
     5854            struct Result {
     5855                float4 output;
     5856            }
     5857            vertex Result foo()
     5858            {
     5859                GroupMemoryBarrierWithGroupSync();
     5860                Result r;
     5861                r.output = float4(1, 2, 3, 4);
     5862                return r;
     5863            }
     5864        `),
     5865        e => e instanceof WTypeError);
     5866    checkFail(
     5867        () => doPrep(`
     5868            struct Result {
     5869                float4 output;
     5870            }
     5871            fragment Result foo()
     5872            {
     5873                GroupMemoryBarrierWithGroupSync();
     5874                Result r;
     5875                r.output = float4(1, 2, 3, 4);
     5876                return r;
     5877            }
     5878        `),
     5879        e => e instanceof WTypeError);
    57545880}
    57555881
  • trunk/Tools/WebGPUShadingLanguageRI/WSyntaxError.js

    r235738 r236455  
    3232        this.syntaxErrorMessage = message;
    3333    }
     34
     35    toString()
     36    {
     37        return this.payload;
     38    }
    3439}
    3540
  • trunk/Tools/WebGPUShadingLanguageRI/index.html

    r236390 r236455  
    3434<script src="CheckLiteralTypes.js"></script>
    3535<script src="CheckLoops.js"></script>
     36<script src="CheckNativeFuncStages.js"></script>
    3637<script src="CheckRecursion.js"></script>
    3738<script src="CheckRecursiveTypes.js"></script>
Note: See TracChangeset for help on using the changeset viewer.