Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UV offsetting in mobile makes that texture hangs and blocky after few minutes #43505

Closed
himaghnam opened this issue Nov 13, 2020 · 13 comments
Closed

Comments

@himaghnam
Copy link

Godot version:
Godot 3.2.4 although it did happen in the previous versions too.

OS/device including version:
Android 9, Asus max pro m2

Issue description:
When I offset tileable texture it starts to hang in mobile and even the texture becomes blocky. It only happens on mobile and only to that texture, I mean the game works fine.

shader_type canvas_item;

void fragment() {
	vec3 c = vec3(UV, 0.0);
	float divide = 5.0;
	float t = mod(TIME/divide,divide);
	vec2 uv = vec2(c.x, c.y+t);
	vec4 _tex = texture(TEXTURE, uv.xy);

	COLOR.rgb = _tex.rgb;
}

Steps to reproduce:

Minimal reproduction project:

@Calinou
Copy link
Member

Calinou commented Nov 13, 2020

This is very likely to be a precision issue, especially if it only occurs on mobile. Try enabling high-precision floats in the Project Settings as per #33646.

@himaghnam
Copy link
Author

Nope, it's still the same, turning on high-precision floats does not solve this issue

@lawnjelly
Copy link
Member

lawnjelly commented Nov 13, 2020

This is a common on android and many devices do not offer high precision in fragment shaders, many have only 10 bit precision. You haven't said whether this is GLES2 or 3, but the issue probably still stands .. I've seen it more on GLES2 devices.

As a general rule, I would recommend not touching texture coordinates in fragment shaders for low end mobile. There are two reasons:

  • On some hardware this will drop down to a lower precision path
  • This prevents readahead of the texture, slowing performance

This typically manifests as blocky point filtering looks and performance dropping off a cliff. It isn't something Godot can do anything about, it is a hardware limitation. TIME could also be problematic because as time increase, the precision available can decrease in the variable .. although I believe there may be a wraparound at some point.

Although we should put in some mechanisms to query low, medium and high precisions at runtime and so allow the user to switch shaders. We have also discussed that we maybe should put warnings up during export when users export such shaders to android etc.

See e.g. #32813 for more info.

@lawnjelly lawnjelly added discussion and removed bug labels Nov 13, 2020
@himaghnam
Copy link
Author

It happens in both GLES2 and 3 but using these does not seems to give me such issues.
I tried highp float and vec2 and vertex() too, but it seems like - mod(uv,1.0) - solves the problem

shader_type canvas_item;

void fragment() {
        float divide = 5.0;
        vec2 uv = UV;
	uv.y += mod(TIME/divide,divide);
	vec4 _tex = texture(TEXTURE, mod(uv,1.0));
	COLOR.rgb = _tex.rgb;
}

@lawnjelly
Copy link
Member

lawnjelly commented Nov 14, 2020

Ah that is interesting, it may have been due to accessing texture outside the 0 - 1 range in your case. Was it a non power of 2 size texture by any chance?

The GPU is Adreno 512:
https://opengles.gpuinfo.org/displayreport.php?id=2565

However it does have extension GL_OES_texture_npot which suggests it should be able to do npot...

@himaghnam
Copy link
Author

himaghnam commented Nov 14, 2020

Nope, the texture is 64x64 tiled across 368x640 res window size using TextureRect node at FullRect setting

@lawnjelly
Copy link
Member

lawnjelly commented Nov 14, 2020

In that case I'm not sure what exactly is triggering it. 🤔

Just to clarify when you say 'starts to hang', what do you mean. Do you mean the app freezes periodically?

You could probably pin it down further by tweaking the shader, but it may be a wild goose chase. Unless it is a generic problem in our shader compiler to GLSL (say something to do with that intermediate vec3 c), then it may well be a quirk of that particular GPU. It may reveal something we can improve though, so it is up to you whether you want to spend time investigating.

It may be that using mod in the UVs before looking up the texture is recognised in the driver, or it may be that it performs better without receiving values outside 0 to 1 range, or it may be it hits a pathological situation. Or precision of one of the intermediates? I'm just wildly guessing at this stage though. 😁

@himaghnam
Copy link
Author

What i mean by "hang" is that only the texture with shader(not the whole game) starts to slow down and and becomes blocky per pixel(i guess) and the size of those block keeps increasing as the time goes.
It also happens in visual shader and in old godot version.

@lawnjelly
Copy link
Member

This does sound exactly as I've seen before when GPUs enter a slow path. No idea why this might be happening with the first variation of the shader and not the second though.

@Calinou
Copy link
Member

Calinou commented Apr 10, 2022

Closing, as decreasing rendering/limits/time/time_rollover_secs to 30 in the Project Settings should fix this issue. Using a higher value like 60 might work, but it may still exhibit noticeable precision artifacts depending on what you're doing.

You'll have to make sure your shader's animation performs a full loop within time_rollover_secs to prevent the time rollover from being visible to the user. If you really need a higher time rollover on mobile, you can enable Enable High Float.Android in the Project Settings, but this has a significant performance penalty.

@lawnjelly
Copy link
Member

lawnjelly commented Apr 11, 2022

I'm not sure we have established that it is TIME that is causing the blockiness / slowdown here. As I said above, touching UVs on some low end GPUs will cause this by causing the GPU to enter a slower, less precise "limp mode", irrespective of whether TIME is used in calculations. They are related issues, but not the same.

"Dependent texture read" I think is one of the names for this:
https://docs.imgtec.com/Profiling_and_Optimisations/PerfRec/topics/c_PerfRec_texture_sampling.html#ariaid-title4

@Calinou
Copy link
Member

Calinou commented Apr 11, 2022

I'm not sure we have established that it is TIME that is causing the blockiness / slowdown here.

The fact that this occurs over time (and not initially) makes me think this is due to TIME precision issues. If UV was the culprit, then the texture would look blocky immediately on startup. (This assumes "limp mode" occurs as soon as you move UV by a tiny amount.)

@lawnjelly
Copy link
Member

Ah yes you are likely to be correct, OP later says that the "hang" is only for the texture concerned (maybe they mean this texture updates less frequently).

When you get this limp slowdown it generally affects everything I think. But you can still potentially get the GPU kicked into lower precision mode which can then in turn make the TIME issue more pronounced. It would be nice to see this confirmed by the OP, but the issue is old so this is unlikely .. so agree is probably worth closing and watching for any newer related issues. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants