• Home
Name Date Size #Lines LOC

..--

analysis/03-May-2024-2,1101,510

codegen/03-May-2024-21,97417,495

dsl/03-May-2024-2,0371,544

generated/03-May-2024-4,2424,223

ir/03-May-2024-13,3219,426

lex/03-May-2024-1,6701,222

tracing/03-May-2024-1,099776

transform/03-May-2024-1,4691,015

BUILD.bazelD03-May-20244.4 KiB187171

GLSL.std.450.hD03-May-20244 KiB13290

README.mdD03-May-20247.8 KiB159128

SkSLAnalysis.cppD03-May-202425.5 KiB706577

SkSLAnalysis.hD03-May-20249.9 KiB26295

SkSLBuiltinTypes.cppD03-May-202413.9 KiB206189

SkSLBuiltinTypes.hD03-May-20245 KiB168122

SkSLCompiler.cppD03-May-202425.9 KiB734562

SkSLCompiler.hD03-May-20247.5 KiB243153

SkSLConstantFolder.cppD03-May-202438.3 KiB885719

SkSLConstantFolder.hD03-May-20242.4 KiB7227

SkSLContext.cppD03-May-2024572 3016

SkSLContext.hD03-May-20241.2 KiB5022

SkSLErrorReporter.cppD03-May-2024735 3016

SkSLFileOutputStream.hD03-May-20241.5 KiB7958

SkSLGLSL.hD03-May-20241,017 5918

SkSLInliner.cppD03-May-202449.9 KiB1,063813

SkSLInliner.hD03-May-20244.7 KiB12073

SkSLIntrinsicList.cppD03-May-2024871 3420

SkSLIntrinsicList.hD03-May-20245 KiB146124

SkSLLexer.cppD03-May-202447.2 KiB809790

SkSLLexer.hD03-May-20243 KiB146126

SkSLMangler.cppD03-May-20242.8 KiB7741

SkSLMangler.hD03-May-2024576 3617

SkSLMemoryLayout.hD03-May-20247.5 KiB212145

SkSLMemoryPool.hD03-May-20241,014 4525

SkSLModifiersPool.hD03-May-2024797 3919

SkSLModuleLoader.cppD03-May-202419.5 KiB445350

SkSLModuleLoader.hD03-May-20242.2 KiB6835

SkSLOperator.cppD03-May-202414.6 KiB385336

SkSLOutputStream.cppD03-May-20241,006 4228

SkSLOutputStream.hD03-May-20241.2 KiB5935

SkSLParser.cppD03-May-202478.1 KiB2,2432,021

SkSLParser.hD03-May-202411 KiB370205

SkSLPool.cppD03-May-20242.7 KiB9866

SkSLPool.hD03-May-20242.5 KiB9745

SkSLPosition.cppD03-May-2024789 3522

SkSLProgramSettings.hD03-May-20247.1 KiB16184

SkSLSampleUsage.cppD03-May-2024754 2711

SkSLString.cppD03-May-20243.2 KiB11695

SkSLStringStream.hD03-May-20241.2 KiB5940

SkSLThreadContext.cppD03-May-20243.8 KiB12797

SkSLThreadContext.hD03-May-20244.9 KiB17885

SkSLUtil.cppD03-May-20245.1 KiB9070

SkSLUtil.hD03-May-20247.4 KiB188112

sksl_compute.skslD03-May-2024738 2216

sksl_frag.skslD03-May-2024417 107

sksl_gpu.skslD03-May-202411 KiB317252

sksl_graphite_frag.skslD03-May-202436.4 KiB877791

sksl_graphite_vert.skslD03-May-202425.6 KiB536481

sksl_public.skslD03-May-2024424 118

sksl_rt_shader.skslD03-May-202440 21

sksl_shared.skslD03-May-202417.5 KiB450399

sksl_vert.skslD03-May-2024252 107

spirv.hD03-May-202427.7 KiB871780

README.md

1# Overview
2
3SkSL ("Skia Shading Language") is a variant of GLSL which is used as Skia's
4internal shading language. SkSL is, at its heart, a single standardized version
5of GLSL which avoids all of the various version and dialect differences found
6in GLSL "in the wild", but it does bring a few of its own changes to the table.
7
8Skia uses the SkSL compiler to convert SkSL code to GLSL, GLSL ES, SPIR-V, or
9MSL before handing it over to the graphics driver.
10
11
12# Differences from GLSL
13
14* Precision modifiers are not used. 'float', 'int', and 'uint' are always high
15  precision. New types 'half', 'short', and 'ushort' are medium precision (we
16  do not use low precision).
17* Vector types are named <base type><columns>, so float2 instead of vec2 and
18  bool4 instead of bvec4
19* Matrix types are named <base type><columns>x<rows>, so float2x3 instead of
20  mat2x3 and double4x4 instead of dmat4
21* GLSL caps can be referenced via the syntax 'sk_Caps.<name>', e.g.
22  sk_Caps.integerSupport. The value will be a constant boolean or int,
23  as appropriate. As SkSL supports constant folding and branch elimination, this
24  means that an 'if' statement which statically queries a cap will collapse down
25  to the chosen branch, meaning that:
26
27    if (sk_Caps.integerSupport)
28        do_something();
29    else
30        do_something_else();
31
32  will compile as if you had written either 'do_something();' or
33  'do_something_else();', depending on whether that cap is enabled or not.
34* no #version statement is required, and it will be ignored if present
35* the output color is sk_FragColor (do not declare it)
36* use sk_Position instead of gl_Position. sk_Position is in device coordinates
37  rather than normalized coordinates.
38* use sk_PointSize instead of gl_PointSize
39* use sk_VertexID instead of gl_VertexID
40* use sk_InstanceID instead of gl_InstanceID
41* the fragment coordinate is sk_FragCoord, and is always relative to the upper
42  left.
43* use sk_Clockwise instead of gl_FrontFacing. This is always relative to an
44  upper left origin.
45* you do not need to include ".0" to make a number a float (meaning that
46  "float2(x, y) * 4" is perfectly legal in SkSL, unlike GLSL where it would
47  often have to be expressed "float2(x, y) * 4.0". There is no performance
48  penalty for 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
50* creating a smaller vector from a larger vector (e.g. float2(float3(1))) is
51  intentionally disallowed, as it is just a wordier way of performing a swizzle.
52  Use swizzles instead.
53* Swizzle components, in addition to the normal rgba / xyzw components, can also
54  be LTRB (meaning "left/top/right/bottom", for when we store rectangles in
55  vectors), and may also be the constants '0' or '1' to produce a constant 0 or
56  1 in that channel instead of selecting anything from the source vector.
57  foo.rgb1 is equivalent to float4(foo.rgb, 1).
58* All texture functions are named "sample", e.g. sample(sampler2D, float3) is
59  equivalent to GLSL's textureProj(sampler2D, float3).
60* Functions support the 'inline' modifier, which causes the compiler to ignore
61  its normal inlining heuristics and inline the function if at all possible
62* some built-in functions and one or two rarely-used language features are not
63  yet supported (sorry!)
64
65
66# Synchronization Primitives
67
68SkSL offers atomic operations and synchronization primitives geared towards GPU compute
69programs. These primitives are designed to abstract over the capabilities provided by
70MSL, SPIR-V, and WGSL, and differ from the corresponding primitives in GLSL.
71
72## Atomics
73
74SkSL provides the `atomicUint` type. This is an opaque type that requires the use of an
75atomic intrinsic (such as `atomicLoad`, `atomicStore`, and `atomicAdd`) to act on its value (which
76is of type `uint`).
77
78A variable with the `atomicUint` type must be declared inside a writable storage buffer block or as
79a workgroup-shared variable. When declared inside a buffer block, it is guaranteed to conform to the
80same size and stride as a `uint`.
81
82```
83workgroup atomicUint myLocalAtomicUint;
84
85layout(set = 0, binding = 0) buffer mySSBO {
86    atomicUint myGlobalAtomicUint;
87};
88
89```
90
91An `atomicUint` can be declared as a struct member or the element type of an array, provided that
92the struct/array type is only instantiated in a workgroup-shared or storage buffer block variable.
93
94### Backend considerations and differences from GLSL
95
96`atomicUint` should not be confused with the GLSL [`atomic_uint` (aka Atomic
97Counter)](https://www.khronos.org/opengl/wiki/Atomic_Counter) type. The semantics provided by
98`atomicUint` are more similar to GLSL ["Atomic Memory
99Functions"](https://www.khronos.org/opengl/wiki/Atomic_Variable_Operations)
100(see GLSL Spec v4.3, 8.11 "Atomic Memory Functions"). The key difference is that SkSL atomic
101operations only operate on a variable of type `atomicUint` while GLSL Atomic Memory Functions can
102operate over arbitrary memory locations (such as a component of a vector).
103
104* The semantics of `atomicUint` are similar to Metal's `atomic<uint>` and WGSL's `atomic<u32>`.
105  These are the types that an `atomicUint` is translated to when targeting Metal and WGSL.
106* When translated to Metal, the atomic intrinsics use relaxed memory order semantics.
107* When translated to SPIR-V, the atomic intrinsics use relaxed [memory
108  semantics](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Memory_Semantics_-id-)
109  (i.e. `0x0 None`). The [memory
110  scope](https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#Scope_-id-) is either `1
111  Device` or `2 Workgroup` depending on whether the `atomicUint` is declared in a buffer block or
112  workgroup variable.
113
114## Barriers
115
116SkSL provides two barrier intrinsics: `workgroupBarrier()` and `storageBarrier()`. These functions
117are only available in compute programs and synchronize access to workgroup-shared and storage buffer
118memory between invocations in the same workgroup. They provide the same semantics as the equivalent
119[WGSL Synchronization Built-in Functions](https://www.w3.org/TR/WGSL/#sync-builtin-functions). More
120specifically:
121
122* Both functions execute a control barrier with Acquire/Release memory ordering.
123* Both functions use a `Workgroup` execution and memory scope. This means that a coherent memory
124  view is only guaranteed between invocations in the same workgroup and NOT across workgroups in a
125  given compute pipeline dispatch. If multiple workgroups require a _synchronized_ coherent view
126  over the same shared mutable state, their access must be synchronized via other means (such as a
127  pipeline barrier between multiple dispatches).
128
129### Backend considerations
130
131* The closest GLSL equivalent for `workgroupBarrier()` is the
132[`barrier()`](https://registry.khronos.org/OpenGL-Refpages/gl4/html/barrier.xhtml) intrinsic. Both
133`workgroupBarrier()` and `storageBarrier()` can be defined as the following invocations of the
134`controlBarrier` intrinsic defined in
135[GL_KHR_memory_scope_semantics](https://github.com/KhronosGroup/GLSL/blob/master/extensions/khr/GL_KHR_memory_scope_semantics.txt):
136
137```
138// workgroupBarrier():
139controlBarrier(gl_ScopeWorkgroup,
140               gl_ScopeWorkgroup,
141               gl_StorageSemanticsShared,
142               gl_SemanticsAcquireRelease);
143
144// storageBarrier():
145controlBarrier(gl_ScopeWorkgroup,
146               gl_ScopeWorkgroup,
147               gl_StorageSemanticsBuffer,
148               gl_SemanticsAcquireRelease);
149```
150
151* In Metal, `workgroupBarrier()` is equivalent to `threadgroup_barrier(mem_flags::mem_threadgroup)`.
152  `storageBarrier()` is equivalent to `threadgroup_barrier(mem_flags::mem_device)`.
153
154* In Vulkan SPIR-V, `workgroupBarrier()` is equivalent to `OpControlBarrier` with `Workgroup`
155  execution and memory scope, and `AcquireRelease | WorkgroupMemory` memory semantics.
156
157  `storageBarrier()` is equivalent to `OpControlBarrier` with `Workgroup` execution and memory
158  scope, and `AcquireRelease | UniformMemory` memory semantics.
159