ethannicholas | 5961bc9 | 2016-10-12 06:39:56 -0700 | [diff] [blame] | 1 | Overview |
| 2 | ======== |
| 3 | |
Ethan Nicholas | 0df1b04 | 2017-03-31 13:56:23 -0400 | [diff] [blame] | 4 | SkSL ("Skia Shading Language") is a variant of GLSL which is used as Skia's |
ethannicholas | 5961bc9 | 2016-10-12 06:39:56 -0700 | [diff] [blame] | 5 | internal shading language. SkSL is, at its heart, a single standardized version |
| 6 | of GLSL which avoids all of the various version and dialect differences found |
| 7 | in GLSL "in the wild", but it does bring a few of its own changes to the table. |
| 8 | |
| 9 | Skia uses the SkSL compiler to convert SkSL code to GLSL, GLSL ES, or SPIR-V |
| 10 | before handing it over to the graphics driver. |
| 11 | |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 12 | |
ethannicholas | 5961bc9 | 2016-10-12 06:39:56 -0700 | [diff] [blame] | 13 | Differences from GLSL |
| 14 | ===================== |
| 15 | |
| 16 | SkSL is based on GLSL 4.5. For the most part, write SkSL exactly as you would |
| 17 | desktop GLSL, and the SkSL compiler will take care of version and dialect |
| 18 | differences (for instance, you always use "in" and "out", and skslc will handle |
Ethan Nicholas | 0df1b04 | 2017-03-31 13:56:23 -0400 | [diff] [blame] | 19 | translating them to "varying" and "attribute" as appropriate). Be aware of the |
ethannicholas | 5961bc9 | 2016-10-12 06:39:56 -0700 | [diff] [blame] | 20 | following differences between SkSL and GLSL: |
| 21 | |
Ethan Nicholas | 5ac13c2 | 2017-05-10 15:06:17 -0400 | [diff] [blame] | 22 | * "@if" and "@switch" are static versions of if and switch. They behave exactly |
| 23 | the same as if and switch in all respects other than it being a compile-time |
| 24 | error to use a non-constant expression as a test. |
Ethan Nicholas | 3605ace | 2016-11-21 15:59:48 -0500 | [diff] [blame] | 25 | * GLSL caps can be referenced via the syntax 'sk_Caps.<name>', e.g. |
| 26 | sk_Caps.sampleVariablesSupport. The value will be a constant boolean or int, |
| 27 | as appropriate. As SkSL supports constant folding and branch elimination, this |
| 28 | means that an 'if' statement which statically queries a cap will collapse down |
| 29 | to the chosen branch, meaning that: |
| 30 | |
| 31 | if (sk_Caps.externalTextureSupport) |
| 32 | do_something(); |
| 33 | else |
| 34 | do_something_else(); |
| 35 | |
| 36 | will compile as if you had written either 'do_something();' or |
| 37 | 'do_something_else();', depending on whether that cap is enabled or not. |
ethannicholas | 22f939e | 2016-10-13 13:25:34 -0700 | [diff] [blame] | 38 | * no #version statement is required, and will be ignored if present |
ethannicholas | 5961bc9 | 2016-10-12 06:39:56 -0700 | [diff] [blame] | 39 | * the output color is sk_FragColor (do not declare it) |
Ethan Nicholas | a51740c | 2017-02-07 14:53:32 -0500 | [diff] [blame] | 40 | * use sk_VertexID instead of gl_VertexID |
Ethan Nicholas | 3865711 | 2017-02-09 17:01:22 -0500 | [diff] [blame] | 41 | * the fragment coordinate is sk_FragCoord, and is always relative to the upper |
| 42 | left. |
Ethan Nicholas | 0df1b04 | 2017-03-31 13:56:23 -0400 | [diff] [blame] | 43 | * lowp, mediump, and highp are always permitted (but will only be respected if |
Ethan Nicholas | 3865711 | 2017-02-09 17:01:22 -0500 | [diff] [blame] | 44 | you run on a device which supports them) |
ethannicholas | 5961bc9 | 2016-10-12 06:39:56 -0700 | [diff] [blame] | 45 | * you do not need to include ".0" to make a number a float (meaning that |
| 46 | "vec2(x, y) * 4" is perfectly legal in SkSL, unlike GLSL where it would often |
Ethan Nicholas | 0df1b04 | 2017-03-31 13:56:23 -0400 | [diff] [blame] | 47 | have to be expressed "vec2(x, y) * 4.0". There is no performance penalty for |
ethannicholas | 5961bc9 | 2016-10-12 06:39:56 -0700 | [diff] [blame] | 48 | this, as the number is converted to a float at compile time) |
| 49 | * type suffixes on numbers (1.0f, 0xFFu) are both unnecessary and unsupported |
Ethan Nicholas | 84645e3 | 2017-02-09 13:57:14 -0500 | [diff] [blame] | 50 | * creating a smaller vector from a larger vector (e.g. vec2(vec3(1))) is |
| 51 | intentionally disallowed, as it is just a wordier way of performing a swizzle. |
| 52 | Use swizzles instead. |
Ethan Nicholas | 2b3dab6 | 2016-11-28 12:03:26 -0500 | [diff] [blame] | 53 | * Use texture() instead of textureProj(), e.g. texture(sampler2D, vec3) is |
| 54 | equivalent to GLSL's textureProj(sampler2D, vec3) |
ethannicholas | 5961bc9 | 2016-10-12 06:39:56 -0700 | [diff] [blame] | 55 | * some built-in functions and one or two rarely-used language features are not |
| 56 | yet supported (sorry!) |
| 57 | |
| 58 | SkSL is still under development, and is expected to diverge further from GLSL |
| 59 | over time. |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 60 | |
| 61 | |
| 62 | SkSL Fragment Processors |
| 63 | ======================== |
| 64 | |
| 65 | An extension of SkSL allows for the creation of fragment processors in pure |
| 66 | SkSL. The program defines its inputs similarly to a normal SkSL program (with |
| 67 | 'in' and 'uniform' variables), but the 'main()' function represents only this |
| 68 | fragment processor's portion of the overall fragment shader. |
| 69 | |
| 70 | Within an '.fp' fragment processor file: |
| 71 | |
| 72 | * C++ code can be embedded in sections of the form: |
| 73 | |
| 74 | @section_name { <arbitrary C++ code> } |
| 75 | |
| 76 | Supported section are: |
| 77 | @header (in the .h file, outside the class declaration) |
Ethan Nicholas | 9fb036f | 2017-07-05 16:19:09 -0400 | [diff] [blame^] | 78 | @headerEnd (at the end of the .h file) |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 79 | @class (in the .h file, inside the class declaration) |
| 80 | @cpp (in the .cpp file) |
Ethan Nicholas | 9fb036f | 2017-07-05 16:19:09 -0400 | [diff] [blame^] | 81 | @cppEnd (at the end of the .cpp file) |
Ethan Nicholas | 762466e | 2017-06-29 10:03:38 -0400 | [diff] [blame] | 82 | @constructorParams (extra parameters to the constructor, comma-separated) |
| 83 | @constructor (replaces the default constructor) |
| 84 | @initializers (constructor initializer list, comma-separated) |
| 85 | @emitCode (extra code for the emitCode function) |
| 86 | @fields (extra private fields, each terminated with a semicolon) |
| 87 | @make (replaces the default Make function) |
| 88 | @setData(<pdman>) (extra code for the setData function, where <pdman> is |
| 89 | the name of the GrGLSLProgramDataManager) |
| 90 | @test(<testData>) (the body of the TestCreate function, where <testData> is |
| 91 | the name of the GrProcessorTestData* parameter) |
| 92 | * global 'in' variables represent data passed to the fragment processor at |
| 93 | construction time. These variables become constructor parameters and are |
| 94 | stored in fragment processor fields. vec2s map to SkPoints, and vec4s map to |
| 95 | SkRects (in x, y, width, height) order. |
| 96 | * 'uniform' variables become, as one would expect, top-level uniforms. By |
| 97 | default they do not have any data provided to them; you will need to provide |
| 98 | them with data via the @setData section. |
| 99 | * 'in uniform' variables are uniforms that are automatically wired up to |
| 100 | fragment processor constructor parameters |
| 101 | * the 'sk_TransformedCoords2D' array provides access to 2D transformed |
| 102 | coordinates. sk_TransformedCoords2D[0] is equivalent to calling |
| 103 | fragBuilder->ensureCoords2D(args.fTransformedCoords[0]) (and the result is |
| 104 | cached, so you need not worry about using the value repeatedly). |
| 105 | * 'colorSpaceXform' is a supported type. It is reflected within SkSL as a mat4, |
| 106 | and on the C++ side as sk_sp<GrColorSpaceXform>. |
| 107 | * the texture() function can be passed a colorSpaceXform as an additional |
| 108 | parameter |
| 109 | * Uniform variables support an additional 'when' layout key. |
| 110 | 'layout(when=foo) uniform int x;' means that this uniform will only be |
| 111 | emitted when the 'foo' expression is true. |
| 112 | * 'in' variables support an additional 'key' layout key. |
| 113 | 'layout(key) uniform int x;' means that this uniform should be included in |
| 114 | the program's key. Matrix variables additionally support 'key=identity', |
| 115 | which causes the key to consider only whether or not the matrix is an |
| 116 | identity matrix. |