Porting Applications to 64-bit Platforms

166d5a8b6792c761ae25aa1bcc1b1f4b
0
Trip99 101 Oct 08, 2005 at 21:09

I recently got a new AMD 64 dual core machine running Windows Professional X64 Edition and decided to convert my T2 Texture Generation Program to run as a 64 bit application. I found there was surprisingly little documentation on the Internet to help. By describing my experiences here I hope to help others wishing to write 64 bit applications.

The 64 bit Development Environment

The first step was to set up my development environment for 64 bit development. I use Visual Studio 2003 which unfortunately has little built in 64 bit support but can be adapted for use.

In order to create 64 bit applications you need to install the latest Platform SDK from Microsoft (Microsoft Platform SDK for Windows Server 2003). The SDK, as well as having libraries for 32 bit programming, has 64 bit versions for AMD64 and IA64 (Intel) development.

Getting the correct library and header file paths set up in Visual Studio proved surprisingly difficult. I wanted the choice of developing 32 bit or 64 bit projects. While the platform SDK comes with command files to set up the correct paths they wipe out any other paths. Since T2 uses DirectX I also needed the DirectX paths setting correctly. In the end I created two batch files, one for normal 32 bit development and one for 64 bit development.

32 bit development batch file

call "C:\Program Files\Microsoft Platform SDK\SetEnv.Cmd" /XP32 /RETAIL
call "dx_setEnv.Cmd" x86
start "" "C:\Program Files (x86)\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.exe" /useenv

64 bit development batch file

call "C:\Program Files\Microsoft Platform SDK\SetEnv.Cmd" /XP64 /RETAIL
call "dx_setenv.cmd" AMD64
start "" "C:\Program Files (x86)\Microsoft Visual Studio .NET 2003\Common7\IDE\devenv.exe" /useenv

The first line of each batch file calls the SDK provided command file to set 32 or 64 bit paths. The second line calls another command file that I created to append the correct DirectX paths (DirectX provides both 32 and 64 bit libraries). This batch file is a bit large to display on this page but you can download it here: dx_setenv.cmd. The final line starts Visual Studio with the /useenv flag to indicate it should use the environment variables for its paths.

You can check that the paths are correct via the Tools / Options menu, Selecting Projects and VC++ Directories.

My library paths for 64 bit development look like this:

C:\Program Files (x86)\Microsoft DirectX 9.0 SDK (August 2005)\Lib\x64
C:\Program Files\Microsoft Platform SDK\Lib\AMD64
C:\Program Files\Microsoft Platform SDK\Lib\AMD64\atlmfc

Now to create 32 bit applications I simply start visual studio with the 32 bit batch file and for 64 bit development I use the 64 bit batch file.

Configurations

Visual Studio 2003 does not support debugging 64 bit applications so I just created a release 64 bit configuration. You need to specify the target machine. This has to be specified in the linker command line box:

/machine:AMD64

(For Intel machines use IA64.)
Another issue is that you cannot run the 64 bit version from within Visual Studio. You get an ‘Unable to start debugging - The specified file is an unrecognised or unsupported binary format’.

This all makes developing 64 bit applications in Visual Studio 2003 a bit of a pain. You have lost the great debugger and so have to resort to log files and printf style output to track down bugs. One very useful setting is under C++ / General in the Visual Studio project property pages called ‘Detect 64 bit Portability Issues’. I would advise having this ticked for all development as I found it very useful in spotting cases where type size changes may cause issues. I also enabled asserts in release mode to help track down problems.

From 32 bit to 64 bit

At first glance the differences between 32 bit and 64 bit development seem quite small. All that is different is the size of some data types but this can lead to all sorts of problems! The data sizes are shown below:

Type        32 bit    64 bit
------------------------------
char        8         unchanged
short       16        unchanged
int         32        unchanged
long        32        unchanged
long long   64        unchanged
pointer     32        64
enum        32        unchanged
float       32        unchanged
double      64        unchanged
long double 128       unchanged
size_t      32        64

The pointer and size_t type are different sizes under 64 bit development. Note that under Linux 64 bit coding a long is 64 bits.

The basetsd,h header from the Platform SDK defines a number of useful types like DWORD32, DWORD64, INT32, INT64, ULONG_PTR etc. For a full list see this MSDN page: The New Data Types.

Structure Sizes
The single biggest headache I had with converting T2 to 64 bit was change in sizes of data in structures. The change in size of the size_t type created some problems as I had been saving it to disk to indicate the size of some data to follow. Again loading the old data files was causing a crash as I tried to load 64 bits when only 32 had been saved. Doing a safe cast to a 32 bit type solved this problem. One issue I had suspected would cause me problems but did not was the change in size of a pointer. This can cause issues if you store a memory address in a 32 bit data type e.g. an unsigned int. Fortunately I had not done that anywhere in my code but I have heard from others who have suffered from this.

T2 uses some free libraries like the excellent zlib library. Some of these libraries use quite low level C code that needed converting to avoid the type size issues.

Results
Below are two tables of timing results for the 32 and 64 bit versions of T2. They show quite a significant speed improvement running the 64 bit version however it must be noted that the 32 bit executable is running in a 64 bit environment which may slow it down somewhat. I still believe there is a good speed increase with the 64 bit version.

Texture Creation

Texture creation involves a lot of passes through texture data. From the results the 64 bit version increased the speed by about 28%

Project     32 bit   64 bit
---------------------------
Moody       0.71     0.52
Island1High 2.70     1.94

Lightmap Creation

Lightmap creation is a slow process as light rays are calculated between light sources and terrain, checking for obstructions in the way. From the results it can be seen that the 64 bit version increased the speed by as much as 50%. The larger the output, and hence the more calculations, the greater the speed gain.

Project     32 bit   64 bit
---------------------------
Moody       8.50     5.27
Island1High 20.10    10.17

Keith Ditchburn - October 2005
www.toymaker.info - My games programming site has the T2 download and many notes on games programming.

18 Replies

Please log in or register to post a reply.

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Oct 08, 2005 at 21:41

Very nice code snapshot. Although I have Athlon 64s in both my machines I haven’t tried developing 64-bit applications yet.

A couple questions. First, I assume you’re using the 64-bit edition of Windows XP - when you installed it, did you have any trouble finding drivers? I understand that 32-bit drivers don’t work in XP-64, and even when 64-bit drivers are available they have not been tested as thoroughly as the 32-bit ones, and so are sometimes unstable.

Second, are 64-bit binaries compatible between AMD64 and IA64?

F6ad85487ec271d99a0ef7a4e1b426d6
0
corey 101 Oct 09, 2005 at 00:55
166d5a8b6792c761ae25aa1bcc1b1f4b
0
Trip99 101 Oct 09, 2005 at 10:20

Reedbeta: My machine came with the 64 bit version of Window. I have a NVidia graphics card and the drivers are fine - all other drivers seem fine as well and most programs seem to run OK so far. The only problem I have really encountered is programs that refuse to install to the new Program Files (x86) folder, insisting that it is an illegal folder name! Be aware though that I have only just got this machine so there may be issues not yet found :) Ultimately I think installing a dual boot system may be best.

corey: that bamboozled me a bit :) I had got the information from a site about Linux 64 bit coding where long does become 64 bit. I just did some tests and you are correct a long is 32 bits under Windows 64. I need to do a few more tests to determine why the DWORD was causing me problems. I have adjusted the text accordingly - apologies for the confusion.

065f0635a4c94d685583c20132a4559d
0
Ed_Mack 101 Oct 09, 2005 at 11:14

Thanks for this very useful info, and the benchmarks.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Oct 09, 2005 at 16:51

Hmm, too bad mixed 32 and 64 bit development is quite a hassle. I hope this will be fixed in VC++ 2005 which is going to be released next month. (Does the 2005 express beta support 64 bit development btw?)

F6ad85487ec271d99a0ef7a4e1b426d6
0
corey 101 Oct 10, 2005 at 00:45

@Trip99

corey: that bamboozled me a bit :) I had got the information from a site about Linux 64 bit coding where long does become 64 bit. I just did some tests and you are correct a long is 32 bits under Windows 64.

No apologies needed, I have to double-check on these things too. Apart from what Win32 types are, the basic C++ types are the key as they’ll be used in multi-platform code. I’ve only done 64-bit research for MSVC7, but now I’m eager to find out how gcc changes the types.

corey

8e0a2324dec15af30ee7df0ceb6270f5
0
cm_rollo 101 Oct 10, 2005 at 13:09

I ran into some problems due to the changed size of long with 64-bit gcc when I was porting over the fluid studios memory manger for my new machine. Here are sizeofs for the types on linux:

char: 1
short: 2
int: 4
long: 8
size_t: 8
ptrdiff_t: 8
float: 4
double: 8

218341be2587d9bdef38af0c2066c308
0
Francois_Hamel 101 Oct 10, 2005 at 15:53

that is why one shouldn`t use basic types at all.
Usually I typedef them all like:

typedef uint64 unsigned long long;
typedef uint32 unsigned long;
typedef uint16 unsigned short;
typedef uint8  unsigned char;
typedef int64  long long;
typedef int32  long;
typedef int16  short;
typedef int8   char;

and I try to use only those types… so when porting to another platform (64 bits windows can be considered another platform), all you need to do is change those typedef`s and you`re done (mostly :blush: )

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Oct 10, 2005 at 18:54

Your typedefs are the other way around ;)

218341be2587d9bdef38af0c2066c308
0
Francois_Hamel 101 Oct 10, 2005 at 22:03

all you need to do is change those typedef`s and you`re done

just like I said, you need to change those typedefs…cause they are wrong :w00t:

seriously I don’t know why but I just can’t remember the correct order everytime I type them :wacko:

F6ad85487ec271d99a0ef7a4e1b426d6
0
corey 101 Oct 10, 2005 at 22:06

Just try to remember that most things are data-typed right to left.

corey

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Oct 11, 2005 at 03:29

Typedefs are just like variable declarations; you write “(type) (name);” in this case the name is not a variable name but the name of a new type.

C53b386a893da037739d159e4e40b8ef
0
eyebex 101 Oct 11, 2005 at 07:29

Thanks for the article!

8e0a2324dec15af30ee7df0ceb6270f5
0
cm_rollo 101 Oct 11, 2005 at 17:53

You can also include <inttypes.h>(http://www.opengroup.org/onlinepubs/007908799/xsh/inttypes.h.html) it defines integer types for a bunch of sizes. It works fine on unix/linux systems. Does anyone know if its also distributed with VS for windows?

331bf79520524e6f8fd777114156cbe8
0
pandora 101 Oct 12, 2005 at 00:14

Here’s a good site from AMD that has info about 64-bit porting http://developer.amd.com. I highly recommend the porting manuals.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Oct 12, 2005 at 11:03

@cm_rollo

You can also include <inttypes.h>(http://www.opengroup.org/onlinepubs/007908799/xsh/inttypes.h.html) it defines integer types for a bunch of sizes. It works fine on unix/linux systems. Does anyone know if its also distributed with VS for windows?

No, but VS has those types built-in: __int8, __int16, __int32 and __int64 as synonyms for their ISO equivalent (although there is none for __int64, long long isn’t official yet in C++, it is in C99 AFAIK), so it’s fairly easy to create the header yourself ;)

Also note that __int8 maps directly to char, which has no default signedness, and is therefore different to both signed char and unsigned char. Therefore, __int8, signed __int8 and unsigned __int8 are different types as well.

166d5a8b6792c761ae25aa1bcc1b1f4b
0
Trip99 101 Oct 12, 2005 at 17:47

I am getting my beta copy of the new visual studio soon so I will see how easy it is with that to create 64 bit code and report back.

Aa20dbb1d6c9b94439558288433b2945
0
WandererMaster 101 Jan 14, 2007 at 09:15

Wished to share with all my brothers’ programmers interesting references:
http://www.viva64.com/links.php

http://www.viva64.com/articles.php
These best materials selection about development 64-bit applications on C++.
I hope, my information will be useful to you.