notes
[webkit_codecamp] / notes
1 Hi, I am Eleni Maria Stea and I am going to talk to you about a few
2 ideas I explored and experiments I've ran concerning the adoption of
3 ANGLE in WebKit/WPE.
4
5 Before I begin, let's se what ANGLE is and what we want to do with it.
6
7 So,ANGLE is an EGL/GLES implementation.
8
9 GLES is the API we use to render graphics with the GPU
10 and EGL is the API we use to create the GLES context
11
12 Both are implemented on top of other APIs.
13 In case of EGL these APIs can be the native system EGL, GLX, gbm or others.
14 In case of GLES they can be the native system driver GLES, OpenGL, Vulkan
15 or others.
16
17 This is because the primary purpose of ANGLE is to provide an EGL/GLES
18 implementation to systems lacking it.
19
20 The users can set the backend they prefer using some extra EGL
21 extensions provided by ANGLE in eglext_angle.h header file.
22
23 On WebKit we'd like to use ANGLE in WebGL two that is implemented in
24 GLES two. The main reason is the performance.
25
26 But there is a problem with our current design:
27 As ANGLE renders on a GLES 2 texture created by an ANGLE context
28 and the WebKit graphics pipeline renders on OpenGL textures that are
29 later assembled in one by the WebKit compositor, we currently need to
30 copy the WebGL texture data from an ANGLE texture to an OpenGL one.
31
32 So all the experiments I am going to present are to replace this copy
33 with something better.
34
35 Let's see a list of them.
36
37 First I've written a program that uses ANGLE to render an image on an X11
38 window and the native system drivers to render another image on another
39 X11 window and display them.
40
41 That was to create a similar situation to the one we have on WebKit.
42
43 Then, I experimented with shared context and textures. I've created a
44 shared texture between the native context and the native context of the
45 ANGLE backend.
46
47 Then I filled it using the ANGLE context and displayed the result using
48 the native driver context. I had to abandon the shared context idea
49 for reasons that I'll explain later.
50
51 My next experiment was to use the Linux kerne dma buffers framework to
52 associate two textures with the same kernel memory. Then filling one
53 texture was automatically filling the other. This method seemed to do
54 exactly what we want and so I am going to use it in WebKit as well.
55
56 Last experiment was to try something similar but with multiple processes.
57 We might need it in the future.
58
59 Let's see them in detail.
60
61 First experiment
62
63 For all my experiments I've written small standalone programs because
64 WebKit is complex and building it takes ages. So, in order to use ANGLE
65 in them I needed to build ANGLe with debugging symbols, and to find some
66 way to use two implementations of the same API in the same program.
67
68 So the first step of the first experiment was to set up ANGLE for debugging
69 with GDB. I will quickly mention that ANGLE by default redirects the
70 debugging symbols and uses non-standard paths so I had to modify the
71 build system arguments and the GDB settings to be able to step into ANGLE
72 functions.
73
74 You can read about these in my blog post.
75
76 So in this test, I've rendered two images one from ANGLE context and
77 one from EGL like in this screenshot where the green image is the ANGLE one
78 and the XOR pattern comes from the native driver.
79
80 In order to have both implementations working together I linked with the
81 system driver libEGL and libGLES and I dynamically opened ANGLE's libEGL
82 and libGLES and loaded each EGL and gl function prefixed by angle_.
83
84 One other thing I needed for this experiment to work was to invalidate the
85 ANGLE context before every draw call. This is an interesting ANGLE problem.
86
87 ANGLE is using some sort of internal context caching. This is to avoid
88 calling MakeCurrent when it's not absolutely necessary. So every time we
89 call angle_MakeCurrent ANGLE checks if the context has been changed and if
90 not it ignores the call.
91
92 When we use two contexts from two drivers in the same process ANGLE
93 considers it's the only EGL implementation available in the program.
94 So, in a rendering loop like the one of the slide, ANGLE would always
95 see angle_MakeCurrent being called with the same context and wouldn't
96 update it. 
97 A simple solution is to invalidate it by calling angle_MakeCurrent using
98 a null context at the top of display. This problem wouldn't happen with
99 threads or multiple processes but it's interesting to know it.
100
101 You can read more about these changes in my blog in the blog post sections
102 mentioned in the slide.
103
104 Let's see the next experiment. In this one I tried to exchange texture data
105 using shared textures and shared context.
106
107 So, what's shared context?
108
109 When we create a new context with EGL we can set an existing context
110 as parameter and use it as "shared". After that all textures created by
111 the shared context can be directly accessed from the other context without
112 leaving the GPU.
113
114 For the shared context to work both contexts must be created by the same
115 process and both context must be created by the same API.
116
117 This means that we can't use shared context directly between EGL and ANGLE,
118 but we can use it between the EGL/OpenGL native system driver and the
119 EGL/OpenGL ANGLE backend.
120
121 ==========
122
123 To do so in WebKit, we'd need to force the EGL/OpenGL backend in ANGLE
124 and write an ANGLE extension that can tell ANGLE when the shared
125 context is native and not ANGLE so that it's used in the backend call.
126
127 =========
128
129 This is how I had designed this extension. In the first picture of the
130 slide we see how we'd create shared context with native EGL and with
131 ANGLE.
132
133 In the second image we see how we'd pass a native context to ANGLE. One
134 of the EGL attributes passed to angle_eglCreateContext should indicate
135 that the context is native
136 ==========
137
138 And this is what happens internally in ANGLE:
139 When the extension attribute is set we create a shared context in the
140 backend. When not, we handle the shared context as ANGLE shared context.
141
142 ===========
143
144 Why we've rejected this method?
145 Main reason is that we plan to split the graphics operations in
146 multiple processes on WebKit.
147
148 But fortunately, there was a better approach to follow.
149
150 =============================
151
152 In that approach, I've used a Linux kernel framework for content sharing:
153 DMA buffers.
154
155 ========================
156
157 This framework can be used to import dma buffers that are used 
158 as backing storage for textures from other drivers. This is handy
159 because if two textures use the same dma buffer storage, filling
160 one will fill the other.
161
162 It has some advantages like that it can easily used by EGL as there are
163 EGL extensions for it.
164 it's driver independent
165 it works with multiple processes and
166
167 as long as ANGLE can implement and expose the extensions to import a
168 dma buffer it's also angle backend independent.
169
170 The only problem is that DMA buffers are used from Linux only while
171 shared context is universal. But in this particular WebKit backend,
172 we don't care.
173
174 ===================================
175
176 I have a list of the EGL extensions that can be used to share a buffer
177 among drivers and links to the two example programs I've written.
178
179 ====================================
180
181 Let's see how we could access a DMA buffer from context A in context B.
182 In this example texture texA corresponds to contextA and texture texB is
183 from texture B.
184
185 In the exporter that is context A, we create an EGL image from contextA
186 and we export some information about it as well as the file descriptor
187 that corresponds to its underlying kernel dma buffer.
188
189 struct tex_storage_info stores the extra information.
190
191 =======================================
192
193 In the importer that is context B we can then
194 create another image that accesses the dma buffer using
195 the file descriptor and the information we extracted before
196
197 and we can use it to create another texture tex B using
198 where the underline dma buffer is the imported one
199
200 Then filling tex B will fill tex A.
201
202 =========================================
203
204 I've followed these steps with context A being native and context B
205 being ANGLE and created a similar case to the one we had in WebKit.
206
207 It worked well! So, I've tested also the multiple processes case.
208
209 ==============================
210
211 DMA buffers seem to work with multiple processes but require some sort
212 of Interprocess communication to exchange the file descriptor and the
213 information about the buffer we've seen before.
214
215 I've found a client server example that uses unix sockets to exchange the
216 file descriptor and works well. Code is on gitlab.
217
218 ================================
219
220 So, finally let's see if this could be integrated to WebKit. 
221
222 The extensions to import dma buffers are fully implemented and exposed in
223 ANGLE and so in WebGL we could import a dma buffer from a graphics pipeline
224 texture when we create the WebGL render target.
225
226 The extension to export dma buffers is implemented on Mesa and so it can be
227 used in main pipeline. In case it's not found we could fallback to some
228 alternative that is copying or maybe libgbm.
229
230 So this week I am investigating what needs to be done on WebKit.
231
232 - I've build ANGLE and fixed the compile errors of that backend
233 - I am currently fixing some link errors (unfortunately there's one I 
234 haven't found yet)
235 - and I've taken a look at the code where I need to make the change.
236
237 ==========================
238
239 References... I intend to upload these slides, and so I've appended a list
240 of links that could be useful in this task at the end. Feel free to
241 take a look at it
242
243 ============================
244
245 And Closing
246 I'd like to thank you very much for watching my talk and for
247 giving me the opportunity to work on this task!
248
249 Goodbye and have a nice day or evening!
250
251 ==========================
252
253