Matan Lurey
49b4523152
[Impeller] Enable MSAA for OpenGLES: Take 2. ( flutter/engine#47030 )
...
Closes https://github.com/flutter/flutter/issues/130045 .
Continues the work started in
https://github.com/flutter/engine/pull/46381 . _This is PR supercedes
https://github.com/flutter/engine/pull/46688._
It's worth calling out the mechanism we're using is only supported in
OpenGL 3.0+, so we'll need a different solution (either by default, or
when Blit is not available) to get proper device support. I'll file an
issue before merging.
## Status
Appears to work! I validated it on a local demo app, flutter_gallery,
and Wonderous.
Example:

---
## Background
<details>
<summary>History</summary>
<br>
**Still blocked**, but MSAA is working provided you use a phone with
OpenGLES 3.0+. The last bit is getting stencil attachments to work again
(they currently crash with a `GL_INVALID_OPERATION`).
Compared to #46688 , we''ve corrected some incorrect OpenGL calls and
assumptions - for example we now have both multi-sampled textures
similar to the
[`MultisampledFBO.cpp`](https://github.com/ARM-software/opengl-es-sdk-for-android/blob/master/samples/advanced_samples/MultisampledFBO/jni/MultisampledFBO.cpp#L702 )
example.
After doing so, the GL driver is successfully called, and no errors or
crashes persist. Yay!
We did need to use
[`glBlitFramebuffer`](https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glBlitFramebuffer.xhtml )
to move from the resolve texture to the color attachment, and referenced
some other [example
code](346624ecc5/YoutubeOpenGL%2027%20-%20Normal%20Maps/Main.cpp (L274) )
for that.
<details>
<summary>Example App</summary>
```dart
import 'package:flutter/material.dart';
void main() {
runApp(const MainApp());
}
class MainApp extends StatefulWidget {
const MainApp({super.key});
@override
State<MainApp> createState() => _MainAppState();
}
class _MainAppState extends State<MainApp> {
bool msaa = true;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Force offscreen MSAA'),
actions: [
Switch(
value: msaa,
onChanged: (value) {
setState(() {
msaa = value;
});
},
),
],
),
body: Center(
child: ForceOffscreenMSAA(opaque: !msaa),
),
),
);
}
}
// Draws 2 overlapping circles (BoxDecoration/BoxShape) wrapped in 50% opacity.
class ForceOffscreenMSAA extends StatelessWidget {
final bool opaque;
const ForceOffscreenMSAA({required this.opaque, super.key});
@override
Widget build(BuildContext context) {
return Opacity(
opacity: opaque ? 1.0 : 0.5,
child: const DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
child: SizedBox(
width: 300,
height: 300,
child: DecoratedBox(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.green,
),
),
),
),
);
}
}
```
</details>
<details>
<summary>Screenshots</summary>


</details>
<details>
<summary>Open GL Commands during MSAA Render</summary>
```txt
glClearStencil(, 0)
glDisable(, 3089)
glDisable(, 2929)
glDisable(, 2960)
glDisable(, 2884)
glDisable(, 3042)
glColorMask(, 1, 1, 1, 1)
glClear(, 17664)
glPushDebugGroupKHR(, 33354, 1367, 10, Solid Fill)
glDisable(, 3042)
glColorMask(, , , , )
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7680)
glStencilFuncSeparate(, 1032, 514, 0, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 787, 787)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glGenBuffers(, 1, 0x6f9900a578)
glBindBuffer(, 34962, 1)
glBufferData(, 34962, 4480, , 35044)
glUseProgram(, 56)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 2, 5126, 0, 8, 0x0)
glUniformMatrix4fv(, 0, 1, 0, 0xb4000070aadbc860)
glUniform4fv(, 1, 1, 0xb4000070aadbc8a0)
glBindBuffer(, 34963, 1)
glDrawElements(, 4, 426, 5123, 0x480)
glDisableVertexAttribArray(, 0)
glUseProgram(, 0)
glPopDebugGroupKHR()
glPushDebugGroupKHR(, 33354, 1369, 10, Solid Fill)
glDisable(, 3042)
glColorMask(, , , , )
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7680)
glStencilFuncSeparate(, 1032, 514, 0, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 787, 787)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glBindBuffer(, 34962, 1)
glUseProgram(, 56)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 2, 5126, 0, 8, 0x880)
glUniformMatrix4fv(, 0, 1, 0, 0xb4000070aadbd160)
glUniform4fv(, 1, 1, 0xb4000070aadbd1a0)
glBindBuffer(, 34963, 1)
glDrawElements(, 4, 426, 5123, 0xd00)
glDisableVertexAttribArray(, 0)
glUseProgram(, 0)
glPopDebugGroupKHR()
glDiscardFramebufferEXT(, 36160, 3, 0xb4000071cad5b590)
glBindFramebuffer(, 36160, 0)
glDeleteFramebuffers(, 1, 0x6f9900b25c)
glPopDebugGroupKHR()
glDeleteBuffers(, 1, 0x6f9900ce98)
glDebugMessageControlKHR(, 4352, 4352, 4352, 0, nullptr, 1)
glPushDebugGroupKHR(, 33354, 1370, 39, EntityPass Render Pass: Depth=0 Count=0)
glClearColor(, 1, 0.984314, 0.996078, 1)
glClearStencil(, 0)
glDisable(, 3089)
glDisable(, 2929)
glDisable(, 2960)
glDisable(, 2884)
glDisable(, 3042)
glColorMask(, 1, 1, 1, 1)
glClear(, 17664)
glPushDebugGroupKHR(, 33354, 1371, 21, Texture Fill: Subpass)
glEnable(, 3042)
glBlendFuncSeparate(, 1, 771, 1, 771)
glBlendEquationSeparate(, 32774, 32774)
glColorMask(, , , , )
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7680)
glStencilFuncSeparate(, 1032, 514, 0, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 1080, 2029)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glGenBuffers(, 1, 0x6f9900bfc8)
glBindBuffer(, 34962, 1)
glBufferData(, 34962, 11360, , 35044)
glUseProgram(, 57)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 2, 5126, 0, 16, 0x0)
glEnableVertexAttribArray(, 1)
glVertexAttribPointer(, 1, 2, 5126, 0, 16, 0x8)
glUniformMatrix4fv(, 1, 1, 0, 0xb40000705ad2f200)
glUniform1fv(, 2, 1, 0xb40000705ad2f240)
glUniform1fv(, 3, 1, 0xb40000705ad2f244)
glActiveTexture(, 33984)
glBindTexture(, 3553, 1)
glTexParameteri(, 3553, 10241, 9728)
glTexParameteri(, 3553, 10240, 9728)
glTexParameteri(, 3553, 10242, 33071)
glTexParameteri(, 3553, 10243, 33071)
glUniform1i(, 0, 0)
glDrawArrays(, 5, 0, 4)
glDisableVertexAttribArray(, 0)
glDisableVertexAttribArray(, 1)
glUseProgram(, 0)
glPopDebugGroupKHR()
glPushDebugGroupKHR(, 33354, 1373, 10, Solid Fill)
glDisable(, 3042)
glColorMask(, , , , )
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7680)
glStencilFuncSeparate(, 1032, 514, 0, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 1080, 2029)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glBindBuffer(, 34962, 1)
glUseProgram(, 58)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 2, 5126, 0, 8, 0x180)
glUniformMatrix4fv(, 0, 1, 0, 0xb40000705ad2f300)
glUniform4fv(, 1, 1, 0xb40000705ad2f340)
glDrawArrays(, 5, 0, 4)
glDisableVertexAttribArray(, 0)
glUseProgram(, 0)
glPopDebugGroupKHR()
glPushDebugGroupKHR(, 33354, 1374, 14, Intersect Clip)
glEnable(, 3042)
glBlendFuncSeparate(, 0, 1, 0, 1)
glBlendEquationSeparate(, 32774, 32774)
glColorMask(,
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7682)
glStencilFuncSeparate(, 1032, 514, 0, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 1080, 2029)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glBindBuffer(, 34962, 1)
glUseProgram(, 59)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 2, 5126, 0, 8, 0x280)
glUniformMatrix4fv(, 0, 1, 0, 0xb40000705ad2f400)
glDrawArrays(, 5, 0, 4)
glDisableVertexAttribArray(, 0)
glUseProgram(, 0)
glPopDebugGroupKHR()
glPushDebugGroupKHR(, 33354, 1375, 9, TextFrame)
glEnable(, 3042)
glBlendFuncSeparate(, 1, 771, 1, 771)
glBlendEquationSeparate(, 32774, 32774)
glColorMask(, , , , )
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7680)
glStencilFuncSeparate(, 1032, 514, 1, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 1080, 2029)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glBindBuffer(, 34962, 1)
glUseProgram(, 60)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 4, 5126, 0, 48, 0x4c0)
glEnableVertexAttribArray(, 3)
glVertexAttribPointer(, 3, 2, 5126, 0, 48, 0x4e8)
glEnableVertexAttribArray(, 1)
glVertexAttribPointer(, 1, 4, 5126, 0, 48, 0x4d0)
glEnableVertexAttribArray(, 2)
glVertexAttribPointer(, 2, 2, 5126, 0, 48, 0x4e0)
glUniformMatrix4fv(, 1, 1, 0, 0xb40000705ad2f500)
glUniformMatrix4fv(, 2, 1, 0, 0xb40000705ad2f540)
glUniform2fv(, 3, 1, 0xb40000705ad2f580)
glUniform2fv(, 4, 1, 0xb40000705ad2f588)
glUniform4fv(, 5, 1, 0xb40000705ad2f590)
glUniform1fv(, 6, 1, 0xb40000705ad2f5a0)
glActiveTexture(, 33984)
glBindTexture(, 3553, 2)
glTexParameteri(, 3553, 10241, 9728)
glTexParameteri(, 3553, 10240, 9728)
glTexParameteri(, 3553, 10242, 33071)
glTexParameteri(, 3553, 10243, 33071)
glUniform1i(, 0, 0)
glDrawArrays(, 4, 0, 120)
glDisableVertexAttribArray(, 0)
glDisableVertexAttribArray(, 3)
glDisableVertexAttribArray(, 1)
glDisableVertexAttribArray(, 2)
glUseProgram(, 0)
glPopDebugGroupKHR()
glPushDebugGroupKHR(, 33354, 1376, 10, Solid Fill)
glDisable(, 3042)
glColorMask(, , , , )
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7680)
glStencilFuncSeparate(, 1032, 514, 1, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 1080, 2029)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glBindBuffer(, 34962, 1)
glUseProgram(, 61)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 2, 5126, 0, 8, 0x1b40)
glUniformMatrix4fv(, 0, 1, 0, 0xb40000705ad30f00)
glUniform4fv(, 1, 1, 0xb40000705ad30f40)
glBindBuffer(, 34963, 1)
glDrawElements(, 4, 144, 5123, 0x1cd0)
glDisableVertexAttribArray(, 0)
glUseProgram(, 0)
glPopDebugGroupKHR()
glPushDebugGroupKHR(, 33354, 1377, 10, Solid Fill)
glDisable(, 3042)
glColorMask(, , , , )
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7680)
glStencilFuncSeparate(, 1032, 514, 1, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 1080, 2029)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glBindBuffer(, 34962, 1)
glUseProgram(, 61)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 2, 5126, 0, 8, 0x1e80)
glUniformMatrix4fv(, 0, 1, 0, 0xb40000705ad31200)
glUniform4fv(, 1, 1, 0xb40000705ad31240)
glBindBuffer(, 34963, 1)
glDrawElements(, 4, 114, 5123, 0x1fc0)
glDisableVertexAttribArray(, 0)
glUseProgram(, 0)
glPopDebugGroupKHR()
glPushDebugGroupKHR(, 33354, 1378, 12, Restore Clip)
glEnable(, 3042)
glBlendFuncSeparate(, 0, 1, 0, 1)
glBlendEquationSeparate(, 32774, 32774)
glColorMask(,
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7681)
glStencilFuncSeparate(, 1032, 513, 0, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 1080, 2029)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glBindBuffer(, 34962, 1)
glUseProgram(, 62)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 2, 5126, 0, 8, 0x2180)
glUniformMatrix4fv(, 0, 1, 0, 0xb40000705ad31300)
glDrawArrays(, 5, 0, 4)
glDisableVertexAttribArray(, 0)
glUseProgram(, 0)
glPopDebugGroupKHR()
glPushDebugGroupKHR(, 33354, 1379, 12, RRect Shadow)
glEnable(, 3042)
glBlendFuncSeparate(, 1, 771, 1, 771)
glBlendEquationSeparate(, 32774, 32774)
glColorMask(, , , , )
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7680)
glStencilFuncSeparate(, 1032, 514, 0, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 1080, 2029)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glBindBuffer(, 34962, 1)
glUseProgram(, 63)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 2, 5126, 0, 8, 0x2240)
glUniformMatrix4fv(, 0, 1, 0, 0xb40000705ad31400)
glUniform4fv(, 1, 1, 0xb40000705ad31500)
glUniform2fv(, 2, 1, 0xb40000705ad31510)
glUniform1fv(, 3, 1, 0xb40000705ad31518)
glUniform1fv(, 4, 1, 0xb40000705ad3151c)
glDrawArrays(, 5, 0, 4)
glDisableVertexAttribArray(, 0)
glUseProgram(, 0)
glPopDebugGroupKHR()
glPushDebugGroupKHR(, 33354, 1380, 10, Solid Fill)
glEnable(, 3042)
glBlendFuncSeparate(, 1, 771, 1, 771)
glBlendEquationSeparate(, 32774, 32774)
glColorMask(, , , , )
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7680)
glStencilFuncSeparate(, 1032, 514, 0, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 1080, 2029)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glBindBuffer(, 34962, 1)
glUseProgram(, 64)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 2, 5126, 0, 8, 0x2420)
glUniformMatrix4fv(, 0, 1, 0, 0xb40000705ad31600)
glUniform4fv(, 1, 1, 0xb40000705ad31640)
glDrawArrays(, 5, 0, 4)
glDisableVertexAttribArray(, 0)
glUseProgram(, 0)
glPopDebugGroupKHR()
glPushDebugGroupKHR(, 33354, 1381, 9, TextFrame)
glEnable(, 3042)
glBlendFuncSeparate(, 1, 771, 1, 771)
glBlendEquationSeparate(, 32774, 32774)
glColorMask(, , , , )
glEnable(, 2960)
glStencilOpSeparate(, 1032, 7680, 7680, 7680)
glStencilFuncSeparate(, 1032, 514, 0, 4294967295)
glStencilMaskSeparate(, 1032, 4294967295)
glDisable(, 2929)
glViewport(, 0, 0, 1080, 2029)
glDisable(, 3089)
glDisable(, 2884)
glFrontFace(, 2304)
glBindBuffer(, 34962, 1)
glUseProgram(, 60)
glEnableVertexAttribArray(, 0)
glVertexAttribPointer(, 0, 4, 5126, 0, 48, 0x26c0)
glEnableVertexAttribArray(, 3)
glVertexAttribPointer(, 3, 2, 5126, 0, 48, 0x26e8)
glEnableVertexAttribArray(, 1)
glVertexAttribPointer(, 1, 4, 5126, 0, 48, 0x26d0)
glEnableVertexAttribArray(, 2)
glVertexAttribPointer(, 2, 2, 5126, 0, 48, 0x26e0)
glUniformMatrix4fv(, 1, 1, 0, 0xb40000705ad31700)
glUniformMatrix4fv(, 2, 1, 0, 0xb40000705ad31740)
glUniform2fv(, 3, 1, 0xb40000705ad31780)
glUniform2fv(, 4, 1, 0xb40000705ad31788)
glUniform4fv(, 5, 1, 0xb40000705ad31790)
glUniform1fv(, 6, 1, 0xb40000705ad317a0)
glActiveTexture(, 33984)
glBindTexture(, 3553, 2)
glTexParameteri(, 3553, 10241, 9729)
glTexParameteri(, 3553, 10240, 9729)
glTexParameteri(, 3553, 10242, 33071)
glTexParameteri(, 3553, 10243, 33071)
glUniform1i(, 0, 0)
glDrawArrays(, 4, 0, 30)
glDisableVertexAttribArray(, 0)
glDisableVertexAttribArray(, 3)
glDisableVertexAttribArray(, 1)
glDisableVertexAttribArray(, 2)
glUseProgram(, 0)
glPopDebugGroupKHR()
glDiscardFramebufferEXT(, 36160, 2, 0xb4000071cad5b310)
glPopDebugGroupKHR()
```
</details>
<details>
<summary>AGI Trace</summary>
<img width="590" alt="Screenshot 2023-10-17 at 3 21 44 PM"
src="https://github.com/flutter/engine/assets/168174/ce9fa65c-9a2b-4b82-9f67-af5373d119c1 ">
<img width="336" alt="Screenshot 2023-10-17 at 3 21 51 PM"
src="https://github.com/flutter/engine/assets/168174/8016029a-ec6d-4c18-b200-50c6485656fa ">
</details>
~~As you can see, with MSAA enabled I get a weird mostly-blank artifact
(or sometimes entirely blank).~~ UPDATE: FIXED.
What we tried (h/t @jonahwilliams):
- [x] Using AGI (with the ANGLE adapter, see also [these
oddities](https://developer.android.com/agi/troubleshooting#game_failure_after_using_agi )),
see
[CircleOpacityTrace.gfxtrace.zip](https://github.com/flutter/engine/files/12966311/CircleOpacityTrace.gfxtrace.zip ).
- [x] Print debugging the commands (see above)
- [x] Commenting out `gl.DiscardFramebufferEXT` optimizations
- [x] Render Doc (I need to use a Samsung phone old enough to have
OpenGLES)
/cc @jonahwilliams to add anything else ^
</details>
2023-10-24 11:01:00 -07:00