Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 14 Feb 2007
Online Last Active Today, 06:17 AM

#5313154 Amd openGL driver crashes

Posted by on 28 September 2016 - 08:16 PM

Whichine of your code does it crash on, and what's the exact crash message?

In my experience, NVidia drivers tend to tolerate (and even encourage) non-standard code, whereas AMD drivers tend to follow the letter of the spec and crash if you deviate from it. So I wouldn't assume a driver bug immediately.

It's been a while since I read the GL spec... So as a guess, try getting the status of the link operation before detaching the programs, instead of after.

#5313138 When should I use int32_t rather than int

Posted by on 28 September 2016 - 06:33 PM

Yeah I'm in the "use int/uint/float by default, and other sized types when you must" camp.

You should only specify the size when it actually matters and let the compiler do the work of figuring out the best size as much as possible.  The places specific sizes will matter vary but an incomplete list would be things such as file formats, network IO, talking to hardware at a low level and various other relatively uncommon tasks.  So, for instance:
  for (int32_t i=0; i<10; ++i)  // Don't do this.  
instead use:
  for (int i=0; i<10; ++i)

I disagree with this. If you suddenly compile for a platform where int is 16 bits, you may end up with all sorts of weird and hard to find bugs. This has actually happend to me. I've always considered the part where int/long/etc are compiler defined to be an incredibly flawed design decision. It's supposed to help with portability, but in my opionion/experience it does the exact opposite since the same code might behave completely different on another target.

Technically if you follow All8's advice including the bolded bit, then you won't get weird bugs :wink:
"When it actually matters" is:
* When you need to use a specific memory layout -- e.g. you require a struct have a 4 byte field.
* When you're working with "large" ranges -- e.g. a list of 100k elements.
So All8's loop should be:
static_assert( 10 <= INT_MAX );
for (int i=0; i<10; ++i)...

In my case, I don't care about porting my game engine to a 16-bit platform, so I'm actually happy to include something like: 
static_assert( INT_MAX >= 0x7FFFFFFF, "Code assumes a 32/64 bit platform. Porting will be hell." );

int doesn't give you any guarantee on the number of bytes it uses. So when you need this guarantee you would need to use any of the sized integers, e.g. for serialization. For performance there is actually int_fast32_t. E.g iirc on the PS3 the fast integer was actually 64bit and they didn't want to make the regular int 64bit. We used fast int in for loops. Personally I would now worry about this.

PPC64 could do int64 at full speed, so there was no need to avoid int64 for perf reasons, but int32 was also full speed IIRC -- there were instructions to operate on half a register as an int32. Most compilers should still implement int as int32_t, as it's the same speed but half the RAM usage.

#5313126 Basic multithread question

Posted by on 28 September 2016 - 05:21 PM

Desktop CPUs run all the time and use the same amount of power because if you don't use the cpu the kernel will do.What happens is that your kernel take the cpu time, to do house keeping work and on top it runs nop if nothing is to do.

The "house keeping" work a kernel does is neglectable. Maybe sometimes you have some stupid "services" run in the background that e.g. create index lists of filenames. But the kernels (Be it Windows or Linux) them self do not do this kind of stuff.

x86 (Since the 8086 to be accurate) uses the HLT command to put the CPU/Core into a halt state. And via IRQ/INT the CPU/Core wakes up again. So there is no need for a NOP busy loops.
FWIW, if you're actually writing a busy wait / spin loop for X86 these days, then you really must put a very specific NOP instruction in the loop body (the one emitted by _mm_pause/YieldProcessor), which not only signals that hyperthreading should kick in immediately, but that the CPU should enter a low power state until the loop condition is met and to de-pipeline the entire loop body on the fly.

For highly contended locks, it can be useful to spin for some nanoseconds before actually putting the thread to sleep via the kernel, as it's likely that this short pause is enough for the lock to become available.

#5313018 Sharpen shader performance

Posted by on 28 September 2016 - 07:48 AM

I wouldn't think so. When Cg was still active, you could actually compile from Cg->GLSL :wink:
Silence must be thinking of the fact that GLSL will be compiled into an internal format that's specific to NVidia/AMD/Intel/Qualcomm/etc, and God knows what happens in that step.
At least with HLSL->D3D bytecode->Vendor ASM (and GLSL->SPIR-V bytecode->Vendor ASM) there's a middle step where you can see what optimisations the offline compiler has performed :D

#5312958 Why do new engines change their file extensions and formats all the time?

Posted by on 27 September 2016 - 11:14 PM

We often change file formats multiple times within the development of one single game, let alone multiple games!

Data structures change as requirements change / are discovered.


For us, changing a structure is not a big deal as all the files are automatically generated from source files (e.g. FBX/DAE/etc). If you change the model format, you just run a batch file and it automatically regenerates all of the game's model files in this new format.

#5312491 Why C# all of a sudden?

Posted by on 25 September 2016 - 07:26 AM

For 20 years C++ was the recommended standard language, especially in the gaming industry. Mostly because it is fast and powerful, inheriting most programming language standards you can possibly think of.

Game and engine development have diverged for a while and the breach is only getting larger over time. Neither AAA nor indie studios build their own engines anymore, that job is now left to middleware developers. All that performance you're talking about needs to be done on the engine side of things, while game developers now instead focus on the higher level stuff - and that can be done with languages that aren't as close to the metal as C++.

It also says something about how complex the game industry has gotten now.

I'd say that most AAA companies build their own engine -- licensed engines are quite rare in AAA from what I can see.
e.g. off the top of my head, almost every AAA company that I can think of has their own internal engine(s): EA, Activision Blizzard, Ubisoft, 2K, Rockstar, Konami, Square Enix, 343, CCP, Naughty Dog, Guerrilla, Insomniac, ArenaNet, Ready At Dawn, Bethesda, CD Projekt, Valve, Codemasters, Riot, Nintendo, Wargaming... In my personal experience, 50% of my games jobs have used licenced engines, and 50% have used their own proprietary tech.
But yes, these engines are typically developed in C++ while the game itself may or may not be. All (4) of the PS4/Xbone games that I've worked on have actually used Lua for the vast majority of the gameplay codebase, and use C# for the vast majority of the tools codebase (and yep, C++ for the majority of the engine codebase)!
In the tools codebase, long term maintainability beats absolute performance, so C# is a great choice.
In the gameplay codebase, daily programmer productivity and agility to change beats absolute performance, so Lua is a great choice.
In the engine codebase, performance is king and we do a lot of data-oriented work, reinterpreting blobs of bits and streaming tightly packed bits of memory between parallel systems, so C++ is a great choice.

C has been a large standard for game development for long time, especialy in times of large impacting games and games "golden era". Wheather it was John Carmack's work, even Doom 3 , Shiny Entertainment's games, Half Life's Source engine as derived from Quake engine, etc. - simply the majority of AAA back then, as well as engines that were not designed and ment to be licensed (Unreal was c++ for that matter).
C++ can introduce performance negative impacts against C, since the inheritance was a subject of heavy missusing very often, making possibly all objects unable to interleave in immediate accessible arrays and so forth.
So if you present C++ as great solely becouse it has been the industry standard for develping video games, you have to review your data.

Doom 3 and Half-Life were mostly C++ with a tiny bit of C :)
The late 90's was when C++ got standardized and aggressively moved into C's turf a lot more.
The argument that C++ is slower because people might use it badly is... not even valid. You can't compare good code in language A with bad code in language B  :rolleyes: That's the kind of hyperbole that only Linus 'Arrogance' Torvalds can get away with.

#5312316 the dreaded "escort" quest

Posted by on 24 September 2016 - 08:43 AM

One of the most memorable COD missions is a reverse escort quest :D

#5312298 Get pixel's location

Posted by on 24 September 2016 - 06:14 AM

IIRC, any vertex after applying projection matrix, should report it pixel location at x, and y component right?

No, the projection matrix takes you to 4 dimensional pre-projective-divide NDC space, where xy>-w and xy<w. After dividing xy by w (which the GPU does for you during rasterization) you get -1<xy<1.

HOWEVER, yes, in the pixel shader, the SV_POSITION semantic implements a bit of magic and applies this divide by w and also applies the viewport matrix, resulting in xy pixel coordinates.

#5312297 Sharpen shader performance

Posted by on 24 September 2016 - 05:59 AM

A quick google turned up the fact that there's vendor specific hints in GLSL, such as #pragma optionNV (unroll all)... :(

Personally I'd recommend treating GLSL like JavaScript on the modern Web -- never directly write the files that will ship; always have them generated from some build system and potentially have the real source code in a better language altogether. That way you can have clean source code and ship ugly optimized GLSL files, such as with pre-unrolled loops.

#5312125 Gui Libraries?

Posted by on 23 September 2016 - 09:22 AM

Would be nice if someone tries to use it and give feedback, so I can improve it.

Separate the GUI library from the GUI rendering logic, and allow users of the library to replace the rendering logic -- look at other libraries such as Dear imgui, and librocket for examples.

Even if my engine is using OpenGL on a certain platform, I don't necessarily want middleware emitting GL function calls itself -- often you want the middleware to emit abstract commands that your engine can convert to GL calls itself (this can actually be more efficient in some cases!).
Also, GL definitely is not supported on all major gaming platforms.
MacOS supports GL2, but you can't mix GL2 and GL3/GL4 code together -- GL2 works in a legacy support mode. So GL2 middleware in a GL4 game is a bad idea.
Windows supports all GL versions, but there's three different implementations that you need to test against, so the vast majority of games on Windows use D3D as it has a single, stable implementation.
No game console supports GL -- so sticking with "just use GL everywhere" is saying that you don't care about people making console games (which is actually a lot of indies these days).

#5312070 After being an indie game developer I begin to doubt myself

Posted by on 23 September 2016 - 03:30 AM

Good news is that with 10-30 installs a day (600 per month) and $500 income per month, you have a pretty healthy ARPU value of over $1... You just need more users!

You might have to hire an advertising/marketing company to help you get more users. As long as the cost to acquire 1 user is under $1, then it will be worthwhile.

#5312053 Rise of the Tomb Raider cave exit effect

Posted by on 23 September 2016 - 01:27 AM

So basically using Reinhard I could achieve the same effect?
Thanks for your response.

Depending on which version, yes.
The basic version (which maps infinity to white) is:
color = color/(1+color);
And the version with an adjustable white point is:
color = (color*(1+color/(white*white)))/(1+color);
Either of these can be augmented to include an exposure modification right before tone-mapping, e.g.:

color *= exposure;                                 // Exposure
color = (color*(1+color/(white*white)))/(1+color); // Reinhard
return pow(color, 1/2.2);                          //linear -> sRGB approximation

If modelling a real physical camera system, you'd compute the exposure multiplier from the camera's ISO, F-stop/aperture and shutter time settings.
If using auto adaptation, you might use the average scene luminance to pick an exposure value that will center the image around middle grey:
e.g. exposure = 0.18/averageLuminance; or exposure = 0.18/exp2( averageLog2Luminance );
Or if manually tweaking your scenes, you can manually set the exposure variable to whatever you like.


However, Reinhard is a pretty unpopular tonemapping curve for games these days. Try some of these instead: http://filmicgames.com/archives/75


You will also need a bloom effect to get the over-exposed regions of the image to bleed into the darker surroundings.

#5312014 How to use Unit-Tests

Posted by on 22 September 2016 - 07:52 PM

When you write:

#define CATCH_CONFIG_MAIN  // This tells Catch to provide a main() - only do this in one cpp file
#include "catch.hpp"

Then this will declare a main function for your program that runs all of the "TEST_CASE" code -- therefore you should write your test cases in a completely seperate executable project than your game.
Unit tests are separate to the game and ensure that each small component works as expected. A test case should use the component in multiple ways, as many as feasible while testing every big of functionality. These unit tests should be runnable without running the actual game, to check if each small part of the code works as expected.

For testing that the state of your program is valid within the normal execution of your game, you should use an assertion library, not a unit testing one (you can/should do both though). Assertions test that everything is valid as part of normal code execution and help you catch crash bugs in the game itself -- before something goes wrong enough to cause a crash, it will/should cause an assertion failure first, which will allow you to break in a debugger and gather information on what went wrong.

#5311997 correct modeling for game developement (poly count)

Posted by on 22 September 2016 - 05:58 PM

but I heard that the animation section from maya is better.

The person who said it is a lair or a Maya user who is familiar with it's controls and not with Max.
Max is the best 3D software around, maybe over priced however it's still the best.

Isn't "best art software" a pretty subjective quality? I wouldn't call a difference in opinions to be a lie :P

#5311905 correct modeling for game developement (poly count)

Posted by on 22 September 2016 - 08:07 AM

Ideally, a triangle would cover roughly an 8x8 pixel area (or more), and at worst, around a 2x2 pixel area. Games tend to use several LODs of a model (levels of detail -- different versions of the model with more/less triangles) and the game will automatically pick the right LOD to use at the right distance to maintain a suitable triangle density.

I wonder Hodgman. Wheather this policy has any further, or even more serious, reasoning, but the redundant vertex stage processing.

You mean, is there a reason for these besides vertex processing costs? Yes, it's actually about pixel stage processing costs!!
Almost every GPU runs pixel shaders on a 2x2 "pixel quad" at a time. If your triangle cuts partially through this 2x2 pixel grid, then the edges will only partially fill those grid cells, but the pixel shader is still executed for the entire 2x2 area. For pixel-sized triangles, this means that you run the vertex shader 3 times for the pixel, plus you run the pixel shader 4 times!
Aside from the extra vertex-shading cost, small triangles can increase your pixel shader cost by 4 times!
The larger your triangles are, the better your "pixel quad efficiency" is.
As for the "should be larger than 8x8" recommendation -- the fixed-function rasterization hardware tends to operate on even larger pixel-quads, such as 16x16 or 32x32 pixels... and GPU shader cores tend to be SIMD processors that operate on 8-64 pixels at a time (or 2-16 "2x2 pixel quads" at a time).