primus icon indicating copy to clipboard operation
primus copied to clipboard

Front buffer updates/single-buffered rendering not supported

Open karolherbst opened this issue 12 years ago • 5 comments

here is the source: http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi/0650/bks/SGI_Developer/books/OpenGLonSGI/sgi_html/ch03.html#LE40932-PARENT

it works with optirun and on intel.

karolherbst avatar Sep 04 '12 17:09 karolherbst

That is because it is single-buffered. This is fixable, but not high priority - any application that needs GL offloading will be double-buffered.

amonakov avatar Sep 04 '12 20:09 amonakov

Am I right, that the issue is, that the nvidia side in primus is double buffered, but the application only uses as it would be single buffer so that it doesn't call glxSwapBuffers and the screen isn't actually painted at any time?

karolherbst avatar Dec 30 '14 09:12 karolherbst

That nvidia-side pbuffer in primus is double-buffered is not important, and simply is a consequence of caring about double-buffered applications only.

The important thing is, like you say in the second half of your question, is that application wouldn't call a function like glXSwapBuffers to signal that it's "done" with a scene it was rendering into the front buffer. Historically, applications used glFlush and/or glFinish for that purpose, but these functions can also be used for other purposes (e.g. in Wine, for enforcing draw ordering).

amonakov avatar Dec 30 '14 10:12 amonakov

yeah, I wasn't thinking it through :/ I was thinking about such a solution: remember what kind of buffer was requested or into which buffer stuff is drawn, then trigger an internal glxSwapBuffers on glFlush and glFinish calls, where the overheads should be reall small, because not much applications will call that.

Could something like that destroy any behaviour in single buffered applications?

hacky approach to implement it (at least the demo source from the link above works with it):

From d5b2a546934c99df2d5f11738ff07508dc98904a Mon Sep 17 00:00:00 2001
From: Karol Herbst <[email protected]>
Date: Tue, 30 Dec 2014 22:17:17 +0200
Subject: [PATCH] single buffer hack try

---
 gl-passthru.def |  2 --
 gl-reimpl.def   |  2 ++
 libglfork.cpp   | 20 ++++++++++++++++++++
 3 files changed, 22 insertions(+), 2 deletions(-)
 create mode 100644 gl-reimpl.def

diff --git a/gl-passthru.def b/gl-passthru.def
index 8dcddae..91f0720 100644
--- a/gl-passthru.def
+++ b/gl-passthru.def
@@ -39,8 +39,6 @@ DEF_GLX_PROTO(void, glPopClientAttrib,(void))
 DEF_GLX_PROTO(GLint, glRenderMode,(GLenum mode), mode)
 DEF_GLX_PROTO(GLenum, glGetError,(void))
 DEF_GLX_PROTO(const GLubyte *, glGetString,(GLenum name), name)
-DEF_GLX_PROTO(void, glFinish,(void))
-DEF_GLX_PROTO(void, glFlush,(void))
 DEF_GLX_PROTO(void, glHint,(GLenum target, GLenum mode), target, mode)
 DEF_GLX_PROTO(void, glClearDepth,(GLclampd depth), depth)
 DEF_GLX_PROTO(void, glDepthFunc,(GLenum func), func)
diff --git a/gl-reimpl.def b/gl-reimpl.def
new file mode 100644
index 0000000..a68e255
--- /dev/null
+++ b/gl-reimpl.def
@@ -0,0 +1,2 @@
+DEF_GLX_PROTO(void, glFinish,(void))
+DEF_GLX_PROTO(void, glFlush,(void))
diff --git a/libglfork.cpp b/libglfork.cpp
index debc159..85d7de3 100644
--- a/libglfork.cpp
+++ b/libglfork.cpp
@@ -60,6 +60,7 @@ struct CapturedFns {
 #include "glxext-reimpl.def"
 #include "gl-passthru.def"
 #include "gl-needed.def"
+#include "gl-reimpl.def"
 #undef DEF_GLX_PROTO
   CapturedFns(const char *lib)
   {
@@ -71,6 +72,7 @@ struct CapturedFns {
 #define DEF_GLX_PROTO(ret, name, args, ...) name = (ret (*) args)this->glXGetProcAddress((GLubyte*)#name);
 #include "glxext-reimpl.def"
 #include "gl-passthru.def"
+#include "gl-reimpl.def"
 #include "gl-needed.def"
 #undef DEF_GLX_PROTO
   }
@@ -933,6 +935,24 @@ static void *i##name(void) \
 #include "gl-passthru.def"
 #undef DEF_GLX_PROTO

+void glFinish()
+{
+  primus.afns.glFinish();
+//TODO: if (primus.dfns.singleBuffered) {
+  glXSwapBuffers(tsdata.dpy, tsdata.drawable);
+  primus.dfns.glFinish();
+//TODO: }
+}
+
+void glFlush()
+{
+  primus.afns.glFlush();
+//TODO: if (primus.dfns.singleBuffered) {
+  glXSwapBuffers(tsdata.dpy, tsdata.drawable);
+  primus.dfns.glFlush();
+//TODO: }
+}
+
 // GLX extensions

 int glXSwapIntervalSGI(int interval)
-- 
2.2.1

karolherbst avatar Dec 30 '14 21:12 karolherbst

I'm afraid attempts to do it fully automatically will run into devils-in-the-details pretty easily. Consider:

  1. Application requests a double-buffered window
  2. Does some drawing in the back buffer
  3. Switches to front buffer
  4. Draws a bit into the front buffer
  5. Switches to back buffer
  6. Calls glFinish

If you examine GL state at step 6 only, it doesn't look like as if front buffer is being modified, and you can't distinguish between this application and Wine using glFinish for draw ordering. To get this right, you'd need to do some tracking at steps 3-5 to notice that you now need to synchronize the front buffer.

So perhaps a way to go is to have an environment variable to signal that all calls to glFlush/glFinish must synchronize the front buffer (destroying performance in "normal" double-buffered Wine games). Or, if automatic solution is desired, do it in a separate library that sits between the application and primus.

amonakov avatar Dec 31 '14 07:12 amonakov