RESOLVED FIXED 226953
Tensorflow.js Broken in Safari 15
https://bugs.webkit.org/show_bug.cgi?id=226953
Summary Tensorflow.js Broken in Safari 15
M
Reported 2021-06-12 08:40:56 PDT
OVERVIEW: Getting a consistent vertex/shader error message across every Tensorflow.js demo on the developer release of iOS 15.0 (using Safari 15). These TFJS applications and and models currently run correctly in iOS 14.6 or 14.7. ERROR LOG: Internal error compiling shader with Metal backend. Please submit this shader, or website as a bug to https://bugs.webkit.org Error: Failed to link vertex and fragment shaders. STEPS TO REPRODUCE: A few websites/demos where you can reproduce the error when running the applications in iOS 15 are: https://emojiscavengerhunt.withgoogle.com/ https://magenta.tensorflow.org/demos/performance_rnn/index.html https://storage.googleapis.com/tfjs-examples/addition-rnn/dist/index.html If more code samples are needed, they can also be accessed here: https://www.tensorflow.org/js/demos ACTUAL RESULTS: The demos/programs error out as the models cannot be processed. EXPECTED BEHAVIOR: The applications above all run well in iOS 14.6 and 14.7 on my iPhone X. HARDWARE: The error occurs in Safari 15.0 in iOS 15 on my iPhone XS.
Attachments
Patch (1.45 KB, patch)
2021-06-14 15:21 PDT, Kyle Piddington
no flags
Patch (2.58 KB, patch)
2021-06-14 16:28 PDT, Kyle Piddington
no flags
Radar WebKit Bug Importer
Comment 1 2021-06-12 14:57:29 PDT
Kenneth Russell
Comment 2 2021-06-14 14:51:15 PDT
Kyle, would you be able to triage this? TensorFlow.js is a major WebGL use case so investigating this regression is urgent.
Kyle Piddington
Comment 3 2021-06-14 15:10:40 PDT
From the GLSL: 2021-06-14 15:07:04.453 MiniBrowser[44123:3425024] // GLSL // // #version 300 es // precision highp float; // precision highp int; // precision highp sampler2D; // in vec2 resultUV; // out vec4 outputColor; // const vec2 halfCR = vec2(0.5, 0.5); // // struct ivec5 // { // int x; // int y; // int z; // int w; // int u; // }; // // struct ivec6 // { // int x; // int y; // int z; // int w; // int u; // int v; // }; // // // bool isNaN(float val) { // return (val < 1.0 || 0.0 < val || val == 0.0) ? false : true; // } // // bvec4 isNaN(vec4 val) { // return bvec4( // isNaN(val.x), // isNaN(val.y), // isNaN(val.z), // isNaN(val.w) // ); // } // // bool hasNaN(vec4 values) { // return any(bvec4( // isNaN(values.x), // isNaN(values.y), // isNaN(values.z), // isNaN(values.w) // )); // } // // // float getNaN(vec4 values) { // return dot(vec4(1), values); // } // // // #define round(value) newRound(value) // int newRound(float value) { // return int(floor(value + 0.5)); // } // // ivec4 newRound(vec4 value) { // return ivec4(floor(value + vec4(0.5))); // } // // // int imod(int x, int y) { // return x - y * (x / y); // } // // //Based on the work of Dave Hoskins // //https://www.shadertoy.com/view/4djSRW // #define HASHSCALE1 443.8975 // float random(float seed){ // vec2 p = resultUV * seed; // vec3 p3 = fract(vec3(p.xyx) * HASHSCALE1); // p3 += dot(p3, p3.yzx + 19.19); // return fract((p3.x + p3.y) * p3.z); // } // // // vec2 uvFromFlat(int texNumR, int texNumC, int index) { // int texR = index / texNumC; // int texC = index - texR * texNumC; // return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR); // } // vec2 packedUVfrom1D(int texNumR, int texNumC, int index) { // int texelIndex = index / 2; // int texR = texelIndex / texNumC; // int texC = texelIndex - texR * texNumC; // return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR); // } // // // vec2 packedUVfrom2D(int texelsInLogicalRow, int texNumR, // int texNumC, int row, int col) { // int texelIndex = (row / 2) * texelsInLogicalRow + (col / 2); // int texR = texelIndex / texNumC; // int texC = texelIndex - texR * texNumC; // return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR); // } // // // vec2 packedUVfrom3D(int texNumR, int texNumC, // int texelsInBatch, int texelsInLogicalRow, int b, // int row, int col) { // int index = b * texelsInBatch + (row / 2) * texelsInLogicalRow + (col / 2); // int texR = index / texNumC; // int texC = index - texR * texNumC; // return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR); // } // // // float getChannel(vec4 frag, vec2 innerDims) { // vec2 modCoord = mod(innerDims, 2.); // return modCoord.x == 0. ? // (modCoord.y == 0. ? frag.r : frag.g) : // (modCoord.y == 0. ? frag.b : frag.a); // } // float getChannel(vec4 frag, int dim) { // float modCoord = mod(float(dim), 2.); // return modCoord == 0. ? frag.r : frag.g; // } // // // float sampleTexture(sampler2D textureSampler, vec2 uv) { // return texture(textureSampler, uv).r; // } // // // void setOutput(vec4 val) { // outputColor = val; // } // // uniform sampler2D A; // uniform int offsetA; // // ivec2 getOutputCoords() { // ivec2 resTexRC = ivec2(resultUV.yx * // vec2(64, 2)); // // int index = resTexRC.x * 2 + resTexRC.y; // int r = 2 * (index / 2); // int c = imod(index, 2) * 2; // // return ivec2(r, c); // } // // // vec4 getA(int row, int col) { // vec2 uv = packedUVfrom2D(2, 64, 2, row, col); // return texture(A, uv); // } // // vec4 getAAtOutCoords() { // ivec2 coords = getOutputCoords(); // // vec4 outputValue = getA(coords.x, coords.y); // return outputValue; // } // // // uniform float NAN; // vec4 unaryOperation(vec4 x) { // // vec4 result = log(x); // vec4 isNaN = vec4(lessThan(x, vec4(0.0))); // result.r = isNaN.r == 1.0 ? NAN : result.r; // result.g = isNaN.g == 1.0 ? NAN : result.g; // result.b = isNaN.b == 1.0 ? NAN : result.b; // result.a = isNaN.a == 1.0 ? NAN : result.a; // // return result; // // } // // void main() { // vec4 x = getAAtOutCoords(); // vec4 y = unaryOperation(x); // // setOutput(y); // } // Our issue is translating // uniform float NAN; NAN in this case is a reserved keyword.
Kyle Piddington
Comment 4 2021-06-14 15:21:12 PDT
Kenneth Russell
Comment 5 2021-06-14 15:22:03 PDT
Comment on attachment 431370 [details] Patch Great! r+
EWS Watchlist
Comment 6 2021-06-14 15:22:20 PDT
Note that there are important steps to take when updating ANGLE. See https://trac.webkit.org/wiki/UpdatingANGLE
Kyle Piddington
Comment 7 2021-06-14 16:28:30 PDT
Kenneth Russell
Comment 8 2021-06-14 16:50:09 PDT
Comment on attachment 431383 [details] Patch Infinity support looks good. r+
Kyle Piddington
Comment 9 2021-06-15 13:55:11 PDT
Comment on attachment 431383 [details] Patch Test failure seems unrelated.
EWS
Comment 10 2021-06-15 14:02:59 PDT
Committed r278898 (238839@main): <https://commits.webkit.org/238839@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 431383 [details].
M
Comment 11 2021-06-29 13:23:08 PDT
I just checked the examples (and my app) against the new iOS15 Beta 2 and this bug still exists for the Tensorflow.js examples. Was the conclusion that Tensorflow.js needs to make changes to support Safari in iOS15 or was this patch not included in the new release? Just wanted to make sure I understood and can ping the TFJS team on Github if needed.
M
Comment 12 2021-06-30 07:57:45 PDT
(In reply to Kenneth Russell from comment #2) > Kyle, would you be able to triage this? TensorFlow.js is a major WebGL use > case so investigating this regression is urgent. Hey Kenneth -- I just wanted to ping you on this since I noticed this error/bug is still present in Safari/Webkit in the new iOS15 Beta 2. I wasn't sure if I should change the status as I'm not on the WebKit team and don't have much experience with Radar. Is this now in the TFJS team's hands or can it get a second look here?
Jon Lee
Comment 13 2021-06-30 09:50:43 PDT
The fix did not make it into beta 2. It likely will make it into the next one.
Note You need to log in before you can comment on or make changes to this bug.