Simplicity Oriented Programming

16.07.2011 16:51 in programming

After few years on Warsztat (a Polish gamedev site) I’ve noticed an interesting phenomenon. Every now and then there are Compos (programming competitions) organized in two different flavours. Some compos are single-run events that last only few hours, others are long-term (several days/weeks). And as an extra catch, the former are usually restricted to basic APIs (SDL, OpenGL etc) while the latter are free-for-all (all sorts of engines, UDK/Unity allowed).

Now, results are somewhat shocking. Much more people participate in short compos than the long ones. But the best part is that quality of games created is just the same, no matter if the games was made in 2 hours or 4 weeks. Why?

  1. Well, creating game in 4 weeks doesn’t usually mean neither 672 nor 224 working hours. In extreme cases 4 week compo is just a 2-hours compo, with 2 hours located at the very end of 4 weeks.
  2. A lot of game value is an idea. Fact: you won’t come up with better idea in 4 weeks than in 10 minutes.
  3. Development process for 2-hours game is very dense. And most of the time is spent on improving core features (because there are no others).
  4. On the other hand, in long-term projects people start to focus on insignificant features. The moment you start improving abstract communication between task pools, adding GUI widgets so that you can make a built-in MP3 player or making splash screen data-oriented, your project is screwed to hell.

And this is probably the most important lesson to remember. If you need to do something very quick, code will be horrific, but also short, simple and fixable. With no time constraints, code will get new levels of complication, features and bugs. Time spent on maintaining won’t justify the result.

In 4 weeks, you can make several iterations of speed-coding, each time improving core features of the game. If you start with future proofness in mind, writing code and fixing bugs will consume most of the time. Sure, in 4 weeks you can make a ton of assets/levels, but how good are they is core gameplay is not good enough?

Finally, one solid C(++) tip: when adding new features, start with the smallest of available guns:

  1. Global function — if you need to display score, don’t hesitate to add void DisplayScore() somewhere. If your game is single-player, store score as a global variable. See? You have just saved 10 minutes of writing getters, setters and designing communication between modules. If your game is multi-player then you will need to store and display scores per-player. But there is no reason to be able to display arbitrary score of arbitrary player if your game is not yet multiplayer. Believe me, you’ll have bigger problems than displaying score with that.
  2. If your functions share common code or require helper functions, group them somewhere, possibly in separate file. Remember about static functions and variables — contrary to “OO” static, file static is about visibility. But it’s cool, because you can have a file for all font-related operations and store internal data in static global variable. Helper functions can be static, and public ones go to one shared header (if you write simple code, compilation time is never your enemy).
  3. Promote functions to classes only when it’s relevant and useful. Remember, classes means objects, objects mean relations and relations means complexity. Is your gameplay so cool that you have time for code complexity?
  4. Any design patterns or other exotic stuff is the last resort if none of above is good enough. Personally? Never got there.

(from #altdevblogaday)

Keep data close, part 1

17.05.2011 02:52 in programming, C++

I would like to present a very cool technique, widely used in C libraries, yet almost completely forgotten in C++.

We have a String class. It is a reference-counted, immutable string. Typical data structures in C++ would look like:

struct string
{
  string_data * data;
};
 

struct string_data
{
  int refcount;
  int length;
  char * data;

};

So, string is merely a reference to actual string_data. Creating new string objects (string foo = "hello world") looks like:

  1. string_constructor(const char *)
  2. allocate string_data
  3. string_data_constructor(const char *)
  4. allocate char[]
  5. copy data, set all other members

In memory, it would actually look like:

So, we have one stack allocation, two dynamic allocations and our data is in three different places in memory. But in C++ terms it seems impossible to improve it. However, we can go C way and change string_data definition:

struct string_data
{
  int refcount;
  int length;

  char data[1];
};

Array of one character? I must be crazy, right?

Most C++ courses are not very precise about pointers and arrays. Especially, what is the difference of following instructions?

const char * string1 = "hello world";

const char string2[] = "hello, C++!";

And what is the difference of those?

int foo(const char *) { printf("*\n"); }

int foo(const char[]) { printf("[]\n"); }

Unfortunately, in C++ world where really various things can be static, answers are different. In first case, string1 and string2 are something else. In second case, there is no difference — actually, that code won’t compile due to non-unique overload.

Maybe little investigation? Let’s print some data:

printf("%p %p %s\n", string1, &string1, string1);
printf("%p %p %s\n", string2, &string2, string2);

What we do is printing expression as a pointer, address of this expression as a second pointer and null-terminated string pointed by expression. Results:

0x08048650 0xbfddbfa4 hello world
0xbfddbf98 0xbfddbf98 hello, C++!

Now you see magic behind it. 0xbf…… are stack addresses while 0×08048650 comes from somewhere else (likely from static, read-only data section). So, while pointer types hold address inside, arrays points to themselves. And we can abuse it!

“Typical” C++ allocation of string_data would look like this:

string_data * foo = new string_data;

It would allocate sizeof(string_data) bytes (9 + padding, probably 12). But in fact, we can allocate as much as we want! For example:

string_data * q = (string_data*)malloc(2 * sizeof(int) + 12);

new (q) string_data;

In this case — 2 ints and 12 bytes of string data. After successful allocation we need to manually invoke constructor, using placement new. Similarly, regular delete q won’t work — following code will:

q->~string_data();
free(q);

Of course if data type is simple (built-in datatypes, relaxed POD, whatever) there is no need to call constructor and destructor (although those calls probably would be simply optimized away). And malloc/free can be replaced with custom allocation routines.

And after such allocation, we can use data like it was not a char[1] array but rather a char[as much as we have allocated] array! How does memory look like with this data structure?

And there are numerous benefits of such approach:

  • one dynamic allocation less
  • data is less scattered in memory
  • we saved some memory (how much? size of the pointer + size of allocation metadata)

In the next part, I’ll show how we can save even more allocations/memory.

(from #altdevblogaday)

Cross-platform system info and why Windows rocks

13.05.2011 14:59 in sysinfo, programming

Recently I'm creating a base library for all my gamedev adventures. It contains both very low-level features (allocator, string, vector, hashmap, errors etc) and reasonably middle-level features (like HTTP requests). Grabbing system information is rather high-level but very important, especially for OpenGL developer. It's very helpful if you can inform user that he just needs to update drivers.

Typical output:

[23:12:26] CPU : 8 x 2806 (2806) MHz (Intel(R) Core(TM) i7 CPU         930  @ 2.80GHz, FPU MMX SSE SSE2 SSE3 SSSE3 EST SSE4.1 SSE4.2 POPCNT HTT)
[23:12:26] RAM : 7956MB/12278MB
[23:12:26] GPU : NVIDIA GeForce GTX 460 [8.17.12.6658, 1-7-2011] :: NVIDIA Corporation GeForce GTX 460/PCI/SSE2 using OpenGL 4.1.0
[23:12:26] OS  : Windows 7 (6.1 Service Pack 1) 64 bit

Many folks complain on Windows API, it's backwards compatiblity and overall misery. But while working on sysinfo program, I've actually learned how powerful it is. Few examples:

Memory

On Windows there is GlobalMemoryStatusEx function that returns accurate results, in 64-bit format even for 32-bit applications.

On Linux there is /proc/meminfo but its results are very hard to interpret and are different than results of free command. In the end, I've used free -mo | head -n 2 | tail -n 1. Pure magic (and pure hope that free output format won't change).

Mac OSX amused me. As you may or may not know, I'm an iOS developer. I thought that Mac will be quite similar to its iOS counterpart, maybe with API like [[NSSystem sharedSystem] freeMemory]. Hell no! To obtain memory statistics, you need to access Mach (Mac OSX kernel) layer, like this:

mach_port_t host_port;
mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
vm_size_t pagesize;
vm_statistics_data_t vm_stat;

host_port = mach_host_self();
host_page_size(host_port, &pagesize);        
   
if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) return;

natural_t mem_used = (vm_stat.active_count + vm_stat.inactive_count + vm_stat.wire_count) * pagesize;
mem_free = vm_stat.free_count * pagesize;
mem_total = mem_used + mem_free;
    
mem_free /= 1024 * 1024;
mem_total /= 1024 * 1024;

GPU

On all platforms I query OpenGL for vendor, renderer and both (OGL and GLSL) version strings. But this doesn't include driver information. And each vendor/platform has his own vision of those strings.

So, on Windows I use SetupAPI to obtain precise GPU information. With SetupDiEnumDeviceInfo I search for FILE_DEVICE_VIDEO devices. This is useful, because it allows to check multi-GPU configurations or to bypass additional layers of (OpenGL) emulation (like for example screen capturing applications). And with SetupAPI there is standarized driver information available.

But on Linux it's not so easy. I have no Linux-specific programming knowledge (not that I've used SetupAPI before). I didn't even search for kernel API for this. I've just used lspci command and searched for VGA compatible controller. For NVIDIA cards I've found that I can obtain driver info from /proc/driver/nvidia/version. For ATI or other vendors -- I have no idea. Fortunately, ATI seems to include driver information in OpenGL version string (like 3.3.10237 Compatibility Profile Context) so this should not be a problem. But if you know better solution, please let me know.

On Mac OSX I didn't even try. In fact you can't install or update GPU drivers on Mac, because those are not provided by NVIDIA or other IHV, but by Great Apple itself -- and that also means that OpenGL stopped at 2.1 version. Hate you, Apple. There is a magic number in OpenGL version string: 2.1 NVIDIA-1.6.26 but I have no idea how could I compare this to Windows/Linux driver version.

Conclusions

There is other data as well, but as complex as examples above. For example to obtain OS data there is GetVersionEx and GetNativeSystemInfo in WinAPI (Native flavour returns 64-bit information for 32-bit apps on 64-bit Windows). On Linux/OSX I just use uname -a (Mac OSX have no variations, and on Linux it would be hard because each distribution has its own vision of versioning). CPU was fortunately mostly cross-platform, because I focus on __cpuid data (BTW -- do you know how to obtain HTT and/or number of cores from __cpuid?).

So my verdict is: Windows rocks, other platforms are pure chaos. At least in grabbing system information. But really, WinAPI may be awkward or "too backward compatible" but at least is simple and powerful.

BTW, if you want to test sysinfo program on your PC, you can grab Windows, Linux or Mac OSX version and share results in comments. This is not the most recent version but results would be helpful.

Why does functional programming suck?

03.10.2010 18:58 in programming

Every single discussion board for developers has a thread called Functional programming vs rest of the world where you could read that Haskell/LISP/Scala/etc is much, MUCH better than C++. But when you ask about AAA games coded entirely in Haskell you get just silence.

Today I've been reading topic about exceptions in C++. One of the arguments against not using exceptions is that when you use return codes for errors you have to pass real results in arguments, like:

int OpenFile(const char *filename, Handle *handle);

Handle h;
if (SUCCESS == OpenFile("file.txt", &h))
{
  // ...
}

And that doing so makes code "less clear" because you can't see what is input and what is output of function -- and you should return output ONLY as return value.

But we should go deeper: OOP is out of question (because method call can modify internal object state) and so are pointers (bacause you could modify something far away from local scope). Now we only need to get rid of variables (as all of our &variables& are constant) and voila! We have Haskell. :)

Let's assert that this style of coding is cool -- so why does nobody code games in Haskell?

Well, I think that functional programming lovers forget that computer program is composed like this:

1. Read input
2. Process input data into output data
3. Write output data

And functional programming is useable only in part 2. Input/output doesn't fit functional programming anyhow. If that parts are simple (like read N numbers from file, process them and save M numbers into another file) we could ignore it. But if it's gamedev, part 1 (reading player/network input) is important, and part 3 is VERY important (like rendering, sound, network communication etc). Part 2 is quite simple or sometimes even trivial -- so why should we need FP for it?

On the other hand, FP is good for example in shaders. GLSL/Cg/HLSL mimic C syntax, but they are overall quite functional. Pure data transformation (input interpolators -> fragment shader -> output colors/data); no external routines; no memory management; massive parallelism. So its just a matter of proper tool for given job.

Why does functional programming suck?

03.10.2010 18:58 in programming

Every single discussion board for developers has a thread called Functional programming vs rest of the world where you could read that Haskell/LISP/Scala/etc is much, MUCH better than C++. But when you ask about AAA games coded entirely in Haskell you get just silence.

Today I've been reading topic about exceptions in C++. One of the arguments against not using exceptions is that when you use return codes for errors you have to pass real results in arguments, like:

int OpenFile(const char *filename, Handle *handle);

Handle h;
if (SUCCESS == OpenFile("file.txt", &h))
{
  // ...
}

And that doing so makes code "less clear" because you can't see what is input and what is output of function -- and you should return output ONLY as return value.

But we should go deeper: OOP is out of question (because method call can modify internal object state) and so are pointers (bacause you could modify something far away from local scope). Now we only need to get rid of variables (as all of our &variables& are constant) and voila! We have Haskell. :)

Let's assert that this style of coding is cool -- so why does nobody code games in Haskell?

Well, I think that functional programming lovers forget that computer program is composed like this:

1. Read input
2. Process input data into output data
3. Write output data

And functional programming is useable only in part 2. Input/output doesn't fit functional programming anyhow. If that parts are simple (like read N numbers from file, process them and save M numbers into another file) we could ignore it. But if it's gamedev, part 1 (reading player/network input) is important, and part 3 is VERY important (like rendering, sound, network communication etc). Part 2 is quite simple or sometimes even trivial -- so why should we need FP for it?

On the other hand, FP is good for example in shaders. GLSL/Cg/HLSL mimic C syntax, but they are overall quite functional. Pure data transformation (input interpolators -> fragment shader -> output colors/data); no external routines; no memory management; massive parallelism. So its just a matter of proper tool for given job.

Why does functional programming suck?

03.10.2010 18:58 in programming

Every single discussion board for developers has a thread called Functional programming vs rest of the world where you could read that Haskell/LISP/Scala/etc is much, MUCH better than C++. But when you ask about AAA games coded entirely in Haskell you get just silence.

Today I've been reading topic about exceptions in C++. One of the arguments against not using exceptions is that when you use return codes for errors you have to pass real results in arguments, like:

int OpenFile(const char *filename, Handle *handle);

Handle h;
if (SUCCESS == OpenFile("file.txt", &h))
{
  // ...
}

And that doing so makes code "less clear" because you can't see what is input and what is output of function -- and you should return output ONLY as return value.

But we should go deeper: OOP is out of question (because method call can modify internal object state) and so are pointers (bacause you could modify something far away from local scope). Now we only need to get rid of variables (as all of our &variables& are constant) and voila! We have Haskell. :)

Let's assert that this style of coding is cool -- so why does nobody code games in Haskell?

Well, I think that functional programming lovers forget that computer program is composed like this:

1. Read input
2. Process input data into output data
3. Write output data

And functional programming is useable only in part 2. Input/output doesn't fit functional programming anyhow. If that parts are simple (like read N numbers from file, process them and save M numbers into another file) we could ignore it. But if it's gamedev, part 1 (reading player/network input) is important, and part 3 is VERY important (like rendering, sound, network communication etc). Part 2 is quite simple or sometimes even trivial -- so why should we need FP for it?

On the other hand, FP is good for example in shaders. GLSL/Cg/HLSL mimic C syntax, but they are overall quite functional. Pure data transformation (input interpolators -> fragment shader -> output colors/data); no external routines; no memory management; massive parallelism. So its just a matter of proper tool for given job.

Why does functional programming suck?

03.10.2010 18:58 in programming

Every single discussion board for developers has a thread called Functional programming vs rest of the world where you could read that Haskell/LISP/Scala/etc is much, MUCH better than C++. But when you ask about AAA games coded entirely in Haskell you get just silence.

Today I've been reading topic about exceptions in C++. One of the arguments against not using exceptions is that when you use return codes for errors you have to pass real results in arguments, like:

int OpenFile(const char *filename, Handle *handle);

Handle h;
if (SUCCESS == OpenFile("file.txt", &h))
{
  // ...
}

And that doing so makes code "less clear" because you can't see what is input and what is output of function -- and you should return output ONLY as return value.

But we should go deeper: OOP is out of question (because method call can modify internal object state) and so are pointers (bacause you could modify something far away from local scope). Now we only need to get rid of variables (as all of our &variables& are constant) and voila! We have Haskell. :)

Let's assert that this style of coding is cool -- so why does nobody code games in Haskell?

Well, I think that functional programming lovers forget that computer program is composed like this:

1. Read input
2. Process input data into output data
3. Write output data

And functional programming is useable only in part 2. Input/output doesn't fit functional programming anyhow. If that parts are simple (like read N numbers from file, process them and save M numbers into another file) we could ignore it. But if it's gamedev, part 1 (reading player/network input) is important, and part 3 is VERY important (like rendering, sound, network communication etc). Part 2 is quite simple or sometimes even trivial -- so why should we need FP for it?

On the other hand, FP is good for example in shaders. GLSL/Cg/HLSL mimic C syntax, but they are overall quite functional. Pure data transformation (input interpolators -> fragment shader -> output colors/data); no external routines; no memory management; massive parallelism. So its just a matter of proper tool for given job.