X64 Windows and JUCE


#1

Not a request - more of a musing.

We’re getting more and more questions from customers about x64 Windows support for our hardware.

In addition, I was at the Microsoft Windows Vista audio conference recently and they made it fairly clear that 64 bit is a priority for Vista.

I, personally, don’t need x64 JUCE right now. You can run 32 bit apps on 64 bit Windows just fine. However, I’m sure I will need it at some point.

I would also bet that Tracktion will want to ship a 64 bit version.

Finally, anyone writing audio plugins using JUCE will need 64 bit support. 64 bit apps can’t host 32 bit plugins.

So it’s nothing urgent - just something that’s been on my mind lately. I don’t think the port would be especially difficult - the main problem would be all the in-line assembly.

I’m sure Jules has his own prioirities and it will happen in its own time. : )


#2

I think it would probably already work… Anybody got a 64 bit OS to try it with?


#3

Hey, I was at the Vista Audio Summit as well.

In the porting lab I was working on getting JUCE going on Vista 64. While I did get it to compile, I never did get it to run, and then I ran out out of time.

I was having some issues in the CriticalSection code because the size of some structs changed, and JUCE expected them to be a bertain size.


#4

You can certainly build a 32 bit app with JUCE and have it run on x64 in WOW64 mode - that’s no problem.

http://en.wikipedia.org/wiki/WoW64

However, building 64 bit native JUCE results in many, many compiler errors- primarily because the AMD64 compiler doesn’t support inline assembly.

Matt


#5

[quote=“G-Mon”]Hey, I was at the Vista Audio Summit as well.

[/quote]

Neat; maybe I saw you there. I’m Matt Gonzalez from Echo Digital Audio.

Matt


#6

[quote=“matt”][quote=“G-Mon”]Hey, I was at the Vista Audio Summit as well.

[/quote]

Neat; maybe I saw you there. I’m Matt Gonzalez from Echo Digital Audio.

Matt[/quote]

Roland Rabien from Mackie/LOUD Technologies.


#7

Oh, OK. I saw Dan Moore from Mackie there, but I don’t think you and I met.

Small world - we’ve been doing a lot of work with Mackie.

Matt


#8

The following patch against the latest published code (1.37) addresses a few issues with Win64. I’ve done this before even coding a single JUCE app so you’ve been warned. That said, the demo works fine (incl. OpenGL). The only thing missing is SSE support and the cpuid stuff–both easily done with intrinsics. Some inline assembly was redone with intrinsics to be portable across Win32/Win64. If you’re not familiar with DWORD_PTR or ULONG_PTR, don’t gag–they are in fact not pointers and so changing the type does not change the code using that type; leave it to MS.

patch for platform_specific_code:

diff -u -r platform_specific_code\juce_win32_FileChooser.cpp /juce/build/win32/platform_specific_code\juce_win32_FileChooser.cpp
--- platform_specific_code\juce_win32_FileChooser.cpp	Sun Aug 20 20:04:19 2006
+++ /juce/build/win32/platform_specific_code\juce_win32_FileChooser.cpp	Tue Aug 08 17:01:00 2006
@@ -114,7 +114,7 @@
 
 void juce_setWindowStyleBit (HWND h, int styleType, int feature, bool bitIsSet);
 
-static UINT_PTR CALLBACK openCallback (HWND hdlg, UINT uiMsg, WPARAM /*wParam*/, LPARAM lParam)
+static unsigned int CALLBACK openCallback (HWND hdlg, UINT uiMsg, WPARAM /*wParam*/, LPARAM lParam)
 {
     if (currentExtraFileWin != 0)
     {
diff -u -r platform_specific_code\juce_win32_Messaging.cpp /juce/build/win32/platform_specific_code\juce_win32_Messaging.cpp
--- platform_specific_code\juce_win32_Messaging.cpp	Sun Aug 20 23:00:29 2006
+++ /juce/build/win32/platform_specific_code\juce_win32_Messaging.cpp	Tue Aug 08 17:01:00 2006
@@ -121,7 +121,7 @@
         }
         else
         {
-            if (GetWindowLong (m.hwnd, GWLP_USERDATA) != improbableWindowNumber)
+            if (GetWindowLong (m.hwnd, GWL_USERDATA) != improbableWindowNumber)
             {
                 // if it's someone else's window being clicked on, give it the kb focus
                 if (m.message == WM_LBUTTONDOWN || m.message == WM_RBUTTONDOWN)
@@ -196,8 +196,7 @@
 
         if (String (windowName) == String (messageWindowName))
         {
-			DWORD_PTR result;
-
+            DWORD result;
             SendMessageTimeout (hwnd, WM_COPYDATA,
                                 (WPARAM) juce_messageWindowHandle,
                                 (LPARAM) &data,
diff -u -r platform_specific_code\juce_win32_SystemStats.cpp /juce/build/win32/platform_specific_code\juce_win32_SystemStats.cpp
--- platform_specific_code\juce_win32_SystemStats.cpp	Sun Aug 20 22:11:00 2006
+++ /juce/build/win32/platform_specific_code\juce_win32_SystemStats.cpp	Tue Aug 08 17:01:00 2006
@@ -112,7 +112,6 @@
 #ifdef __GNUC__
         __asm__ ("cpuid" : "=a" (family), "=b" (ext), "=c" (dummy),"=d" (cpu) : "a" (1));
 #else
-#ifndef JUCE_64BIT
         __asm
         {
             mov eax, 1
@@ -121,7 +120,6 @@
             mov family, eax
             mov ext, ebx
         }
-#endif
 
 #endif
     }
@@ -163,7 +161,6 @@
                [vendor3] "m" (vendor[2])
              : "cc", "eax", "ebx", "ecx", "edx", "memory");
 #else
-#ifndef JUCE_64BIT
         __asm
         {
             mov eax, 0
@@ -173,7 +170,6 @@
             mov [vendor + 8], ecx
         }
 #endif
-#endif
     }
 #ifndef __MINGW32__
     __except (EXCEPTION_EXECUTE_HANDLER)
@@ -205,8 +201,8 @@
     logicalCpuInfo.numPackages = 0;
     logicalCpuInfo.physicalAffinityMask = 0;
 
-    DWORD_PTR processAffinity;
-    DWORD_PTR systemAffinity;
+    unsigned long processAffinity;
+    unsigned long systemAffinity;
 
     if (! GetProcessAffinityMask (hCurrentProcessHandle, &processAffinity, &systemAffinity))
         return;
@@ -217,7 +213,7 @@
         || (featuresWord & (1 << 28)) == 0
         || ((extFeaturesWord >> 16) & 0xff) < 2)
     {
-        logicalCpuInfo.physicalAffinityMask = static_cast<unsigned long> (processAffinity);
+        logicalCpuInfo.physicalAffinityMask = processAffinity;
         return;
     }
 
@@ -447,7 +443,6 @@
            [lo] "m" (lo)
          : "cc", "eax", "ebx", "ecx", "edx", "memory");
 #else
-#ifndef JUCE_64BIT
     __asm
     {
         xor eax, eax
@@ -456,7 +451,6 @@
         mov lo, eax
         mov hi, edx
     }
-#endif
 #endif
 
     return (int64) ((((uint64) hi) << 32) | lo);
diff -u -r platform_specific_code\juce_win32_Threads.cpp /juce/build/win32/platform_specific_code\juce_win32_Threads.cpp
--- platform_specific_code\juce_win32_Threads.cpp	Sun Aug 20 22:11:23 2006
+++ /juce/build/win32/platform_specific_code\juce_win32_Threads.cpp	Tue Aug 08 17:01:00 2006
@@ -61,7 +61,7 @@
 CriticalSection::CriticalSection() throw()
 {
     // (just to check the MS haven't changed this structure and broken things...)
-    static_jassert (sizeof (CRITICAL_SECTION) <= sizeof (internal));
+    static_jassert (sizeof (CRITICAL_SECTION) <= 24);
 
     InitializeCriticalSection ((CRITICAL_SECTION*) internal);
 }
@@ -167,7 +167,7 @@
 
     __try
     {
-        RaiseException (MS_VC_EXCEPTION, 0, sizeof (info) / sizeof (ULONG_PTR), (ULONG_PTR*) &info);
+        RaiseException (MS_VC_EXCEPTION, 0, sizeof (info) / sizeof (DWORD), (DWORD*) &info);
     }
     __except (EXCEPTION_CONTINUE_EXECUTION)
     {}
diff -u -r platform_specific_code\juce_win32_Windowing.cpp /juce/build/win32/platform_specific_code\juce_win32_Windowing.cpp
--- platform_specific_code\juce_win32_Windowing.cpp	Sun Aug 20 23:01:35 2006
+++ /juce/build/win32/platform_specific_code\juce_win32_Windowing.cpp	Tue Aug 08 17:01:00 2006
@@ -3508,8 +3508,8 @@
 
                     if (controlHWND != 0)
                     {
-                        originalWndProc = (void*) GetWindowLongPtr (controlHWND, GWLP_WNDPROC);
-                        SetWindowLongPtr (controlHWND, GWLP_WNDPROC, (LONG_PTR) activeXHookWndProc);
+                        originalWndProc = (void*) GetWindowLongPtr (controlHWND, GWL_WNDPROC);
+                        SetWindowLongPtr (controlHWND, GWL_WNDPROC, (LONG_PTR) activeXHookWndProc);
                     }
 
                     return true;

patch for (portable) src:

diff -u -r src\juce_appframework\gui\graphics\contexts\juce_LowLevelGraphicsSoftwareRenderer.cpp /juce/src\juce_appframework\gui\graphics\contexts\juce_LowLevelGraphicsSoftwareRenderer.cpp
--- src\juce_appframework\gui\graphics\contexts\juce_LowLevelGraphicsSoftwareRenderer.cpp	Sun Aug 20 21:57:21 2006
+++ /juce/src\juce_appframework\gui\graphics\contexts\juce_LowLevelGraphicsSoftwareRenderer.cpp	Tue Aug 08 17:01:00 2006
@@ -42,9 +42,7 @@
 #include "../../../../juce_core/basics/juce_SystemStats.h"
 
 #ifndef JUCE_MAC
-  #if !defined (JUCE_WIN32) || !defined (JUCE_64BIT)
-    #define JUCE_USE_SSE_INSTRUCTIONS 1
-  #endif
+ #define JUCE_USE_SSE_INSTRUCTIONS 1
 #endif
 
 //==============================================================================
diff -u -r src\juce_core\basics\juce_Atomic.h /juce/src\juce_core\basics\juce_Atomic.h
--- src\juce_core\basics\juce_Atomic.h	Sun Aug 20 22:17:09 2006
+++ /juce/src\juce_core\basics\juce_Atomic.h	Tue Aug 08 17:01:00 2006
@@ -35,11 +35,6 @@
 //==============================================================================
 // Atomic increment/decrement operations..
 
-#ifdef JUCE_WIN32
-  #include <intrin.h>
-  #pragma intrinsic (_InterlockedIncrement)
-  #pragma intrinsic (_InterlockedDecrement)
-#endif
 
 //==============================================================================
 #if JUCE_MAC && ! DOXYGEN
@@ -111,22 +106,15 @@
     /** Increments an integer in a thread-safe way. */
     inline_assembly void __fastcall atomicIncrement (int& variable) throw()
     {
-  #ifdef JUCE_WIN32
-		_InterlockedIncrement ( reinterpret_cast<volatile long *> (&variable) );
-  #else    
-		__asm {
+        __asm {
             mov ecx, dword ptr [variable]
             lock inc dword ptr [ecx]
-        }	
-  #endif
+        }
     }
 
     /** Increments an integer in a thread-safe way and returns the incremented value. */
     inline_assembly int __fastcall atomicIncrementAndReturn (int& variable) throw()
     {
-  #ifdef JUCE_WIN32
-		return _InterlockedIncrement ( reinterpret_cast<volatile long *> (&variable) );
-  #else
         int result;
 
         __asm {
@@ -138,28 +126,20 @@
         }
 
         return result;
-  #endif
     }
 
     /** Decrememts an integer in a thread-safe way. */
     inline_assembly void __fastcall atomicDecrement (int& variable) throw()
     {
-  #ifdef JUCE_WIN32
-		_InterlockedDecrement ( reinterpret_cast<volatile long *> (&variable) );
-  #else
         __asm {
             mov ecx, dword ptr [variable]
             lock dec dword ptr [ecx]
         }
-  #endif
     }
 
     /** Decrememts an integer in a thread-safe way and returns the incremented value. */
     inline_assembly int __fastcall atomicDecrementAndReturn (int& variable) throw()
     {
-  #ifdef JUCE_WIN32
-		return _InterlockedDecrement ( reinterpret_cast<volatile long *> (&variable) );
-  #else
         int result;
 
         __asm {
@@ -171,7 +151,6 @@
         }
 
         return result;
-  #endif
     }
 
 #endif
diff -u -r src\juce_core\basics\juce_DataConversions.h /juce/src\juce_core\basics\juce_DataConversions.h
--- src\juce_core\basics\juce_DataConversions.h	Sun Aug 20 22:22:38 2006
+++ /juce/src\juce_core\basics\juce_DataConversions.h	Tue Aug 08 17:01:00 2006
@@ -37,11 +37,6 @@
 //==============================================================================
 // Endianness conversions..
 
-#ifdef JUCE_WIN32
-  #include <intrin.h>
-  #pragma intrinsic (_byteswap_ulong)
-#endif
-
 /** Swaps the byte-order in an integer from little to big-endianness or vice-versa. */
 inline_assembly uint32 swapByteOrder (uint32 n) throw()
 {
@@ -54,15 +49,11 @@
     return n;
   #else
     // Win32 version..
-    #ifdef JUCE_WIN32
-	n = _byteswap_ulong (n);
-    #else
     __asm {
         mov eax, n
         bswap eax
         mov n, eax
-    }	
-    #endif
+    }
     return n;
   #endif
 #endif
diff -u -r src\juce_core\basics\juce_PlatformDefs.h /juce/src\juce_core\basics\juce_PlatformDefs.h
--- src\juce_core\basics\juce_PlatformDefs.h	Sun Aug 20 23:17:27 2006
+++ /juce/src\juce_core\basics\juce_PlatformDefs.h	Tue Aug 08 17:01:00 2006
@@ -139,12 +139,6 @@
 //==============================================================================
 // Debugging and assertion macros
 
-//==============================================================================
-#ifdef JUCE_WIN32
-	#include <intrin.h>
-	#pragma intrinsic (__debugbreak)
-#endif
-
 #ifdef JUCE_DEBUG
   //==============================================================================
   // If debugging is enabled..
@@ -175,11 +169,7 @@
 
         @see jassert()
     */
-  #ifdef JUCE_WIN32
-    #define jassertfalse			__debugbreak();
-  #else
     #define jassertfalse            { __asm int 3 }
-  #endif
   #elif defined (JUCE_MAC)
     #define jassertfalse            { Debugger(); }
   #elif defined (__GNUC__) || defined (JUCE_LINUX)
diff -u -r src\juce_core\threads\juce_CriticalSection.h /juce/src\juce_core\threads\juce_CriticalSection.h
--- src\juce_core\threads\juce_CriticalSection.h	Sun Aug 20 22:01:39 2006
+++ /juce/src\juce_core\threads\juce_CriticalSection.h	Tue Aug 08 17:01:00 2006
@@ -96,11 +96,7 @@
 private:
     //==============================================================================
 #ifdef JUCE_WIN32
-  #ifdef JUCE_64BIT
-    uint8 internal [44];
-  #else
     uint8 internal [24];
-  #endif
 #else
     mutable pthread_mutex_t internal;
 #endif

#9

Cool - thanks very much, I’ll go through those today and try merging it…


#10