Blake
|
|
« Reply #100 on: February 05, 2009, 06:26:43 AM » |
|
Ah.. I'm a happy programmer at the moment, because I finally got Owlboy optimized to run at 60FPS on the Xbox without any drop in framerate, throughout the entire large dungeon we've made.
I was very OCD about the framerate!
|
|
|
Logged
|
|
|
|
increpare
Guest
|
|
« Reply #101 on: February 05, 2009, 06:29:38 AM » |
|
any tearing?
|
|
|
Logged
|
|
|
|
Blake
|
|
« Reply #102 on: February 05, 2009, 07:23:25 AM » |
|
No sir! It's all synced up.
|
|
|
Logged
|
|
|
|
genericuser
Guest
|
|
« Reply #103 on: February 05, 2009, 01:15:48 PM » |
|
I just figured out how to use atan2 to make stuff move towards coordinates :D
I'm extra happy since that's one of the biggest problems I've had coding...well, anything.
|
|
|
Logged
|
|
|
|
Kaelan
|
|
« Reply #104 on: February 05, 2009, 07:05:55 PM » |
|
Ah.. I'm a happy programmer at the moment, because I finally got Owlboy optimized to run at 60FPS on the Xbox without any drop in framerate, throughout the entire large dungeon we've made.
I was very OCD about the framerate!
Out of curiosity, are you making much use of the GPU? The 360's relatively weak FPU performance has me wondering if I'm going to have to move things like my particle system over to the GPU in order to maintain a stable framerate.
|
|
|
Logged
|
|
|
|
Zaknafein
|
|
« Reply #105 on: February 05, 2009, 07:11:28 PM » |
|
Are you using XNA/C#? Have you had any specific issues, like I've heard people going crazy and unrolling every foreach loop to for(int...)'s and avoiding stack instanciation like the pleague. I hope this is bullshit.
|
|
|
Logged
|
|
|
|
Cymon
|
|
« Reply #106 on: February 05, 2009, 07:31:28 PM » |
|
Spent my lunch today with a friend programming a Quadratic Formula program into our TI-84 calculators. Now, we just input values for a, b, and c, and out pops the x-values. For a beginning programmer (extremely beginning) like me, this was a huge triumph.
Awesome! You've induced a wonderful sepia-toned flashback for me, in which I have thicker hair and am arguing with my teacher over whether I should be allowed to use programs I write myself on a test. I think my response was to spend more time writing a video poker game and less time encoding my math book. What's next for you? Well, I tried doing the same program in C++, but it was a little too advanced for me. What? Hold on, lemme take a stab at this: #include <math.h> #include <stdio.h>
int main () { int a, b, c; double p, x1, x2;
printf ("Input values for:\n"); scanf ("A: %d", a); scanf ("B: %d", b); scanf ("C: %d", c); p = (b * b) - (4 * a * c); if (p < 0) printf ("\nX has no real values."); else { x1 = (-b + sqrt(p)) / (2 * a); x2 = (-b - sqrt(p)) / (2 * a); print ("X = %.2f and %.2f", x1, x2); } getch (); }
Someone throw that in a compiler and tell me if it works. I gotta put my kids to bed. I think it should, tho.
|
|
|
Logged
|
|
|
|
Kaelan
|
|
« Reply #107 on: February 06, 2009, 04:37:50 AM » |
|
Are you using XNA/C#? Have you had any specific issues, like I've heard people going crazy and unrolling every foreach loop to for(int...)'s and avoiding stack instanciation like the pleague. I hope this is bullshit.
I've had to control my heap allocation rate and optimize out some floating point operations (since they're significantly more expensive) but I haven't had to do anything crazy like unroll loops. Stack allocation is so ridiculously cheap on .NET that I can't imagine why people would need to avoid it (though I have actually seen improvement by eliminating some calls to constructors for stack values, that was because those constructors did floating-point math.) I'm basically just seeing a situation where my (single-threaded) game's profile is vastly different on the 360 than on the PC, with certain operations being way more expensive and other operations being way cheaper, and the 360's framerate is about half what I get on the PC. I'm still well above 60fps, so I'm not worried yet, but since there's no CPU profiler for the 360 yet I'm trying to keep an eye out for good optimization techniques. Luckily there's a good memory profiler for .NET on the Windows that's completely free, and finding a decent CPU profiler isn't hard either, so I've been able to find all of my bottlenecks so far by testing on my PC. Then again, the fact that Vector2.Dot is #3 on my CPU profiles means I might be doing something fundamentally wrong.
|
|
« Last Edit: February 06, 2009, 05:01:24 AM by Kaelan »
|
Logged
|
|
|
|
Zaknafein
|
|
« Reply #108 on: February 06, 2009, 05:17:12 AM » |
|
Cool, I'll be trying to make Fez run (fast) on Xbox360 soon-ish, so I'm looking for all the foresight I can get.
|
|
|
Logged
|
|
|
|
increpare
Guest
|
|
« Reply #109 on: February 06, 2009, 05:22:33 AM » |
|
heh heh heh I'm having a relatively content afternoon, though I have been dragging my heels a little bit. Doing UI stuff atm, which is never particularly pleasant.
|
|
|
Logged
|
|
|
|
Blake
|
|
« Reply #110 on: February 06, 2009, 09:57:15 AM » |
|
Well, for Owlboy (entirely 2D game), the effects aren't too terribly complex so I'm not pushing things like particles to the GPU. Instead, I'm just allocating the particle objects beforehand and reusing them when they are 'destroyed.' Nothing too fancy there.
As far as unwinding loops and stuff goes, there isn't a need to worry about that so much, just be sure to do all your allocating of managed objects before the actual gameplay starts (loading screen). There are a few things the just happen to always allocate objects (without explicit instruction to do so), such as foreach (*sometimes*) and a few others. I ran into that problem once, but it was easy to fix.
.. Now I'm officially excited for Fez 360
|
|
|
Logged
|
|
|
|
Kaelan
|
|
« Reply #111 on: February 06, 2009, 05:04:42 PM » |
|
As far as unwinding loops and stuff goes, there isn't a need to worry about that so much, just be sure to do all your allocating of managed objects before the actual gameplay starts (loading screen). There are a few things the just happen to always allocate objects (without explicit instruction to do so), such as foreach (*sometimes*) and a few others. I ran into that problem once, but it was easy to fix. Good point there, that initially surprised me as well. One particularly hard-learned lesson there: Since casting value types to reference types always generates garbage, casting a struct to an interface will also generate garbage. The subtle bit is that if you have code something like this: struct MyEnumerator : IEnumerator<float> { ... public bool MoveNext () { } ... } Then the following code block will generate garbage: IEnumerator<float> e = new MyEnumerator(); e.MoveNext(); But the following will not: MyEnumerator e = new MyEnumerator(); e.MoveNext(); This seems super obvious until you apply it to things like LINQ and function argument types - a lot of the garbage my game used to generate was a result of this; luckily in most cases you can easily get rid of the garbage without having to make major code changes. List<T> and Dictionary<K, V> both happen to define their enumerators as structs instead of classes, so you can use foreach on those containers without generating garbage; on the other hand LINQ will always generate garbage no matter what, so you pretty much can't use it in update/draw code. Generics come in handy for dealing with this - you can do something like: void MyFunction<T> (ref T foo) where T : struct, IEnumerator<float> And get the ability to use methods of interfaces without incurring the overhead of a forced type conversion or a copy.
|
|
|
Logged
|
|
|
|
David Pittman
|
|
« Reply #112 on: February 07, 2009, 11:41:58 PM » |
|
Today I am a happy programmer because I improved my memory allocation and got a substantial performance gain from it.
Way, way back in the early days of this project, I wrote a custom allocator/memory manager, mostly to get some more useful debug statistics for catching memory leaks, and just because I could and it seemed like a fun and interesting challenge. It was a pretty basic, minimal design: first-fit algorithm with a single linked list of blocks. It's stable and useful for debugging, but it's significantly slower than the default CRT allocator. Slow enough that I began to suspect it was my primary performance bottleneck. So I switched it off, and sure enough, my frame rate doubled.
So I could have just abandoned my custom allocator and used the default. My engine is largely feature complete and I don't expect to run into any really nasty memory issues. But then I thought about why my allocator was slower and realized a previously hidden benefit of having a custom memory manager. Because I knew its exact implementation, I could arrange my memory in such a way as to be optimal for the allocator.
The reason my allocator was so slow was that it has to traverse the linked list to find a free block of the desired size for every allocation. As the project has grown, that list has become relatively large (~20k allocated blocks). In order to improve performance, I needed to reduce the size of that list. So I moved a few systems with lots of total allocations and/or lots of allocations per frame to separate memory arenas. I gave particles, config vars, and strings their own separate allocators, which stops them cluttering up the main block list and makes them faster internally.
But the performance was still lagging behind the default allocator, and I remembered something I'd realized months ago and then completely forgotten about. All the game's subsystems and the static elements of the world are loaded in first, which means they sit at the front of the block list. That means that every subsequent allocation is going to have to iterate over those blocks and will never find a free block in there, because that stuff is basically static. All I had to do was use a separate allocator while initializing the game and loading worlds, and then the main allocator was a blank slate for runtime. Now my memory performance is at least on par with the default allocator's, and more importantly, memory allocation is no longer a bottleneck.
I guess the surface lesson here is to trust the default allocator. The deeper lesson I learned is that if I'm going to re-implement something, to actually take advantage of what it offers beyond the default.
|
|
|
Logged
|
|
|
|
BorisTheBrave
|
|
« Reply #113 on: February 08, 2009, 03:12:10 AM » |
|
There are actually drop in replacements for the default allocator that supposedly outpeform it. But the really best performance comes when you understand the characteristics of your own programs allocations, and use that information to your advantage, just like you have been. The Box2D engine has a neat trick along those lines: it has separate allocators for stuff that is temporary (scrapped every frame), and persistent. It then uses different strategies for each.
|
|
|
Logged
|
|
|
|
cpets
|
|
« Reply #114 on: February 08, 2009, 03:06:34 PM » |
|
I'm a happy programmer because I just finished my first game since 1997, when I wrote and released a tetris clone. I guess it's not finished in the sense of being an actual game, or having proper mechanics, or graphics, or balancing, or graphics, or sound, but, you know, it's done in the sense that the ludum dare compos only allow 48 hours and now my hours are up and I've posted a release. I'm choosing to think of this as the dawning of a new era.
|
|
|
Logged
|
|
|
|
increpare
Guest
|
|
« Reply #115 on: February 08, 2009, 03:09:37 PM » |
|
quite a nice game it is as well, cap!
|
|
|
Logged
|
|
|
|
Cymon
|
|
« Reply #116 on: February 08, 2009, 06:52:20 PM » |
|
I am an ecstatic programmer because I've been in communication this weekend with a new programmer inspired by Cymon's Games, as well as getting a couple of Cymon's Games submitted for Ubuntu distribution by another reader. What a great weekend.
|
|
|
Logged
|
|
|
|
increpare
Guest
|
|
« Reply #117 on: February 10, 2009, 04:11:30 AM » |
|
i'm quite happy; I've managed to pretty much *completely* resist any temptations to prematurely optimize the game I'm working on at the moment. std::strings strewn about everywhere, barely a char* in sight; not a single array it pauses occasionally, but that's because of one particular calculation, which I can maybe get about to dealing with when everything else is done. and: I got through some coding I had been putting off for several days this morning. hopefully get the rest of it done over the next couple of hours.
|
|
|
Logged
|
|
|
|
Will Vale
|
|
« Reply #118 on: February 11, 2009, 02:48:34 AM » |
|
I'm happy: a while ago I recovered some art and code from 15-year-old floppy disks, but unfortunately I hadn't left the project (kind of a Wing Commander demake) in a working state. This evening I got it all in source control, installed DosBox and Turbo Pascal 6, and fixed the worst of the problems. I can now run the front end and in-game executables, but can't chain them together. It's quite tricky to debug since with the IDE running there isn't enough heap to run the game Still, it was vintage bugfixing fun
|
|
|
Logged
|
|
|
|
increpare
Guest
|
|
« Reply #119 on: February 11, 2009, 02:51:30 AM » |
|
you could probably get it working on freepascal, if you want something more hi-fi
|
|
|
Logged
|
|
|
|
|