aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/opengl/windows
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-07-27 04:00:26 +0200
committerSven Gothel <[email protected]>2014-07-27 04:00:26 +0200
commit007f120cd8d33e4231ef4d207b85ed156d1e0c82 (patch)
treed04584098e9ded5144030054ec5f978d5998abd4 /src/jogl/classes/jogamp/opengl/windows
parentc77b8f586cb2553582a42f5b90aeee5ef85f1efe (diff)
Fixed and Changed NVidia Windows Driver Threaded optimization bug workaround of commit 5166d6a6b617ccb15c40fcb8d4eac2800527aa7b
Commit 5166d6a6b617ccb15c40fcb8d4eac2800527aa7b added a workaround for the NVidia driver 260.99 for Window from 2010-12-11 issue. [1] The workaround sets a process affinity while JOGL initialization to mitigate NVidia driver's 'Threaded optimization := On' race conditions. The process affinity is reset reset after initialization. [2] The process affinity reset code had a bug, i.e. instead to restore the original process's affinity mask, we restored the system's default affinity mask. [3] Further more, there seem to be issues with changing a process affinity mask regarding the process group. This patch: - Solves issue [2] by using the original process affinity mask - Solves issue [3] by allowing a custom affinity mode via the property 'jogl.debug.windows.cpu_affinity_mode': - 0 - none (default, no affinity required for Windows NV driver >= 266.58 from 2011-01-24) - 1 - process affinity (was required w/ Windows NV driver 260.99 from 2010-12-11, see commit 5166d6a6b617ccb15c40fcb8d4eac2800527aa7b) - 2 - thread affinity (experimental) Hence the workaround is disabled by default, since the crash as dicumented in commit 5166d6a6b617ccb15c40fcb8d4eac2800527aa7b could not be reproduced with NV driver 266.58 from 2011-01-24.
Diffstat (limited to 'src/jogl/classes/jogamp/opengl/windows')
-rw-r--r--src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java197
1 files changed, 169 insertions, 28 deletions
diff --git a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
index 4d8c85137..42e802a95 100644
--- a/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
+++ b/src/jogl/classes/jogamp/opengl/windows/wgl/WindowsWGLDrawableFactory.java
@@ -68,6 +68,7 @@ import jogamp.nativewindow.windows.GDI;
import jogamp.nativewindow.windows.GDIDummyUpstreamSurfaceHook;
import jogamp.nativewindow.windows.GDISurface;
import jogamp.nativewindow.windows.RegisteredClassFactory;
+import jogamp.opengl.Debug;
import jogamp.opengl.DesktopGLDynamicLookupHelper;
import jogamp.opengl.GLContextImpl;
import jogamp.opengl.GLDrawableFactoryImpl;
@@ -83,11 +84,35 @@ import com.jogamp.opengl.GLExtensions;
import com.jogamp.opengl.GLRendererQuirks;
public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
+ /**
+ * Property integer value <code>jogl.debug.windows.cpu_affinity_mode</code>:
+ * <ul>
+ * <li>0 - none (default, no affinity required for Windows NV driver >= 266.58 from 2011-01-24)</li>
+ * <li>1 - process affinity (was required w/ Windows NV driver 260.99 from 2010-12-11, see commit 5166d6a6b617ccb15c40fcb8d4eac2800527aa7b)</li>
+ * <li>2 - thread affinity (experimental)</li>
+ * </ul>
+ */
+ private static final int CPU_AFFINITY_MODE = Debug.getIntProperty("jogl.debug.windows.cpu_affinity_mode", true, 0);
+
private static DesktopGLDynamicLookupHelper windowsWGLDynamicLookupHelper = null;
+ private final CPUAffinity cpuAffinity;
+
public WindowsWGLDrawableFactory() {
super();
+ switch( CPU_AFFINITY_MODE ) {
+ case 1:
+ cpuAffinity = new WindowsProcessAffinity();
+ break;
+ case 2:
+ cpuAffinity = new WindowsThreadAffinity();
+ break;
+ default:
+ cpuAffinity = new NopCPUAffinity();
+ break;
+ }
+
synchronized(WindowsWGLDrawableFactory.class) {
if( null == windowsWGLDynamicLookupHelper ) {
windowsWGLDynamicLookupHelper = AccessController.doPrivileged(new PrivilegedAction<DesktopGLDynamicLookupHelper>() {
@@ -168,45 +193,23 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
return windowsWGLDynamicLookupHelper;
}
+ /* pp */ static String toHexString(final long l) { return "0x"+Long.toHexString(l); }
+
private WindowsGraphicsDevice defaultDevice;
private SharedResourceRunner sharedResourceRunner;
private HashMap<String /*connection*/, SharedResourceRunner.Resource> sharedMap;
- private long processAffinityChanges = 0;
- private final PointerBuffer procMask = PointerBuffer.allocateDirect(1);
- private final PointerBuffer sysMask = PointerBuffer.allocateDirect(1);
-
@Override
protected void enterThreadCriticalZone() {
- synchronized (sysMask) {
- if( 0 == processAffinityChanges) {
- final long pid = GDI.GetCurrentProcess();
- if ( GDI.GetProcessAffinityMask(pid, procMask, sysMask) ) {
- if(DEBUG) {
- System.err.println("WindowsWGLDrawableFactory.enterThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + getThreadName());
- // Thread.dumpStack();
- }
- processAffinityChanges = pid;
- GDI.SetProcessAffinityMask(pid, 1);
- }
- }
+ synchronized (cpuAffinity) {
+ cpuAffinity.set(1);
}
}
@Override
protected void leaveThreadCriticalZone() {
- synchronized (sysMask) {
- if( 0 != processAffinityChanges) {
- final long pid = GDI.GetCurrentProcess();
- if( pid != processAffinityChanges) {
- throw new GLException("PID doesn't match: set PID 0x" + Long.toHexString(processAffinityChanges) +
- " this PID 0x" + Long.toHexString(pid) );
- }
- if(DEBUG) {
- System.err.println("WindowsWGLDrawableFactory.leaveThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + getThreadName());
- }
- GDI.SetProcessAffinityMask(pid, sysMask.get(0));
- }
+ synchronized (cpuAffinity) {
+ cpuAffinity.reset();
}
}
@@ -598,4 +601,142 @@ public class WindowsWGLDrawableFactory extends GLDrawableFactoryImpl {
GDI.SetDeviceGammaRamp(screenDC, originalGammaRamp);
GDI.ReleaseDC(0, screenDC);
}
+
+ static interface CPUAffinity {
+ boolean set(final int newAffinity);
+ boolean reset();
+ }
+ static final class WindowsThreadAffinity implements CPUAffinity {
+ private long threadHandle;
+ private long threadOrigAffinity;
+ private long threadNewAffinity;
+ public WindowsThreadAffinity() {
+ threadHandle = 0;
+ threadOrigAffinity = 0;
+ threadNewAffinity = 0;
+ }
+ @Override
+ public boolean set(final int newAffinity) {
+ final long tid = GDI.GetCurrentThread();
+ if( 0 != threadHandle ) {
+ throw new IllegalStateException("Affinity already set");
+ }
+ final long threadLastAffinity = GDI.SetThreadAffinityMask(tid, newAffinity);
+ final int werr = GDI.GetLastError();
+ final boolean res;
+ if( 0 != threadLastAffinity ) {
+ res = true;
+ this.threadHandle = tid;
+ this.threadNewAffinity = newAffinity;
+ this.threadOrigAffinity = threadLastAffinity;
+ } else {
+ res = false;
+ }
+ if(DEBUG) {
+ System.err.println("WindowsThreadAffinity.set() - tid " + toHexString(tid) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+werr+"), Affinity: "+toHexString(threadOrigAffinity) + " -> " + toHexString(newAffinity));
+ }
+ return res;
+ }
+ @Override
+ public boolean reset() {
+ if( 0 == threadHandle ) {
+ return true;
+ }
+ final long tid = GDI.GetCurrentThread();
+ if( tid != threadHandle) {
+ throw new IllegalStateException("TID doesn't match: set TID " + toHexString(threadHandle) +
+ " this TID " + toHexString(tid) );
+ }
+ final long preThreadAffinity = GDI.SetThreadAffinityMask(threadHandle, threadOrigAffinity);
+ final boolean res = 0 != preThreadAffinity;
+ if(DEBUG) {
+ System.err.println("WindowsThreadAffinity.reset() - tid " + toHexString(threadHandle) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+GDI.GetLastError()+"), Affinity: "+toHexString(threadNewAffinity)+" -> orig "+ toHexString(threadOrigAffinity));
+ }
+ this.threadHandle = 0;
+ this.threadNewAffinity = this.threadOrigAffinity;
+ return res;
+ }
+ }
+ static final class WindowsProcessAffinity implements CPUAffinity {
+ private long processHandle;
+ private long newAffinity;
+ private final PointerBuffer procMask;
+ private final PointerBuffer sysMask;
+
+ public WindowsProcessAffinity() {
+ processHandle = 0;
+ newAffinity = 0;
+ procMask = PointerBuffer.allocateDirect(1);
+ sysMask = PointerBuffer.allocateDirect(1);
+ }
+ @Override
+ public boolean set(final int newAffinity) {
+ if( 0 != processHandle ) {
+ throw new IllegalStateException("Affinity already set");
+ }
+ final long pid = GDI.GetCurrentProcess();
+ final boolean res;
+ if ( GDI.GetProcessAffinityMask(pid, procMask, sysMask) ) {
+ if( GDI.SetProcessAffinityMask(pid, newAffinity) ) {
+ this.processHandle = pid;
+ this.newAffinity = newAffinity;
+ res = true;
+ } else {
+ res = false;
+ }
+ if(DEBUG) {
+ System.err.println("WindowsProcessAffinity.set() - pid " + toHexString(pid) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+GDI.GetLastError()+"), Affinity: procMask "+ toHexString(procMask.get(0)) + ", sysMask "+ toHexString(sysMask.get(0)) +
+ " -> "+toHexString(newAffinity));
+ }
+ } else {
+ if(DEBUG) {
+ System.err.println("WindowsProcessAffinity.set() - pid " + toHexString(pid) + " - " + getThreadName() +
+ ": Error, could not GetProcessAffinityMask, werr "+GDI.GetLastError());
+ }
+ res = false;
+ }
+ return res;
+ }
+ @Override
+ public boolean reset() {
+ if( 0 == processHandle ) {
+ return true;
+ }
+ final long pid = GDI.GetCurrentProcess();
+ if( pid != processHandle) {
+ throw new IllegalStateException("PID doesn't match: set PID " + toHexString(processHandle) +
+ " this PID " + toHexString(pid) );
+ }
+ final long origProcAffinity = procMask.get(0);
+ final boolean res = GDI.SetProcessAffinityMask(processHandle, origProcAffinity);
+ if(DEBUG) {
+ final int werr = GDI.GetLastError();
+ System.err.println("WindowsProcessAffinity.reset() - pid " + toHexString(processHandle) + " - " + getThreadName() +
+ ": OK "+res+" (werr "+werr+"), Affinity: "+toHexString(newAffinity)+" -> procMask "+ toHexString(origProcAffinity));
+ }
+ this.processHandle = 0;
+ this.newAffinity = origProcAffinity;
+ return res;
+ }
+ }
+ static final class NopCPUAffinity implements CPUAffinity {
+ public NopCPUAffinity() { }
+ @Override
+ public boolean set(final int newAffinity) {
+ if(DEBUG) {
+ System.err.println("NopCPUAffinity.set() - " + getThreadName());
+ }
+ return false;
+ }
+ @Override
+ public boolean reset() {
+ if(DEBUG) {
+ System.err.println("NopCPUAffinity.reset() - " + getThreadName());
+ }
+ return false;
+ }
+ }
}