godot icon indicating copy to clipboard operation
godot copied to clipboard

Tearing when using UV to access an array of sampler2d's

Open WaveyGames opened this issue 1 year ago • 4 comments

Tested versions

Reproducible in: 4.3stable and 4.4dev3

System information

Godot v4.3.stable - Windows 10.0.26100 - Vulkan (Forward+) - dedicated AMD Radeon RX 6600 (Advanced Micro Devices, Inc.; 32.0.12011.1036) - 12th Gen Intel(R) Core(TM) i3-12100F (8 Threads)

Issue description

I wrote a short shader to have a mesh sample one image when UV.x < 0.5, and another image otherwise. Here it is:

shader_type spatial;
uniform sampler2D[2] images : source_color;

void fragment() {
	ALBEDO = texture(images[int(step(0.5, UV.x))], UV).rgb;
}

But when you put it on a mesh and fill the array with two different images it looks something like this: tearing_showcase

I expected a clean line in the middle separating the two images, like this: image

The code for the above:

shader_type spatial;
uniform sampler2D[2] images : source_color;

vec3 get_color(int index, vec2 uv) {
	if(index == 1) {
		return texture(images[1], uv).rgb;
	}
	return texture(images[0], uv).rgb;
}
void fragment() {
	ALBEDO = get_color(int(step(0.5, UV.x)), UV);
}

Steps to reproduce

After you open the MRP, the issue should be visible immediately.

Minimal reproduction project (MRP)

MRP_bug.zip

WaveyGames avatar Oct 18 '24 07:10 WaveyGames

I can't reproduce it on 4.3. Possibly hardware or driver specific?

Godot_v4 3-stable_win64_42RzYf4qGx

Godot v4.3.stable - Windows 10.0.19045 - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1660 Ti with Max-Q Design (NVIDIA; 32.0.15.5612) - AMD Ryzen 7 3750H with Radeon Vega Mobile Gfx (8 Threads)

tetrapod00 avatar Oct 18 '24 08:10 tetrapod00

This is a pretty typical artifact from not indicating the access is not uniform explicitly in the shader.

https://anki3d.org/resource-uniformity-bindless-access-in-vulkan/

One additional piece to the puzzle is the NonUniform SPIR-V decoration which is exposed via nonuniformEXT in GLSL and NonUniformResourceIndex() in HLSL.

I don't believe access to this modifier is exposed in GDShader. It might take a while to get a feature like that added and it's a pretty highly technical modifier to expect people to know about it. I'd argue this is a bit more of a documentation issue.

My suggestion would be you attempt some other way to do this. Try just sampling both of the images and mixing based on the step UV value. That should guarantee the access to both samplers is uniform.

DarioSamo avatar Oct 18 '24 12:10 DarioSamo

I can't reproduce it on 4.3. Possibly hardware or driver specific?

Yes, AMD is more prone to showing artifacts when non uniform access is not specified.

DarioSamo avatar Oct 18 '24 12:10 DarioSamo

Is there a downside to having the Godot shader compiler always insert the nonuniformEXT decorator for array indexing of textures? According to the article:

If an implementation doesn’t care then it will simply ignore it [nonuniformEXT].

stuartcarnie avatar Oct 18 '24 20:10 stuartcarnie

My suggestion would be you attempt some other way to do this. Try just sampling both of the images and mixing based on the step UV value. That should guarantee the access to both samplers is uniform.

I found a way around the issue using a bunch of step functions, since the original problem is sampling from a couple more textures, and the result looks great! Thanks!

WaveyGames avatar Oct 19 '24 05:10 WaveyGames