[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:


![flutter_05](https://github.com/flutter/engine/assets/168174/36f41602-511c-4b62-95d6-e09b56f89566)

---

## 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>


![Disabled](https://github.com/flutter/engine/assets/168174/0b00e278-fb8f-468d-b5ae-896341789d3f)

![Enabled](https://github.com/flutter/engine/assets/168174/045d056a-2a23-4a27-be9a-b8fbc3e60fb8)

</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>
This commit is contained in:
Matan Lurey 2023-10-24 11:01:00 -07:00 committed by GitHub
parent 9900774b34
commit 49b4523152
6 changed files with 98 additions and 95 deletions

View File

@ -106,6 +106,19 @@ CapabilitiesGLES::CapabilitiesGLES(const ProcTableGLES& gl) {
gl.GetDescription()->HasExtension(kOESTextureBorderClampExt)) {
supports_decal_sampler_address_mode_ = true;
}
if (gl.GetDescription()->HasExtension(
"GL_EXT_multisampled_render_to_texture") &&
// The current implementation of MSAA support in Impeller GLES requires
// the use of glBlitFramebuffer, which is not available on all GLES
// implementations. We can't use MSAA on these platforms yet.
gl.BlitFramebuffer.IsAvailable()) {
// We hard-code 4x MSAA, so let's make sure it's supported.
GLint value = 0;
gl.GetIntegerv(GL_MAX_SAMPLES_EXT, &value);
supports_offscreen_msaa_ = value >= 4;
}
}
size_t CapabilitiesGLES::GetMaxTextureUnits(ShaderStage stage) const {
@ -124,7 +137,7 @@ size_t CapabilitiesGLES::GetMaxTextureUnits(ShaderStage stage) const {
}
bool CapabilitiesGLES::SupportsOffscreenMSAA() const {
return false;
return supports_offscreen_msaa_;
}
bool CapabilitiesGLES::SupportsSSBO() const {

View File

@ -118,6 +118,7 @@ class CapabilitiesGLES final
private:
bool supports_framebuffer_fetch_ = false;
bool supports_decal_sampler_address_mode_ = false;
bool supports_offscreen_msaa_ = false;
};
} // namespace impeller

View File

@ -185,7 +185,7 @@ constexpr std::optional<GLenum> ToTextureTarget(TextureType type) {
case TextureType::kTexture2D:
return GL_TEXTURE_2D;
case TextureType::kTexture2DMultisample:
return std::nullopt;
return GL_TEXTURE_2D;
case TextureType::kTextureCube:
return GL_TEXTURE_CUBE_MAP;
case TextureType::kTextureExternalOES:

View File

@ -6,7 +6,9 @@
#include "flutter/fml/trace_event.h"
#include "fml/closure.h"
#include "fml/logging.h"
#include "impeller/base/validation.h"
#include "impeller/core/texture_descriptor.h"
#include "impeller/renderer/backend/gles/context_gles.h"
#include "impeller/renderer/backend/gles/device_buffer_gles.h"
#include "impeller/renderer/backend/gles/formats_gles.h"
@ -125,6 +127,7 @@ struct RenderPassData {
Scalar clear_depth = 1.0;
std::shared_ptr<Texture> color_attachment;
std::shared_ptr<Texture> resolve_attachment;
std::shared_ptr<Texture> depth_attachment;
std::shared_ptr<Texture> stencil_attachment;
@ -186,6 +189,7 @@ struct RenderPassData {
return false;
}
}
if (auto depth = TextureGLES::Cast(pass_data.depth_attachment.get())) {
if (!depth->SetAsFramebufferAttachment(
GL_FRAMEBUFFER, TextureGLES::AttachmentPoint::kDepth)) {
@ -470,6 +474,45 @@ struct RenderPassData {
}
}
// When we have a resolve_attachment, MSAA is being used. We blit from the
// MSAA FBO to the resolve FBO, otherwise the resolve FBO ends up being
// incomplete (because it has no attachments).
//
// Note that this only works on OpenGLES 3.0+, or put another way, in older
// versions of OpenGLES, MSAA is not currently supported by Impeller. It's
// possible to work around this issue a few different ways (not yet done).
//
// TODO(matanlurey): See https://github.com/flutter/flutter/issues/137093.
if (!is_default_fbo && pass_data.resolve_attachment) {
// MSAA should not be enabled if BlitFramebuffer is not available.
FML_DCHECK(gl.BlitFramebuffer.IsAvailable());
GLuint draw_fbo = GL_NONE;
gl.GenFramebuffers(1u, &draw_fbo);
gl.BindFramebuffer(GL_FRAMEBUFFER, draw_fbo);
auto resolve = TextureGLES::Cast(pass_data.resolve_attachment.get());
if (!resolve->SetAsFramebufferAttachment(
GL_FRAMEBUFFER, TextureGLES::AttachmentPoint::kColor0)) {
return false;
}
gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, draw_fbo);
gl.BindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
auto size = pass_data.resolve_attachment->GetSize();
gl.BlitFramebuffer(0, // srcX0
0, // srcY0
size.width, // srcX1
size.height, // srcY1
0, // dstX0
0, // dstY0
size.width, // dstX1
size.height, // dstY1
GL_COLOR_BUFFER_BIT, // mask
GL_NEAREST // filter
);
}
if (gl.DiscardFramebufferEXT.IsAvailable()) {
std::vector<GLenum> attachments;
@ -498,11 +541,6 @@ struct RenderPassData {
attachments.data() // size
);
}
#ifdef IMPELLER_DEBUG
if (is_default_fbo) {
tracer->MarkFrameEnd(gl);
}
#endif // IMPELLER_DEBUG
return true;
}
@ -531,6 +569,7 @@ bool RenderPassGLES::OnEncodeCommands(const Context& context) const {
/// Setup color data.
///
pass_data->color_attachment = color0.texture;
pass_data->resolve_attachment = color0.resolve_texture;
pass_data->clear_color = color0.clear_color;
pass_data->clear_color_attachment = CanClearAttachment(color0.load_action);
pass_data->discard_color_attachment =
@ -548,7 +587,7 @@ bool RenderPassGLES::OnEncodeCommands(const Context& context) const {
}
//----------------------------------------------------------------------------
/// Setup depth data.
/// Setup stencil data.
///
if (stencil0.has_value()) {
pass_data->stencil_attachment = stencil0->texture;

View File

@ -12,6 +12,7 @@
#include "impeller/base/allocation.h"
#include "impeller/base/validation.h"
#include "impeller/core/formats.h"
#include "impeller/core/texture_descriptor.h"
#include "impeller/renderer/backend/gles/formats_gles.h"
namespace impeller {
@ -21,19 +22,22 @@ static TextureGLES::Type GetTextureTypeFromDescriptor(
const auto usage = static_cast<TextureUsageMask>(desc.usage);
const auto render_target =
static_cast<TextureUsageMask>(TextureUsage::kRenderTarget);
if (usage == render_target) {
const auto is_msaa = desc.sample_count == SampleCount::kCount4;
if (usage == render_target && !is_msaa) {
// TODO(matanlurey): MSAA render buffers?
// See https://github.com/flutter/flutter/issues/137095.
return TextureGLES::Type::kRenderBuffer;
}
return TextureGLES::Type::kTexture;
return is_msaa ? TextureGLES::Type::kTextureMultisampled
: TextureGLES::Type::kTexture;
}
HandleType ToHandleType(TextureGLES::Type type) {
switch (type) {
case TextureGLES::Type::kTexture:
case TextureGLES::Type::kTextureMultisampled:
return HandleType::kTexture;
case TextureGLES::Type::kRenderBuffer:
// MSAA textures are treated as render buffers.
case TextureGLES::Type::kRenderBufferMultisampled:
return HandleType::kRenderBuffer;
}
FML_UNREACHABLE();
@ -118,8 +122,17 @@ struct TexImage2DData {
external_format = GL_RGBA;
type = GL_HALF_FLOAT;
break;
case PixelFormat::kUnknown:
// TODO(matanlurey): This is a combined depth stencil format (like
// kD24UnormS8Uint below). We should find a way to use a stencil-only
// format instead.
//
// See https://github.com/flutter/flutter/issues/137094.
case PixelFormat::kS8UInt:
internal_format = GL_DEPTH_STENCIL;
external_format = GL_DEPTH_STENCIL;
type = GL_UNSIGNED_INT_24_8;
break;
case PixelFormat::kUnknown:
case PixelFormat::kD24UnormS8Uint:
case PixelFormat::kD32FloatS8UInt:
case PixelFormat::kR8UNormInt:
@ -133,52 +146,9 @@ struct TexImage2DData {
}
TexImage2DData(PixelFormat pixel_format,
std::shared_ptr<const fml::Mapping> mapping) {
switch (pixel_format) {
case PixelFormat::kUnknown:
return;
case PixelFormat::kA8UNormInt: {
internal_format = GL_ALPHA;
external_format = GL_ALPHA;
type = GL_UNSIGNED_BYTE;
data = std::move(mapping);
break;
}
case PixelFormat::kR8G8B8A8UNormInt: {
internal_format = GL_RGBA;
external_format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
data = std::move(mapping);
break;
}
case PixelFormat::kR32G32B32A32Float: {
internal_format = GL_RGBA;
external_format = GL_RGBA;
type = GL_FLOAT;
data = std::move(mapping);
break;
}
case PixelFormat::kR16G16B16A16Float: {
internal_format = GL_RGBA;
external_format = GL_RGBA;
type = GL_HALF_FLOAT;
data = std::move(mapping);
break;
}
case PixelFormat::kR8G8B8A8UNormIntSRGB:
case PixelFormat::kB8G8R8A8UNormInt:
case PixelFormat::kB8G8R8A8UNormIntSRGB:
case PixelFormat::kS8UInt:
case PixelFormat::kD24UnormS8Uint:
case PixelFormat::kD32FloatS8UInt:
case PixelFormat::kR8UNormInt:
case PixelFormat::kR8G8UNormInt:
case PixelFormat::kB10G10R10XRSRGB:
case PixelFormat::kB10G10R10XR:
case PixelFormat::kB10G10R10A10XR:
return;
}
is_valid_ = true;
std::shared_ptr<const fml::Mapping> mapping)
: TexImage2DData(pixel_format) {
data = std::move(mapping);
}
bool IsValid() const { return is_valid_; }
@ -362,7 +332,8 @@ void TextureGLES::InitializeContentsIfNecessary() const {
}
switch (type_) {
case Type::kTexture: {
case Type::kTexture:
case Type::kTextureMultisampled: {
TexImage2DData tex_data(GetTextureDescriptor().format);
if (!tex_data.IsValid()) {
VALIDATION_LOG << "Invalid format for texture image.";
@ -382,7 +353,6 @@ void TextureGLES::InitializeContentsIfNecessary() const {
nullptr // data
);
}
} break;
case Type::kRenderBuffer: {
auto render_buffer_format =
@ -401,26 +371,6 @@ void TextureGLES::InitializeContentsIfNecessary() const {
);
}
} break;
case Type::kRenderBufferMultisampled: {
auto render_buffer_msaa =
ToRenderBufferFormat(GetTextureDescriptor().format);
if (!render_buffer_msaa.has_value()) {
VALIDATION_LOG << "Invalid format for render-buffer MSAA image.";
return;
}
gl.BindRenderbuffer(GL_RENDERBUFFER, handle.value());
{
TRACE_EVENT0("impeller", "RenderBufferStorageInitialization");
gl.RenderbufferStorageMultisampleEXT(
GL_RENDERBUFFER, // target
4, // samples
render_buffer_msaa.value(), // internal format
size.width, // width
size.height // height
);
}
break;
}
}
}
@ -438,7 +388,8 @@ bool TextureGLES::Bind() const {
}
const auto& gl = reactor_->GetProcTable();
switch (type_) {
case Type::kTexture: {
case Type::kTexture:
case Type::kTextureMultisampled: {
const auto target = ToTextureTarget(GetTextureDescriptor().type);
if (!target.has_value()) {
VALIDATION_LOG << "Could not bind texture of this type.";
@ -447,8 +398,6 @@ bool TextureGLES::Bind() const {
gl.BindTexture(target.value(), handle.value());
} break;
case Type::kRenderBuffer:
// MSAA textures are treated as render buffers.
case Type::kRenderBufferMultisampled:
gl.BindRenderbuffer(GL_RENDERBUFFER, handle.value());
break;
}
@ -516,6 +465,7 @@ bool TextureGLES::SetAsFramebufferAttachment(GLenum target,
return false;
}
const auto& gl = reactor_->GetProcTable();
switch (type_) {
case Type::kTexture:
gl.FramebufferTexture2D(target, // target
@ -525,16 +475,7 @@ bool TextureGLES::SetAsFramebufferAttachment(GLenum target,
0 // level
);
break;
case Type::kRenderBuffer:
gl.FramebufferRenderbuffer(target, // target
ToAttachmentPoint(point), // attachment
GL_RENDERBUFFER, // render-buffer target
handle.value() // render-buffer
);
break;
case Type::kRenderBufferMultisampled:
// Assume that when MSAA is enabled, we're using 4x MSAA.
FML_DCHECK(GetTextureDescriptor().sample_count == SampleCount::kCount4);
case Type::kTextureMultisampled:
gl.FramebufferTexture2DMultisampleEXT(
target, // target
ToAttachmentPoint(point), // attachment
@ -544,7 +485,16 @@ bool TextureGLES::SetAsFramebufferAttachment(GLenum target,
4 // samples
);
break;
case Type::kRenderBuffer:
gl.FramebufferRenderbuffer(target, // target
ToAttachmentPoint(point), // attachment
GL_RENDERBUFFER, // render-buffer target
handle.value() // render-buffer
);
gl.BindRenderbuffer(GL_RENDERBUFFER, GL_NONE);
break;
}
return true;
}

View File

@ -17,8 +17,8 @@ class TextureGLES final : public Texture,
public:
enum class Type {
kTexture,
kTextureMultisampled,
kRenderBuffer,
kRenderBufferMultisampled,
};
enum class IsWrapped {