Skip to content

Commit

Permalink
Adding NVIDIA 'Threaded optimization' workaround/fix at initializatio…
Browse files Browse the repository at this point in the history
…n on Windows for javaws/applets.

It has been observed that for some combinations, eg:
     - Windows 7 64bit (other variants may apply too)
     - NVIDIA 8600M GT
     - 260.99

the NVIDIA setting of 'Threaded optimization' := 'auto' (default) causes the JVM to simply crash
in case of javaws and [jnlp] applets.

'Threaded Optimization' := 'off' works reliable

'Threaded Optimization' := 'on'  never works with javaws and applets on the above configuration

A user could workaround this by setting 'Threaded Optimization' := 'off',
however, this would disable many users on the spot,
since you cannot ask the average user for such a task, if she only wants to see a web page.

This patch 'fixes' the 'auto' mode by running the eager GL profile initialization
within a block of single CPU affinity:

  SetProcessAffinityMask(pid, 1);
  try {
    initProfilesForDeviceImpl(device);
  } finally {
    SetProcessAffinityMask(pid, sysValue);
  }

Hopefully we can remove this hack with a driver fix.
However this workaround is as little invasive as possible.
  • Loading branch information
sgothel committed Dec 18, 2010
1 parent 5f67805 commit 5166d6a
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 1 deletion.
5 changes: 4 additions & 1 deletion make/stub_includes/win32/windows.h
Expand Up @@ -12,7 +12,7 @@
typedef int BOOL;
typedef unsigned char BYTE;
typedef char CHAR;
typedef unsigned int DWORD;
typedef unsigned __int32 DWORD;
typedef int INT;
typedef __int32 INT32;
typedef __int64 INT64;
Expand All @@ -29,12 +29,15 @@ typedef HANDLE HWND;
typedef __int32 LONG;
typedef const char* LPCSTR;
typedef void* LPVOID;
typedef unsigned __int64 ULONG_PTR;
typedef struct _proc* PROC;
typedef unsigned int* PUINT;
typedef unsigned int UINT;
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned short ATOM;
typedef intptr_t DWORD_PTR;
typedef intptr_t* PDWORD_PTR;

/* Necessary handle typedefs for parsing wglext.h */

Expand Down
5 changes: 5 additions & 0 deletions make/stub_includes/win32/wingdi.h
Expand Up @@ -194,6 +194,11 @@ WINUSERAPI int WINAPI ReleaseDC(HWND hWnd, HDC hDC);
WINUSERAPI BOOL WINAPI DestroyWindow(HWND hWnd);
WINUSERAPI DWORD WINAPI GetObjectType(HGDIOBJ h);

WINUSERAPI HANDLE WINAPI GetCurrentProcess(void);
WINUSERAPI BOOL WINAPI GetProcessAffinityMask(HANDLE hProcess,PDWORD_PTR lpProcessAffinityMask,PDWORD_PTR lpSystemAffinityMask);
WINUSERAPI BOOL WINAPI SetProcessAffinityMask(HANDLE hProcess,DWORD_PTR dwProcessAffinityMask);


// Routines for changing gamma ramp of display device
WINGDIAPI BOOL WINAPI GetDeviceGammaRamp(HDC,LPVOID);
WINGDIAPI BOOL WINAPI SetDeviceGammaRamp(HDC,LPVOID);
Expand Down
Expand Up @@ -60,6 +60,7 @@
import javax.media.opengl.GLProfile;

import com.jogamp.common.JogampRuntimeException;
import com.jogamp.common.nio.PointerBuffer;
import com.jogamp.common.util.ReflectionUtil;
import com.jogamp.nativewindow.impl.ProxySurface;
import com.jogamp.nativewindow.impl.windows.GDI;
Expand Down Expand Up @@ -125,6 +126,42 @@ public WindowsWGLDrawableFactory() {
Thread sharedResourceThread;
HashMap/*<connection, SharedResource>*/ sharedMap = new HashMap();

long processAffinityChanges = 0;
PointerBuffer procMask = PointerBuffer.allocateDirect(1);
PointerBuffer sysMask = PointerBuffer.allocateDirect(1);

protected void enterThreadCriticalZone() {
synchronized (sysMask) {
if( 0 == processAffinityChanges) {
long pid = GDI.GetCurrentProcess();
if ( GDI.GetProcessAffinityMask(pid, procMask, sysMask) ) {
if(DEBUG) {
System.err.println("WindowsWGLDrawableFactory.enterThreadCriticalZone() - 0x" + Long.toHexString(pid) + " - " + Thread.currentThread().getName());
Thread.dumpStack();
}
processAffinityChanges = pid;
GDI.SetProcessAffinityMask(pid, 1);
}
}
}
}

protected void leaveThreadCriticalZone() {
synchronized (sysMask) {
if( 0 != processAffinityChanges) {
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) + " - " + Thread.currentThread().getName());
}
GDI.SetProcessAffinityMask(pid, sysMask.get(0));
}
}
}

static class SharedResource implements SharedResourceRunner.Resource {
private WindowsGraphicsDevice device;
private AbstractGraphicsScreen screen;
Expand Down
3 changes: 3 additions & 0 deletions src/jogl/classes/javax/media/opengl/GLDrawableFactory.java
Expand Up @@ -220,6 +220,9 @@ protected GLDrawableFactory() {
}
}

protected void enterThreadCriticalZone() {};
protected void leaveThreadCriticalZone() {};

protected abstract void shutdownInstance();

/**
Expand Down
9 changes: 9 additions & 0 deletions src/jogl/classes/javax/media/opengl/GLProfile.java
Expand Up @@ -1218,6 +1218,15 @@ private static synchronized boolean initProfilesForDevice(AbstractGraphicsDevice
if(null == device) {
return false;
}
GLDrawableFactory factory = GLDrawableFactory.getFactoryImpl(device);
factory.enterThreadCriticalZone();
try {
return initProfilesForDeviceImpl(device);
} finally {
factory.leaveThreadCriticalZone();
}
}
private static synchronized boolean initProfilesForDeviceImpl(AbstractGraphicsDevice device) {
boolean isSet = GLContext.getAvailableGLVersionsSet(device);

if(DEBUG) {
Expand Down

0 comments on commit 5166d6a

Please sign in to comment.