Audit and upgrade OpenGL version and canvas code
Open, Needs TriagePublic

Description

During the CY2022 upgrade MR, which I did along with @alvinhochun's MR audit, I noticed that we have quite a few shortcomings with our support of OpenGL.

  • We are still stuck on 3.2 core on macOS -- all hardware sold during the past decade, even M1, now supports 4.1. Even macOS returns 4.1 when asked for a core profile, no other version.
  • We claim to support OpenGL ES 2, but as Alvin's MR showed, we treat it as unsupported because it is not OpenGL 2.1 (!!!).
    • Nvidia provides ES2 only on Linux desktops, and I'm about to check it in my Potato with Armbian.
  • We have the supportsLod() check around, which according to the author should have been deleted since we migrated to 5.7... we're now in 5.12 and Soon(tm) on 6.
  • OCIO v1 is dumb enough that it'll work on GLES, but v2 locks us to the legacy pipeline.
    • as it uses a single LUT texture, but the default processor uses 1D textures.
  • We have a lot of unused shaders and duplicated code in the support checker.

I'd like to hear your takes!

lsegovia created this task.Sep 10 2021, 2:51 PM
rempt added a comment.Sep 10 2021, 3:12 PM

Make sure that when going from core 3 to core 4, the Qt opengl qpainter engine doesn't stop working. Afair, that was the big problem.

I'll check it tomorrow. On Linux we seem to be still on 3.0 (at least on my Linux Laptop).

Do we really support OpenGL ES 2 at all? On Windows we require Direct3D 11 which is needed to get OpenGL ES 3 with ANGLE.

Do we really support OpenGL ES 2 at all? On Windows we require Direct3D 11 which is needed to get OpenGL ES 3 with ANGLE.

There's an anomalous situation; we accept:

OpenGL 3 AND (deprecated extensions OR openGL ES)
OR OpenGL 2.01

That last one is the default Apple profile; I understood it initially as "we support ES 2.0" since they are both equally crippled for our purposes.

I'll check it tomorrow. On Linux we seem to be still on 3.0 (at least on my Linux Laptop).

Linux requires 3.0+Compatibility but will give you 4.x happily. Here at least, it's 4.6 compatibility, and ES2.0 if I compile with -opengl es2.

I'm not sure why we ask for a Compatibility profile, given that we run already a Core profile in macOS, though.

Hi, @lsegovia!

I guess that we should take a bit different approach to the audit. It is quite difficult to discuss "what version of OpenGL we should set as a minimum requirement". We will always have some users with rather old hardware (it happened when we tried to drop openGL 2 support, but then recovered it back).

It we want to make a proper audit, we need to make a list of OpenGL features we use. And for each feature write down the following information:

  • where is this feature used in Krita?
  • is it an optional feature?
  • what version of openGL this feature became core profile? what extension is needed for lower versions of openGL?
  • what version of openGL ES this feature became core profile? what extension is needed for lower versions of openGL ES?

When we have such a list/table, we can increase granularity of our feature-recognition code a lot. Right now we basically have only two checks, hasOpenGL3() and isOpenGLES(). It leads to problems like, our canvas cannot use FBO on Linux, because it returns openGL 3.0, while FBO is technically supported.

Here is an example of what I mean:

  • Sync Objects
    • KisOpenGLCanvas2::isBusy()
    • this feature is optional; Krita can work without it, though there will be some delay when painting with small brushes
    • core since openGL 3.2
    • ARB_sync
    • core since openGL ES 3.0
    • none

That is, we can add KisOpenGL::supportsSync(), which check all these numbers extensions.

With such granularity, we don't really care, what is the profile version returned by the system. We can just request all the versions from highest to lowest until the driver satisfies our request. We have all infrastructure for that (see KisOpenGLModeProber)

PS:

Linux requires 3.0+Compatibility but will give you 4.x happily

Well, it gives me 3.0 all the time on my laptop. Though I'm not sure where we tell it what version we want.

For the point of old hardware: on macOS: the oldest OS version we support is the oldest Qt supports, this is macOS 10.13. openGL 4.1 coreprofile was added in macos 10.9, so we can be sure older hardware will not be an issue here, they are not capable of running krita today because of Qt.

Well, it gives me 3.0 all the time on my laptop. Though I'm not sure where we tell it what version we want.

In KisOpenGLProber we ask it for 3.0 compatibility+deprecated on Linux. (Yikes.)

Well, it gives me 3.0 all the time on my laptop. Though I'm not sure where we tell it what version we want.

In KisOpenGLProber we ask it for 3.0 compatibility+deprecated on Linux. (Yikes.)

Well, then we can easily implement sequential requests for different formats :)

lsegovia added a comment.EditedSep 22 2021, 5:45 PM

List of OpenGL features we use (WIP)


VAO/VBO

  • KisOpenGLCanvas2::renderCanvasGL
  • KisOpenGLCanvas2::initializeGL
  • Core since OpenGL 3.0 (3.2 w/programmable pipeline)
  • Core since OpenGL ES 3.0
  • ARB_vertex_array_object

Vertex buffer objects

  • KisOpenGLCanvas2::drawGrid et. al.
  • Looks like they're used to draw the pixel grid
  • Core since OpenGL 2.0, OpenGL ES v.???

Framebuffer objects

  • used currently for rendering cursor with image overlay fx.
  • useFBOForToolOutlineRendering
  • Core since OpenGL 3.0
  • Core since OpenGL ES 2.0
  • GL_ARB_framebuffer_object
    • DO NOT USE GL_EXT_framebuffer_object, that's fixed function

Level of detail objects

  • used for HQ filtering
  • *maybe* Core since OpenGL 3.0
  • Core since OpenGL ES 3.0
  • GL_EXT_shader_texture_lod
    • detecting this extension w/GLES < 3.0 means you need to target texture<N>DLodEXT with a define -- see my cleanup branch
    • using this extension in GLES3 will result in a shader build error

Sync Objects

Floating point textures

  • they are needed for enabling HDR (Angle)
  • initializeRGBA16FTextures in kis_opengl_image_textures.cpp
  • Core since OpenGL and OpenGL ES 3.0
  • They otherwise need:
    • GL: GL_ARB_half_float_pixel or GL_ATI_texture_float
    • GLES 2: GL_EXT_texture_storage and:
      • F32: GL_OES_texture_half_float, GL_EXT_color_buffer_half_float and GL_OES_texture_half_float_linear
      • F16: GL_OES_texture_float and GL_OES_texture_float_linear (haven't checked, but GL_EXT_color_buffer_float probably as well)

I recall there being an ANGLE-specific extension GL_EXT_texture_format_BGRA8888 (maybe that's not really ANGLE-specific...) that we need to render textures in this format on OpenGL ES.

VAO/VBO

  • OES_vertex_array_object on openGL ES 2.0

Vertex buffer objects

  • also used to paint normal image tiles
  • core in openGL ES 2.0

Framebuffer objects

  • we use a check from Qt and it also uses GL_EXT_framebuffer_object. Is it a problem? For the framebuffer we just use QOpenGLFrameBufferObject.
if (extensions.match("GL_EXT_framebuffer_object") ||
          extensions.match("GL_ARB_framebuffer_object"))
          features |= QGLFunctions::Framebuffers;

Buffer mapping

  • optional, Krita can work without it
  • KisTextureTile::update() and KisOpenGLBufferCreationGuard
  • core since openGL 2.0
  • core since openGL ES 3
  • extensions for openGL ES 2.0: "GL_OES_mapbuffer" or "GL_EXT_map_buffer_range", the latter is used by Qt as an optimization, but not strictly needed
  • extension for openGL 2.0: "GL_ARB_map_buffer_range" is used by Qt as an optimization, but not strictly needed

Buffer Discarding

  • used to upload image textures efficiently in KisOpenGLBufferCircularStorage::BufferBinder
  • this option is disabled by default atm (needs testing from people)
  • core since openGL 4.3
  • not available in openGL ES at all
  • extension for openGL: "GL_ARB_invalidate_subdata"

Buffer Discarding


  • not available in openGL ES at all
  • extension for openGL: "GL_ARB_invalidate_subdata"

This is not correct, section "Dependencies on OpenGL ES 2.0" does list it as available; also, none of the simplifications apply because you only used InvalidateBufferData for your macOS MR.

This is not correct, section "Dependencies on OpenGL ES 2.0" does list it as available; also, none of the simplifications apply because you only used InvalidateBufferData for your macOS MR.

Hm, weird, I just ctrl+f'ed in the official registry and didn't find it :) Anyway, it is good that it is also present in openGL ES :)

lsegovia claimed this task.Jan 10 2022, 8:42 PM

Will also need to check what the small color selector really needs: https://invent.kde.org/graphics/krita/-/merge_requests/1308#note_384330

I just realized that hasOpenGL3 checks for OpenGL version >= 3.2, and Krita only asks for a surface of version 3.0. Does the small color selector not work with OpenGL 3.0? And what's the point of checking for >= 3.2 if it only asks for 3.0?

Change was deployed in https://invent.kde.org/graphics/krita/-/commit/ca645e71a09e1ee81dc0f7ef153b00304af058de and reverted in https://invent.kde.org/graphics/krita/-/commit/fa671d407fd6d89c87c15c67d486e5dd1c7b0301.

According to Dmitry, Mesa will refuse to instance a surface if the version is beyond 3.3 on 20.04, so I'll need to narrow the version down.