Weird GPU output on GTX 780 with updated drivers?

Hi, it just so happens that recently, I got my hands on a gaming computer with a GTX 780 2GB card and just realized my project looks like this on that computer! Any idea what could cause this on GTX high-end cards? I must specify that the top right yellow bar bounding rectangles and fillings are textures that are all part of the same texture atlas I use for the images that F*** up as you can see in the middle of the screen and at the bottom. Please throw at me all ideas you get abou what could cause this, thx:

It’s supposed to look more like this (Except for the orange message on the top/left corner) :

Thx…

AWWW F*** DAMNIT XD … The images are in reversed order and I cannot edit my post for an unknown reason. Sorry :stuck_out_tongue:

It looks like some kind of maybe Z-fighting because even when the camera doesn’t move, on certain angles, it flickers very fast, but it doesn’t always flicker. Also, here is another screenshot with stuff picked up in the inventory, as you can see, the pickup items (plants) are displayed correctly and the little green bars underneath (which are part of the same texture atlas as the parts that flicker) seem correctly drawn too! I mean, the only 2 parts that are flickering are what I displayed in the first post… that’s mind boggling.

You see the 3rd box in the inventory line that flickers, the black and white little image that appears in that box is the FULL INVENTORY image that flickers on the first post I did. It appears there even if the full inventory is not open, which indicates to me it looks like a vertex buffer mismatch or something because it draws a part of the texture it’s not supposed to.

Hm, i have a 780 too running with the current gl4.5 beta driver…

Never noticed such issues on my side. If you want i can test it on my side. If you don’t want to send me the game, just make a small test case showing the issue.

Its a bit strang that only the overlays show the issue however

Hey! Well actually, I don’t mind at all sending you the compiled game just to confirm if another GTX 780 setup does the same thing or not, that would be nice to begin with… Thank you for trying to help me. Also when you say it’s only overlays, it’s not ALL overlays, as you can see the HAND CURSOR and text/bars at the top right corner all display 100% perfectly, no flicker or nothing, all the time, no matter the camera orientation. Also, the yellow bars are textures right from the same texture atlas as the ones which F*** up. That’s mind boggling. I have also tried earlier to send them FARTHER in the Z plane, because they’re at like Z=1.001 and I thought maybe nVidia cards don’t like when stuff is too close, but then again, even if I put Z=1.1 it’s exactly the same, plus the yellow bars at the top right corner are also very close and they never flicker… WTF?

Whenever I see this kind of thing it almost always ends up being missing vertex data or missing uniforms that the shader expects. ie: the driver is free to insert whatever garbage there that it feels like. nVidia is generally pretty nice about zeroing out things that aren’t set but some cards won’t… and maybe newer versions don’t either.

Something to check at least. If you are using a custom shader for those overlays (or even if not) try commenting bits of them out or just setting gl_FragColor to red and see if it works and then work backwards from there.

At least it happens consistently for you.

Good thing is, it is happening also on my 780. So its at least not a hardware failure of your card. But i have to say that all other games works fine on my side, and also my jme projects don’t show that issue…

Are you using custom shaders?

I experienced similar issues when in my jogl project when i missed to upload a texture to shader (basically what paul said). It seems that the gpu does then read from some random place in the vram. (Probably not random, but starting from 0) The output of course is mostly garbage, but actually under specific scenarios it has drawn an actual unbound texture.

My driver version is: 340.65

@pspeed said: nVidia is generally pretty nice about zeroing out things that aren’t set but some cards won’t… and maybe newer versions don’t either.

Yeah, but surprisingly, it ONLY happens on the GTX 780 so far. I have had friends try it with a bunch of different cards and it just never happened before, except for the GTX 780. I have a Radeon R9 270X card and let me tell you I have seen F**** strange drawing bugs before and fixed them all, but I have never seen THIS with my card tough.

@pspeed said: try commenting bits of them out or just setting gl_FragColor to red and see if it works and then work backwards from there.

Interesting, I’ll try it and see what I come up with, but I think too it has something to do with the vertex buffers, because it looks like it’s drawing another portion of the texture atlas where it should not. What’s F***'ed up about it is that the only 2 quads that are doing it are coded exactly the same as all the yellow bars at the top right, which are using the same material and same texture atlas! So why are those simple 2 quads doing this and nothing else using the same material… :?

@zzuegg said: Good thing is, it is happening also on my 780. So its at least not a hardware failure of your card.

Are you using custom shaders?

I experienced similar issues when in my jogl project when i missed to upload a texture to shader (basically what paul said). It seems that the gpu does then read from some random place in the vram. (Probably not random, but starting from 0) The output of course is mostly garbage, but actually under specific scenarios it has drawn an actual unbound texture.

My driver version is: 340.65

Thank god, it’s repeatable on all same hardware, I’m actually happy to read this, thanks.

The one I tested my project with reports as: NVIDIA 344.11… which is a newer driver and still doing it, so it must be something in the code for sure because it’s doing it on all GTX 780 but what is it that this card hates so much for those 2 quads that make them draw garbage where all other GPU in the world don’t!!

Look at all the cards I have tested my project with and it NEVER happens, the drawing is flawless, including a couple older GTX models:

IntelÂŽ HD Graphics / 2.1.0
AMD Radeon HD 5800 Series
GeForce GTX 750 Ti/PCIe/SSE2 / 4.4.0
AMD Radeon R9 200 Series
IntelÂŽ HD Graphics / 3.1.0
AMD Radeon HD 7900 Series
GeForce GTX 645/PCIe/SSE2 / 4.3.0
GeForce GTS 250/PCIe/SSE2 / 3.3.0
IntelÂŽ HD Graphics Family / 3.0.0
ATI Radeon HD 5670 / 4.2.11762 Compatibility Profile Context
GeForce GT 130M/PCIe/SSE2 / 3.3.0
AMD Radeon R7 200 Series / 4.3.12618 Compatibility Profile Context 13.251.0.0
ATI Radeon HD 5800 Series / 4.2.12217 Compatibility Profile Context 12.104.0.0

I almost got it working guys. Turns out it has NOTHING to do with the vertex buffers or z-fighting at all! I have (totally randomly) came upon wondering why that little black and white image in the currently active inventory slot is showing. That image comes fourth (ID:3) in the texture atlas. It should be the next texture – yellow box border – showing instead (ID:4)… so I took a look in the GLSL shader and could not understand why it seemed like drawing the texture that comes BEFORE the actual texture that’s supposed to be drawn.

Well… it turns out I’ve been passing the texture ID as a float and that GTX card --THE ONLY ONE YET-- has precision issues or maybe the driver does – I don’t know – preventing it from reading a whole number, effectively missing maybe 0.000001 or so, rendering a “1” as “0.999999” so when I cast (int) on it at some point, it gives 0 instead of 1! (or 3 instead 4 etc…)

By using int(ceil(tex_id)) it outputs the right texture. I think I should go back 4-5 months ago and pass this value as an integer instead of a float, it would be more efficient CPU wise and also less frustrating for precision round off errors like this!

It has a small glitch still (look in the full inventory in the black area, there are missing lines) but I think this too has something to do with the GTX card reading 1 pixel off or something… I’ll play with it a little and probably fix it easily today.

Thanks for your help guys! Hope my little story helps somebody with a strange texture problem that only happens on GTX 780 cards! :stuck_out_tongue:

OK just fixed it completely by using int(round(tex_id)) :stuck_out_tongue:

So basically, good thing to remember: float precision on GTX 780 F**** sucks. 1 can be 0.999999 or 1.000001, not sure what exact precision it has, but by rounding it, it works fine and still runs faster FPS-wise than my R9 270X card, so I’m quite happy about it. I don’t think I could have passed it as an integer in the end, because I’m hacking the VBO and sending it through the SIZE buffer, since it has a small (1) array component.

@.Ben. said: OK just fixed it completely by using int(round(tex_id)) :P

So basically, good thing to remember: float precision on GTX 780 F**** sucks. 1 can be 0.999999 or 1.000001, not sure what exact precision it has, but by rounding it, it works fine and still runs faster FPS-wise than my R9 270X card, so I’m quite happy about it. I don’t think I could have passed it as an integer in the end, because I’m hacking the VBO and sending it through the SIZE buffer, since it has a small (1) array component.

What version do specify for your shader in the j3md file?

Hi Paul, thanks for your interest. It’s GLSL100, does that matter? Would a newer GLSL version take care of this VERY RARE float precision problem? As it sits right now, it works flawlessly, even on the GTX 780.

@.Ben. said: Hi Paul, thanks for your interest. It's GLSL100, does that matter? Would a newer GLSL version take care of this VERY RARE float precision problem? As it sits right now, it works flawlessly, even on the GTX 780.

GLSL100 is essentially “no version” and lets the driver do whatever the hell it wants, basically. It throws nVidia into compatibility mode on most cards in which it will kindly accept all kinds of crap (like 0 instead of 0.0 and so on).

I’ve taken to putting GLSL110 in all of my shaders. The upside is that I get a stricter syntax check pinned to a specific (real) version. The only downside is that my shaders won’t work on Android by default. I’d have to add another technique block or whatever.

1 Like

Well Paul, despite the fact that the GLSL110 definition forced me to make all hardcoded integers end with .0 (like for instance instead of 128, I had to rewrite it to 128.0) for it to shut up about the variable type cast conversion that is unacceptable to GLSL110 and that it crashed because the round() function does not seem to exist under that version of GLSL, else than that, it made absolutely no difference at all in graphics which means it’s really the floating point precision that is lacking under the GTX 780 card.

I reverted the round() to a floor() and then tried a ceil() just to prove that the float precision is really the culprit here for the GTX 780 card, same weird half-textured gibberish because of unprecise floats (sometimes above 1, sometimes under 1):

Thanks for letting me know GLSL100 is risky… and letting me know it’s the only GLSL version that works on Android, but as of today, that’s also the only version that works on all GPUs tough! And I took the material definition from the Unshaded material from the current JME3 stable version, so I mean, it can’t be that bad to use it now can it?

It’s not the only GLSL version that works on android. It’s just that if the only version you specify is GLSL110 then it definitely won’t work on android. GLSL110 will work on all desktop openGLs.

As to your 128 versus 128.0 error, I’d have to see the line. GLSL is incredibly picky about floats and integers.

For example:
int i = 0;
should be fine
but
float i = 0
is definitely not. If you do that then some cards will complain even if you left it at GLSL100.

The floats are passed as the SIZE vertex buffer which is a 1-dimensional float array.

It comes in the fragment shader like this:

[java]
varying float tex_id; // Coming from the vertex shader untouched as: attribute float inSize;
const float atlas_height = 1273.0;

vec3 top_width_height = vec3(atlas_height, 0.0, 0.0); // ID #0: Transparent
switch(int(round(tex_id))){
case 0:
top_width_height = vec3(atlas_height, 0.0, 0.0);
break;
case 1:
top_width_height = vec3(atlas_height - 583.0, 439.0, 583.0);
break;
case 2:
top_width_height = vec3(atlas_height - 651.0, 662.0, 68.0);
break;
case 3: // …
[/java]

See the round there? This is mandatory, else it will sometimes draw the texture ID:0 instead of ID:1 as you can see in the previous screenshots… but with the round, it’s always perfect.

@.Ben. said: Well Paul, despite the fact that the GLSL110 definition forced me to make all hardcoded integers end with .0 (like for instance instead of 128, I had to rewrite it to 128.0) for it to shut up about the variable type cast conversion that is unacceptable to GLSL110
@pspeed said: As to your 128 versus 128.0 error, I'd have to see the line. GLSL is incredibly picky about floats and integers.

For example:
int i = 0;
should be fine
but
float i = 0
is definitely not. If you do that then some cards will complain even if you left it at GLSL100.

In other words your “hard coded ints” weren’t “hard coded ints” unless they actually were ints. Otherwise, they were “hard coded floats” that were in an invalid format that would break on Macs and many ATI cards that properly adhere to the spec even in GLSL100.

It’s not the only thing that GLSL100 will let you get away with on nVidia cards that will break in other situations.

I wasn’t talking about the round()… that just seems like better math, to me.

“varying float tex_id”

The “varying” could make it do all kinds of strange things as it’s interpolated over the shape.

You’re skipping topics a lot and you lost me with this post. I don’t understand where this is going because as stated, the issue is completely solved with a round() to actually accomodate all precision errors that only GTX 780 cards seem to have. You’re saying it won’t work on ATI cards but it does work flawlessly on an iMac 21" 2009. It also works flawlessly on all other GPU, including many AMD cards, listed in this previous post: http://hub.jmonkeyengine.org/forum/topic/weird-gpu-output-on-gtx-780-with-updated-drivers/#post-296920

But I’d be interested to understand what you’re trying to explain to me, so please refine your answer: If VARYING could be yet another cause of this GTX 780-only float precision problem: what do you want me to do differently than passing the attribute with VARYING? BTW, this is the UNSHADED shader that comes with JME3, I only added a switch case to the fragment shader to render a texture atlas part, that’s it. It was already written with “varying” to pass attributes to the fragment shader like:

varying vec2 texCoord1;
varying vec2 texCoord2;
varying vec4 vertColor;

You can see it in the UNSHADED shader that comes with the stable release of JME3.

So what should I do differently then? And please if somebody has another Mac model, PLEASE try it to confirm if this breaks as it is now. Thanks.

You posted a bunch of stuff in one post that said you fixed it but also implying that you were upset that you had to put .0 on the end of your “integers”, etc. when using GLSL110.

I responded saying essentially that you shouldn’t have to put .0 on the end of your integers and so they must not have been integers. You absolutely DO have to put .0 on the ends of any floats and that absolutely WILL break on some cards (especially on Macs) even with GLSL100.

You responded talking about round() which had nothing to do with what I was saying.

So I posted your original quote that I was responding to that had nothing to do with round() along with the quote of my response that had nothing to do with round(). I added an explanation on what I was saying.

I also mentioned that the round() method is probably better math because the ‘varying’ could do slight precision things during interpolation and if the difference between 0.9999999 and 1.0 is important, ie: they should both be 1.0 then the case was incorrect in the first place and your code is more robust/better/gooder now.

Your code should work universally now and it’s all the better for it.

Although, note that if you have a value that should not vary over the triangle then you can use the “flat” interpolation qualifier and avoid any interpolation being done. It may or may not be another way to fix your issue… and if as I suspect the value really doesn’t vary over the triangle then it’s “more correct”.

Otherwise, if the value does vary over the triangle then the results you get were expected and you were lucky before… but I don’t think that’s the case based on the fact that it’s a tileID.

Example of ‘flat’ interpolation:
flat varying float tileId;

And if that still fails without the round() then yes there is something extremely screwy with that card. :slight_smile:

Edit: do note that forcing flat would also hide mesh errors if you accidentally had more than one tileId in the triangle’s vertex attributes… but it seems harmless.

Also note that ‘doing the math’ if possible instead of the switch/case might be a better technique overall. ie: find the texture coordinates by multiplying by tile size. Then again, I don’t understand the full extend of what you are doing and why a tileId is preferable to just texture coordinates in the first place.