Bug 230107

Summary: [WebGL2, Safari 15 - iOS15] Problems with drawElements in some conditions
Product: WebKit Reporter: Brendan Duncan <brendanduncan>
Component: WebGLAssignee: Kyle Piddington <kpiddington>
Status: RESOLVED FIXED    
Severity: Normal CC: anthony.bowker, dino, ews-watchlist, gman, kbr, kkinnunen, kondapallykalyan, kpiddington, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: iPhone / iPad   
OS: Other   
Bug Depends on:    
Bug Blocks: 223434    
Attachments:
Description Flags
Repo test of a iOS15 WebGL2 problem
none
Repo test of a iOS15 WebGL2 problem -- Draw One Triangle
none
Repo test of a iOS15 WebGL2 problem - Draw No Vertex Buffer
none
Repo test of a iOS15 WebGL2 problem - Draw Bigger Vertex Buffer
none
Patch
none
Patch
none
Patch for landing none

Description Brendan Duncan 2021-09-09 10:13:33 PDT
Created attachment 437756 [details]
Repo test of a iOS15 WebGL2 problem

Testing Unity WebGL2 builds on iOS 15 Beta 8, there are draw calls being used by Unity's UI system that cause WebGL2 to go into a bad state. It stops rendering, takes over 5000ms to complete a frame, usually crashing the page before too long.

I narrowed it down to a complex shader being used by the Unity UI system, and a call to drawElements that causes things to go wrong. I attached a small Javascript reproduction of the issue. The test is a self contained HTML with embedded JS code with the minimal GL calls that trigger the issue. It doesn't render anything useful, it's just triggering the problem. The problem can be seen by the displayed frame rate dropping to ~5000ms.

The repo test runs correctly on MacOS Safari 15, and on Android mobiles. The issue only happens on iOS 15, tested on an iPhone XS and iPad.

In the repo test, there are three lines:
    gl.drawElements(4, 174, 5123, 0); // Original from Unity, BAD
    //gl.drawElements(4, 159, 5123, 0); // BAD
    //gl.drawElements(4, 158, 5123, 0); // GOOD

If I change the drawElements count to 158, the problem goes away. At count 159, the problem appears. 
In the real, non repo test, the shader and drawElements are generated from Unity, not manually authored.
Comment 1 Kimmo Kinnunen 2021-09-10 02:09:12 PDT
I can confirm iPhone 12, WebGL via Metal: repros.
Comment 2 Kimmo Kinnunen 2021-09-10 02:10:06 PDT
No repro on OpenGL.
Comment 3 Kimmo Kinnunen 2021-09-10 02:12:20 PDT
Error during command buffer execution
Comment 4 Radar WebKit Bug Importer 2021-09-10 09:29:22 PDT
<rdar://problem/82975755>
Comment 5 Kenneth Russell 2021-09-10 12:58:24 PDT
Thanks so much Kimmo for investigating and confirming.

Do you think you might be able to take this bug since only someone from Apple can really debug it? Do you think it's something ANGLE's Metal backend is doing wrong and that's the cause of the command buffer execution error?

The vertex and element array buffers in this example are being allocated with DYNAMIC_DRAW. UNSIGNED_SHORT indices are being used. All of the data is zeroed out, so all of the triangles being drawn are degenerate. (All zero indices, all 0.0 vertices.)
Comment 6 Brendan Duncan 2021-09-10 13:04:42 PDT
Thanks to both of you.

Please don't get hung up on the zero index and vertex buffers, and the resulting degenerate triangles. I just didn't include the array data to avoid including the giant arrays, since it still seemed to have the effect without the data. If the degenerate triangles are throwing off testing, I can include that data.
Comment 7 Brendan Duncan 2021-09-21 11:53:55 PDT
I was wondering if there was any progress identifying the issue as it will be a significant problem for Unity WebGL builds running on iOS15.
Comment 8 Kyle Piddington 2021-09-21 12:09:35 PDT
(In reply to Brendan Duncan from comment #7)
> I was wondering if there was any progress identifying the issue as it will
> be a significant problem for Unity WebGL builds running on iOS15.

Hey Brendan, 
Thank you for the ping on this. I'll have a chance to look this week on what can be causing our perf issue. Our submission issue is due to a page fault in the shader. Perhaps we're not allocating enough space for our index buffer?
Comment 9 Kyle Piddington 2021-09-21 15:25:29 PDT
Created attachment 438868 [details]
Repo test of a iOS15 WebGL2 problem  -- Draw One Triangle

Local testing
Comment 10 Kyle Piddington 2021-09-21 16:00:07 PDT
Created attachment 438875 [details]
Repo test of a iOS15 WebGL2 problem - Draw No Vertex Buffer
Comment 11 Kyle Piddington 2021-09-21 16:02:22 PDT
Created attachment 438877 [details]
Repo test of a iOS15 WebGL2 problem - Draw Bigger Vertex Buffer
Comment 12 Kyle Piddington 2021-09-21 16:46:36 PDT
From debugging:
Adjusting the vertex array from 16384 to 16385, or to smaller (144) seem to work,
In addition to adjusting the drawElements call from 158 to 159.
Comment 13 Kyle Piddington 2021-09-21 17:56:20 PDT
(In reply to Kyle Piddington from comment #12)
> From debugging:
> Adjusting the vertex array from 16384 to 16385, or to smaller (144) seem to
> work

I misread this: This isn't the vertex array. It's the index array. 
I think something's gone wrong with allocating exactly 4k indices. How that relates to drawing less or more, I haven't figured out yet.
Comment 14 Kyle Piddington 2021-09-21 17:57:06 PDT
(In reply to Kyle Piddington from comment #13)
> I think something's gone wrong with allocating exactly 4k indices. How that
> relates to drawing less or more, I haven't figured out yet.

And by 4k, I meant 16k. (0x4000, got my wires crossed)
Comment 15 Kyle Piddington 2021-09-21 19:03:46 PDT
Issue appears to be in the provoking vertex index rewrite. I just spotted that the UI elements uses flat shading. Disabling index rewrite causes this to work.
Comment 16 Kyle Piddington 2021-09-21 19:17:29 PDT
Created attachment 438905 [details]
Patch
Comment 17 EWS Watchlist 2021-09-21 19:18:13 PDT
Note that there are important steps to take when updating ANGLE. See https://trac.webkit.org/wiki/UpdatingANGLE
Comment 18 Brendan Duncan 2021-09-21 20:45:17 PDT
This is great! Thank you Kyle!
Comment 19 Kimmo Kinnunen 2021-09-22 04:21:46 PDT
Comment on attachment 438905 [details]
Patch

Looks good for what I understand.
I think we "guess" that `pipelineState.maxTotalThreadsPerThreadgroup >= 64`?


For obligatory nits, the first hunk is unnecessary and the second hunk you could have formatted with the command..
Comment 20 Kyle Piddington 2021-09-22 11:55:24 PDT
Created attachment 438963 [details]
Patch
Comment 21 Kenneth Russell 2021-09-22 16:14:37 PDT
Comment on attachment 438963 [details]
Patch

Great find and fix Kyle! I defer to Dean's earlier review.
Comment 22 Kyle Piddington 2021-09-23 14:39:06 PDT
Created attachment 439094 [details]
Patch for landing
Comment 23 EWS 2021-09-23 15:08:16 PDT
Committed r283014 (242079@main): <https://commits.webkit.org/242079@main>

All reviewed patches have been landed. Closing bug and clearing flags on attachment 439094 [details].