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

Fix crash GPU particles on ios #89072

Closed
wants to merge 1 commit into from
Closed

Conversation

Arthas92t
Copy link
Contributor

@Arthas92t Arthas92t commented Mar 2, 2024

This will fix crash engine when use GPU particles on ios, tested on 4.0.x, 4.1.x, 4.2.x (issue #72469). With this fix both 3D and 2D GPU particles won't crash on ios but only 2D particles work (on 4.1.2 and 4.2.1 require this #88745 which merged to master branch or it won't show anything).
For 3D GPU particles on ios don't show anything, seem like there is another bug when core run into restart state of particles.glsl and code won't run if xform[3].xyz and out_velocity_flags.xyz == vec3(0.0). So if you add a simple code to prevent it become zero then 3D GPU particles will work on ios
image

	if (restart && particle_active) {
#CODE : START
        if(length(out_velocity_flags) == 0.0)
            out_velocity_flags.xyz = (emission_transform * vec4(0.0, 0.0001, 0.0, 0.0)).xyz;
        xform[3].xyz += out_velocity_flags.xyz * 0.0001;
	}

but I don't fully understand all those shader code in particles.glsl so may need someone else who fully understand it to make a better fix

@clayjohn
Copy link
Member

clayjohn commented Mar 2, 2024

Thank you very much for investigating this and confirming that this change was all thats needed to get particles working on iOS. The same code is in #88816 which is a very similar PR with the goal of getting particles working on Adreno 3XX devices (old Android devices basically). So it seems the two of you struck upon the same issue!

#88816 Is still a work in progress, so it may be worthwhile to merge your PR first to get the fix in ASAP. But if #88816 is almost finished, I think it makes sense just to merge #88816 and close this PR.

@Arthas92t
Copy link
Contributor Author

Ok, i got it. Thank you

@clayjohn
Copy link
Member

clayjohn commented Mar 2, 2024

@Arthas92t For GPUParticles3D, Is your code fixing a crash, or is it fixing the particles not appearing? If it's fixing a crash, then I have no idea what is going on, but if it is fixing the particles just not appearing, then I have some theories we can discuss further if you want

@Arthas92t
Copy link
Contributor Author

Arthas92t commented Mar 2, 2024

@clayjohn this commit only fix crash issue.
but this one fix 3DGPUParticles isn't appearing:
image
but like i said, i don't think it a good way to fix it.

@clayjohn
Copy link
Member

clayjohn commented Mar 2, 2024

@clayjohn this commit only fix crash issue. but this one fix 3DGPUParticles isn't appearing: image but like i said, i don't think it a good way to fix it.

I agree that there is probably a better fix. I wonder if what is happening is that velocity flags isn't getting cleared correctly, so in_velocity_flags contains garbage values which get carried through to subsequent passes.

Could you try testing with a custom Particles Process material where you replace the following lines with something constant?
I.e. convert the ParticlesProcessMaterial to a ShaderMaterial and replace:

VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;
VELOCITY += EMITTER_VELOCITY * inherit_emitter_velocity_ratio;

with

VELOCITY = vec3(0.0, 0.01, 0.0);

This should result in a particle that slowly moves up.

My theory is that velocity_flags passes a bad value to out_velocity_flags. So by overwriting VELOCITY you can ensure that out_velocity_flags is okay.

If my code replacement works above, then we need to investigate why out_velocity_flags isn't getting properly cleared.
It should be happening here:

if (clear) {
out_color = vec4(1.0);
out_custom = vec4(0.0);
out_velocity_flags = vec4(0.0);
} else {
out_color = color;
out_velocity_flags = velocity_flags;
out_custom = custom;
xform[0] = xform_1;
xform[1] = xform_2;
#ifdef MODE_3D
xform[2] = xform_3;
#endif
xform = transpose(xform);
flags = floatBitsToUint(velocity_flags.w);
}

@Arthas92t
Copy link
Contributor Author

Arthas92t commented Mar 3, 2024

@clayjohn this commit only fix crash issue. but this one fix 3DGPUParticles isn't appearing: image but like i said, i don't think it a good way to fix it.

I agree that there is probably a better fix. I wonder if what is happening is that velocity flags isn't getting cleared correctly, so in_velocity_flags contains garbage values which get carried through to subsequent passes.

Could you try testing with a custom Particles Process material where you replace the following lines with something constant? I.e. convert the ParticlesProcessMaterial to a ShaderMaterial and replace:

VELOCITY = (EMISSION_TRANSFORM * vec4(VELOCITY, 0.0)).xyz;
VELOCITY += EMITTER_VELOCITY * inherit_emitter_velocity_ratio;

with

VELOCITY = vec3(0.0, 0.01, 0.0);

This should result in a particle that slowly moves up.

My theory is that velocity_flags passes a bad value to out_velocity_flags. So by overwriting VELOCITY you can ensure that out_velocity_flags is okay.

If my code replacement works above, then we need to investigate why out_velocity_flags isn't getting properly cleared. It should be happening here:

if (clear) {
out_color = vec4(1.0);
out_custom = vec4(0.0);
out_velocity_flags = vec4(0.0);
} else {
out_color = color;
out_velocity_flags = velocity_flags;
out_custom = custom;
xform[0] = xform_1;
xform[1] = xform_2;
#ifdef MODE_3D
xform[2] = xform_3;
#endif
xform = transpose(xform);
flags = floatBitsToUint(velocity_flags.w);
}

Sorry, maybe my code make you confuse.
Actually, particles will work if i add a line to init xform[3]:

xform[3].xyz += out_velocity_flags.xyz *0.0001; //or some thing but i choose a small out_velocity_flags value

but there is an exception in case velocity == 0.0 too so i need to add another code to check that case.
So the problem isn't out_velocity_flags but my fix not work with out_velocity_flags == vec3(0.0)
Problem may come from restart_postion code.
And i just test your suggest, it does not work too

@Arthas92t
Copy link
Contributor Author

Arthas92t commented Mar 3, 2024

@clayjohn, i just make a test with particles_process_material.cpp and change

code += "vec3 calculate_initial_position(inout uint alt_seed) {\n";
code += " float pi = 3.14159;\n";
code += " float degree_to_rad = pi / 180.0;\n";
code += " vec3 pos = vec3(0.);\n";
if (emission_shape == EMISSION_SHAPE_POINT) {
code += " pos = vec3(0.);\n";
}

to :

	code += "vec3 calculate_initial_position(inout uint alt_seed) {\n";
	code += "	float pi = 3.14159;\n";
	code += "	float degree_to_rad = pi / 180.0;\n";
	code += "	vec3 pos = vec3(0.0, 0.001, 0.0);\n";
	if (emission_shape == EMISSION_SHAPE_POINT) {
		code += "	 pos = vec3(0.0, 0.001, 0.0);\n";
	}

then it work. But i dont like to change that file cause old particles shader saved file won't have update permanently. And i still dont understand why xform[3] == vec3(0.) cause this issues

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

Successfully merging this pull request may close these issues.

3 participants