[graphics/krita] libs/ui/opengl: Add a (hidden) option to invalidate texture buffers right after the usage

Dmitry Kazakov null at kde.org
Tue Sep 28 07:08:39 BST 2021


Git commit 426798ea99f7e2e428f25691072d7c0b82f66844 by Dmitry Kazakov.
Committed on 23/09/2021 at 15:53.
Pushed by dkazakov into branch 'master'.

Add a (hidden) option to invalidate texture buffers right after the usage

When the function is enabled, the buffer is marked as invalidated
right after Krita requested its uploading to the GPU texture. It
should potentially increase the speed of texture uploading and reduce
GPU memory footprint Krita uses.

To enable the option, add the following line into `kritarc`:

useBufferInvalidation=true

You need to also pay attention to the following lines in the system
information log:

supportsBufferInvalidation: true
useBufferInvalidation (config option): true

The first line tells if the feature is supported bu the GPU, the second
tells if the feature is enabled in Krita's config file.

CC:kimageshop at kde.org

M  +5    -1    libs/ui/opengl/KisOpenGLBufferCircularStorage.cpp
M  +3    -0    libs/ui/opengl/KisOpenGLModeProber.cpp
M  +5    -0    libs/ui/opengl/KisOpenGLModeProber.h
M  +30   -0    libs/ui/opengl/kis_opengl.cpp
M  +4    -0    libs/ui/opengl/kis_opengl.h

https://invent.kde.org/graphics/krita/commit/426798ea99f7e2e428f25691072d7c0b82f66844

diff --git a/libs/ui/opengl/KisOpenGLBufferCircularStorage.cpp b/libs/ui/opengl/KisOpenGLBufferCircularStorage.cpp
index 5ceb871530..6becb947e4 100644
--- a/libs/ui/opengl/KisOpenGLBufferCircularStorage.cpp
+++ b/libs/ui/opengl/KisOpenGLBufferCircularStorage.cpp
@@ -7,7 +7,7 @@
 #include "KisOpenGLBufferCircularStorage.h"
 
 #include "kis_assert.h"
-#include <QVector>
+#include "kis_opengl.h"
 
 
 KisOpenGLBufferCircularStorage::BufferBinder::BufferBinder(KisOpenGLBufferCircularStorage *bufferStorage, const void **dataPtr, int dataSize) {
@@ -23,6 +23,10 @@ KisOpenGLBufferCircularStorage::BufferBinder::BufferBinder(KisOpenGLBufferCircul
 KisOpenGLBufferCircularStorage::BufferBinder::~BufferBinder() {
     if (m_buffer) {
         m_buffer->release();
+
+        if (KisOpenGL::useTextureBufferInvalidation()) {
+            KisOpenGL::glInvalidateBufferData(m_buffer->bufferId());
+        }
     }
 }
 
diff --git a/libs/ui/opengl/KisOpenGLModeProber.cpp b/libs/ui/opengl/KisOpenGLModeProber.cpp
index c61ad6ca72..8ad36b78b5 100644
--- a/libs/ui/opengl/KisOpenGLModeProber.cpp
+++ b/libs/ui/opengl/KisOpenGLModeProber.cpp
@@ -325,4 +325,7 @@ KisOpenGLModeProber::Result::Result(QOpenGLContext &context) {
             context.hasExtension("GL_OES_mapbuffer") ||
             context.hasExtension("GL_EXT_map_buffer_range");
 
+    m_supportsBufferInvalidation = !m_isOpenGLES &&
+            ((m_glMajorVersion >= 4 && m_glMinorVersion >= 3) ||
+             context.hasExtension("GL_ARB_invalidate_subdata"));
 }
diff --git a/libs/ui/opengl/KisOpenGLModeProber.h b/libs/ui/opengl/KisOpenGLModeProber.h
index d285b7f00b..af2113b507 100644
--- a/libs/ui/opengl/KisOpenGLModeProber.h
+++ b/libs/ui/opengl/KisOpenGLModeProber.h
@@ -110,6 +110,10 @@ public:
         return m_supportsBufferMapping;
     }
 
+    bool supportsBufferInvalidation() const {
+        return m_supportsBufferInvalidation;
+    }
+
 #ifdef Q_OS_WIN
     // This is only for detecting whether ANGLE is being used.
     // For detecting generic OpenGL ES please check isOpenGLES
@@ -140,6 +144,7 @@ private:
     bool m_isOpenGLES = false;
     bool m_supportsFBO = false;
     bool m_supportsBufferMapping = false;
+    bool m_supportsBufferInvalidation = false;
     QString m_rendererString;
     QString m_driverVersionString;
     QString m_vendorString;
diff --git a/libs/ui/opengl/kis_opengl.cpp b/libs/ui/opengl/kis_opengl.cpp
index bb8817cbd8..cb829f0012 100644
--- a/libs/ui/opengl/kis_opengl.cpp
+++ b/libs/ui/opengl/kis_opengl.cpp
@@ -39,6 +39,8 @@
 #  define GL_RENDERER 0x1F01
 #endif
 
+typedef void (APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC) (GLuint buffer);
+
 using namespace KisOpenGLPrivate;
 
 namespace
@@ -60,6 +62,9 @@ namespace
     KisOpenGL::OpenGLRenderers g_supportedRenderers;
     KisOpenGL::OpenGLRenderer g_rendererPreferredByQt;
 
+    bool g_useBufferInvalidation = false;
+    PFNGLINVALIDATEBUFFERDATAPROC g_glInvalidateBufferData = nullptr;
+
     void overrideSupportedRenderers(KisOpenGL::OpenGLRenderers supportedRenderers, KisOpenGL::OpenGLRenderer preferredByQt) {
         g_supportedRenderers = supportedRenderers;
         g_rendererPreferredByQt = preferredByQt;
@@ -143,6 +148,8 @@ void KisOpenGL::initialize()
         debugOut.resetFormat();
         debugOut << "\n     Supports deprecated functions" << openGLCheckResult->supportsDeprecatedFunctions();
         debugOut << "\n     is OpenGL ES:" << openGLCheckResult->isOpenGLES();
+        debugOut << "\n  supportsBufferMapping:" << openGLCheckResult->supportsBufferMapping();
+        debugOut << "\n  supportsBufferInvalidation:" << openGLCheckResult->supportsBufferInvalidation();
     }
 
     debugOut << "\n\nQPA OpenGL Detection Info";
@@ -154,6 +161,8 @@ void KisOpenGL::initialize()
     debugOut << "\n  supportsOpenGLES:" << bool(g_supportedRenderers & RendererOpenGLES);
     debugOut << "\n  isQtPreferOpenGLES:" << bool(g_rendererPreferredByQt == RendererOpenGLES);
 #endif
+
+
 //    debugOut << "\n== log ==\n";
 //    debugOut.noquote();
 //    debugOut << g_surfaceFormatDetectionLog;
@@ -175,6 +184,10 @@ void KisOpenGL::initialize()
 #endif
 
     KisConfig cfg(true);
+
+    g_useBufferInvalidation = cfg.readEntry("useBufferInvalidation", false);
+    KisUsageLogger::writeSysInfo(QString("\nuseBufferInvalidation (config option): %1\n").arg(g_useBufferInvalidation ? "true" : "false"));
+
     if ((isOnX11 && openGLCheckResult->rendererString().startsWith("AMD")) || cfg.forceOpenGLFenceWorkaround()) {
         g_needsFenceWorkaround = true;
     }
@@ -238,6 +251,11 @@ void KisOpenGL::initializeContext(QOpenGLContext *ctx)
     QOpenGLFunctions *f = ctx->functions();
     f->initializeOpenGLFunctions();
 
+    if (openGLCheckResult->supportsBufferInvalidation()) {
+        QOpenGLContext *ctx = QOpenGLContext::currentContext();
+        g_glInvalidateBufferData = (PFNGLINVALIDATEBUFFERDATAPROC)ctx->getProcAddress("glInvalidateBufferData");
+    }
+
     QFile log(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/krita-opengl.txt");
     log.open(QFile::WriteOnly);
     QString vendor((const char*)f->glGetString(GL_VENDOR));
@@ -304,6 +322,13 @@ bool KisOpenGL::supportsBufferMapping()
     return openGLCheckResult && openGLCheckResult->supportsBufferMapping();
 }
 
+bool KisOpenGL::useTextureBufferInvalidation()
+{
+    initialize();
+    return g_useBufferInvalidation &&
+        openGLCheckResult && openGLCheckResult->supportsBufferInvalidation();
+}
+
 bool KisOpenGL::useFBOForToolOutlineRendering()
 {
     initialize();
@@ -332,6 +357,11 @@ void KisOpenGL::setDebugSynchronous(bool value)
     g_isDebugSynchronous = value;
 }
 
+void KisOpenGL::glInvalidateBufferData(uint buffer)
+{
+    g_glInvalidateBufferData(buffer);
+}
+
 KisOpenGL::OpenGLRenderer KisOpenGL::getCurrentOpenGLRenderer()
 {
     if (!openGLCheckResult) return RendererAuto;
diff --git a/libs/ui/opengl/kis_opengl.h b/libs/ui/opengl/kis_opengl.h
index dfef7a1598..53e5682f09 100644
--- a/libs/ui/opengl/kis_opengl.h
+++ b/libs/ui/opengl/kis_opengl.h
@@ -99,6 +99,8 @@ public:
 
     static bool supportsBufferMapping();
 
+    static bool useTextureBufferInvalidation();
+
     /**
      * @brief supportsRenderToFBO
      * @return True if OpenGL can render to FBO, used
@@ -121,6 +123,8 @@ public:
     static void testingInitializeDefaultSurfaceFormat();
     static void setDebugSynchronous(bool value);
 
+    static void glInvalidateBufferData(uint buffer);
+
 private:
     static void fakeInitWindowsOpenGL(KisOpenGL::OpenGLRenderers supportedRenderers, KisOpenGL::OpenGLRenderer preferredByQt);
 



More information about the kimageshop mailing list