diff options
author | Sven Gothel <[email protected]> | 2013-06-17 04:39:58 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-06-17 04:39:58 +0200 |
commit | d7e2cb6fdec200d25a9189f7951c5f94c26a1ce4 (patch) | |
tree | 21032f1f85d365b5a205ea7296f8ff5f76b2166d /src/jogl | |
parent | c3dc7fbdb9437f773146926b41003df32ba756d1 (diff) |
Fix Bug 753: Stuttering caused by lack of GL resource synchronization between Java GL- and CALayer thread ; Simplify / Fix waitUntilRenderSignal().
Stuttering caused by lack of GL resource synchronization between Java GL- and CALayer thread
+ // Required(?) to finish previous GL rendering to give CALayer proper result,
+ // i.e. synchronize both threads each w/ their GLContext sharing same resources.
+ //
+ // FIXME: IMHO this synchronization should be implicitly performed via 'CGL.flushBuffer(contextHandle)' above,
+ // in case this will be determined a driver bug - use a QUIRK entry in GLRendererQuirks!
+ gl.glFinish();
Simplify / Fix waitUntilRenderSignal()
- remove loop and 'ready' condition -> nonsense
- if too later, i.e. lastWaitTime+TO < now, use now+TO as max. vsync waiting time
Bug735 Tests:
- Make vsync, wait and ECT (exclusive context thread) configurable via main args.
- Inv2*, Inv3* and Inv4*: Fluent Animation
- Works w/ ECT
Diffstat (limited to 'src/jogl')
-rw-r--r-- | src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java | 52 | ||||
-rw-r--r-- | src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m | 63 |
2 files changed, 82 insertions, 33 deletions
diff --git a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java index 976056891..6b086ce44 100644 --- a/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java +++ b/src/jogl/classes/jogamp/opengl/macosx/cgl/MacOSXCGLContext.java @@ -81,7 +81,7 @@ import com.jogamp.opengl.util.glsl.ShaderCode; import com.jogamp.opengl.util.glsl.ShaderProgram; public class MacOSXCGLContext extends GLContextImpl -{ +{ // Abstract interface for implementation of this context (either // NSOpenGL-based or CGL-based) protected interface GLBackendImpl { @@ -1000,6 +1000,8 @@ public class MacOSXCGLContext extends GLContextImpl CGL.setNSOpenGLLayerSwapInterval(l, interval); if( 0 < interval ) { vsyncTimeout = interval * screenVSyncTimeout + 1000; // +1ms + } else { + vsyncTimeout = 1 * screenVSyncTimeout + 1000; // +1ms } if(DEBUG) { System.err.println("NS setSwapInterval: "+interval+" -> "+vsyncTimeout+" micros"); } } @@ -1008,6 +1010,14 @@ public class MacOSXCGLContext extends GLContextImpl } private int skipSync=0; + /** TODO: Remove after discussion + private boolean perfIterReset = false; + private int perfIter = 0; + private long waitGLS = 0; + private long finishGLS = 0; + private long frameXS = 0; + private long lastFrameStart = 0; + */ @Override public boolean swapBuffers() { @@ -1036,6 +1046,45 @@ public class MacOSXCGLContext extends GLContextImpl res = CGL.flushBuffer(contextHandle); if(res) { if(0 == skipSync) { + /** TODO: Remove after discussion + perfIter++; + if( !perfIterReset && 100 == perfIter ) { + perfIterReset = true; + perfIter = 1; + waitGLS = 0; + finishGLS = 0; + frameXS = 0; + } + final long lastFramePeriod0 = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart; + gl.glFinish(); // Require to finish previous GL rendering to give CALayer proper result + final long lastFramePeriod1 = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart; + + // If v-sync is disabled, frames will be drawn as quickly as possible w/o delay, + // while still synchronizing w/ CALayer. + // If v-sync is enabled wait until next swap interval (v-sync). + CGL.waitUntilNSOpenGLLayerIsReady(cmd.nsOpenGLLayer, vsyncTimeout); + final long lastFramePeriodX = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()) - lastFrameStart; + + final long finishGL = lastFramePeriod1 - lastFramePeriod0; + final long waitGL = lastFramePeriodX - lastFramePeriod1; + finishGLS += finishGL; + waitGLS += waitGL; + frameXS += lastFramePeriodX; + + System.err.println("XXX["+perfIter+"] TO "+vsyncTimeout/1000+" ms, "+ + "lFrame0 "+lastFramePeriod0/1000+" ms, "+ + "lFrameX "+lastFramePeriodX/1000+" / "+frameXS/1000+" ~"+(frameXS/perfIter)/1000.0+" ms, "+ + "finishGL "+finishGL/1000+" / "+finishGLS/1000+" ~"+(finishGLS/perfIter)/1000.0+" ms, "+ + "waitGL "+waitGL/1000+" / "+waitGLS/1000+" ~"+(waitGLS/perfIter)/1000.0+" ms"); + */ + // + // Required(?) to finish previous GL rendering to give CALayer proper result, + // i.e. synchronize both threads each w/ their GLContext sharing same resources. + // + // FIXME: IMHO this synchronization should be implicitly performed via 'CGL.flushBuffer(contextHandle)' above, + // in case this will be determined a driver bug - use a QUIRK entry in GLRendererQuirks! + gl.glFinish(); + // If v-sync is disabled, frames will be drawn as quickly as possible w/o delay, // while still synchronizing w/ CALayer. // If v-sync is enabled wait until next swap interval (v-sync). @@ -1050,6 +1099,7 @@ public class MacOSXCGLContext extends GLContextImpl // trigger CALayer to update incl. possible surface change (new pbuffer handle) CGL.setNSOpenGLLayerNeedsDisplayPBuffer(cmd.nsOpenGLLayer, drawable.getHandle()); } + // lastFrameStart = TimeUnit.NANOSECONDS.toMicros(System.nanoTime()); } } else { res = true; diff --git a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m index 6738364a7..046171efc 100644 --- a/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m +++ b/src/jogl/native/macosx/MacOSXWindowSystemInterface-calayer.m @@ -818,40 +818,39 @@ static const GLfloat gl_verts[] = { - (void)waitUntilRenderSignal: (long) to_micros { - BOOL ready = NO; - int wr = 0; + struct timespec t0, to_until; + BOOL tooLate; + int wr; + if( 0 >= to_micros ) { + to_micros = 16666 + 1000; // defaults to 1/60s + 1ms + NSLog(@"MyNSOpenGLContext::waitUntilRenderSignal: to_micros was zero, using defaults"); + } pthread_mutex_lock(&renderLock); - SYNC_PRINT("{W %ld us", to_micros); - do { - if(0 >= swapInterval) { - ready = YES; - } - if(NO == ready) { - #ifdef DBG_SYNC - struct timespec t0, t1, td, td2; - timespec_now(&t0); - #endif - if( 0 >= to_micros ) { - to_micros = 16666 + 1000; // defaults to 1/60s + 1ms - NSLog(@"MyNSOpenGLContext::waitUntilRenderSignal: to_micros was zero, using defaults"); - } - struct timespec to_abs = lastWaitTime; - timespec_addmicros(&to_abs, to_micros); - #ifdef DBG_SYNC - timespec_subtract(&td, &to_abs, &t0); - fprintf(stderr, ", (%ld) / ", timespec_milliseconds(&td)); - #endif - wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_abs); - #ifdef DBG_SYNC - timespec_now(&t1); - timespec_subtract(&td, &t1, &t0); - timespec_subtract(&td2, &t1, &lastWaitTime); - fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2)); - #endif - ready = YES; + timespec_now(&t0); + to_until = lastWaitTime; + timespec_addmicros(&to_until, to_micros); + tooLate = timespec_compare(&to_until, &t0) < 0; + #ifdef DBG_SYNC + struct timespec td_until; + timespec_subtract(&td_until, &to_until, &t0); + SYNC_PRINT("{W %ld ms, to %ld ms, late %d", to_micros/1000, timespec_milliseconds(&td_until), tooLate); + #endif + if( 0 < swapInterval ) { + if( tooLate ) { + // adjust! + to_until = t0; + timespec_addmicros(&to_until, to_micros); } - } while (NO == ready && 0 == wr) ; - SYNC_PRINT("-%d-%d-%d}", shallDraw, wr, ready); + wr = pthread_cond_timedwait(&renderSignal, &renderLock, &to_until); + #ifdef DBG_SYNC + struct timespec t1, td, td2; + timespec_now(&t1); + timespec_subtract(&td, &t1, &t0); + timespec_subtract(&td2, &t1, &lastWaitTime); + fprintf(stderr, "(%ld) / (%ld) ms", timespec_milliseconds(&td), timespec_milliseconds(&td2)); + #endif + } + SYNC_PRINT("-%d-%d}\n", shallDraw, wr); timespec_now(&lastWaitTime); pthread_mutex_unlock(&renderLock); } |