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

GPUParticles3D not working on Meta Quest 2 with OpenGL renderer #83275

Closed
dsnopek opened this issue Oct 13, 2023 · 13 comments · Fixed by #83756
Closed

GPUParticles3D not working on Meta Quest 2 with OpenGL renderer #83275

dsnopek opened this issue Oct 13, 2023 · 13 comments · Fixed by #83756

Comments

@dsnopek
Copy link
Contributor

dsnopek commented Oct 13, 2023

Godot version

System information

Meta Quest 2, GL Compatibility Renderer

Issue description

When using the GL Compatibility Renderer, GPUParticles3D works fine in the editor. But when I deploy to the Meta Quest 2, nothing appears. (FYI, using the Vulkan Mobile renderer, it works fine.)

Looking through the issue queue, issue #82419 seemed similar, but the fix doesn't work: I disabled the shader cache, and it didn't fix the problem. In fact, on that issue, the GPUParticles3D worked the first time, whereas I've never seen it work. I have uninstalled, re-installed, and even changed the unique ID of the app (so Android treats it as a different app altogether) and this hasn't seemed to make disabling the shader cache do anything useful.

I haven't yet had a chance to try Godot 4.2-beta1 to see if the same problem exists there.

UPDATE: I just tried with Godot 4.2-beta1 (updating to the latest OpenXR loader plugin, of course!) and I'm still seeing the same thing.

Steps to reproduce

Setting up a Quest app has quite a few steps! So, best to try the MRP. :-) The MRP already has the shader cache disabled.

Minimal reproduction project

You'll need to do "Project" -> "Install Android Build Template..." before exporting to Quest

I've uploaded a Renderdoc capture I saved from running the 4.2 MRP.

@dsnopek dsnopek added this to the 4.x milestone Oct 13, 2023
@dsnopek dsnopek changed the title GPUParticles3D not working on Meta Quest 2 GPUParticles3D not working on Meta Quest 2 with OpenGL renderer Oct 13, 2023
@dsnopek
Copy link
Contributor Author

dsnopek commented Oct 15, 2023

I just tried with Godot 4.2-beta1 (updating to the latest OpenXR loader plugin, of course!) and I'm still seeing the same thing.

@clayjohn
Copy link
Member

Have you checked for errors?

@BastiaanOlij do you know if renderdoc works with the Quest2?

@dsnopek
Copy link
Contributor Author

dsnopek commented Oct 15, 2023

I'm not seeing any errors via adb logcat. Renderdoc does work - is there anything in particular I should be looking for?

UPDATE: Using renderdoc I just did a frame capture in an app where I should be staring at a GPUParticles3D. But given that rendering isn't really my area, I'm not sure where to look. :-) I clicked each draw call and looked at the texture viewer to try and identify which draw call should be drawing the particles, but I couldn't even narrow that down :-/ Ok, I was able to find which draw call is for the particles, by looking at the shader contents... I'm not sure what to do with that, though :-)

UPDATE 2: I take it back - I am seeing some errors via adb logcat! I'm not sure why I didn't see them in my testing earlier. And they do seem to point to the shader cache, although I have it disabled in the project settings:

10-15 11:49:53.410 24092 24143 I VrRuntimeClient: APP ACTIVITY CLASS = com.godot.game.GodotApp
10-15 11:49:53.720 24092 24143 E godot   : USER ERROR: Condition "f.is_null()" is true.
10-15 11:49:53.720 24092 24143 E godot   :    at: _save_to_cache (drivers/gles3/shader_gles3.cpp:624)
10-15 11:49:53.735  1147  1187 I ActivityTaskManager: Displayed com.snopekgames.GPUParticlesQuestTest2/com.godot.game.GodotApp: +2s245ms
10-15 11:49:53.986 24092 24143 E godot   : USER ERROR: Condition "f.is_null()" is true.
10-15 11:49:53.987 24092 24143 E godot   :    at: _save_to_cache (drivers/gles3/shader_gles3.cpp:624)
10-15 11:49:54.018 24092 24143 E godot   : USER ERROR: Condition "f.is_null()" is true.
10-15 11:49:54.018 24092 24143 E godot   :    at: _save_to_cache (drivers/gles3/shader_gles3.cpp:624)
10-15 11:49:55.666 24092 24143 E godot   : USER ERROR: Condition "f.is_null()" is true.
10-15 11:49:55.666 24092 24143 E godot   :    at: _save_to_cache (drivers/gles3/shader_gles3.cpp:624)

Why might this be happening with shader_compiler/shader_cache/enabled=false?

@dsnopek
Copy link
Contributor Author

dsnopek commented Oct 15, 2023

If I run my MRP on my Android phone (using the MobileVRInterface rather than the OpenXRInterface) it works fine, no matter how many times I run it (so it seems different than issue #82419, where they work the first time, but not subsequent times).

I'm seeing the same shader cache errors from my last comment in adb logcat, ex:

10-15 12:36:31.648 32452 32688 E godot   : USER ERROR: Condition "f.is_null()" is true.
10-15 12:36:31.648 32452 32688 E godot   :    at: _save_to_cache (drivers/gles3/shader_gles3.cpp:624)

So, those seem unrelated to the actual problem with the particles not rendering on the Quest, since the particles render fine on my phone?

@clayjohn
Copy link
Member

@dsnopek in renderdoc there is a tab for "pipeline". If you click on a particle draw call while in the pipeline tab you can select the first sub tab. It's called something like "vertex array" or something like that (all the way on the left, before vertex shader). Once in that tab you can inspect the data that goes in and out of the vertex shader and see if any bogus data is being used

@dsnopek
Copy link
Contributor Author

dsnopek commented Oct 15, 2023

Ok, so looking at the shader contents in Renderdoc and comparing it with the various glsl files in drivers/gles3/shaders/, I'm able to find the draw call for particles.glsl and particles_copy.glsl. And looking in the mesh viewer I'm able to find what I think is the meant to be the draw call for actually rendering the particles, because the mesh is a sphere (the only other shape in the scene is a cube).

@clayjohn:

in renderdoc there is a tab for "pipeline". If you click on a particle draw call while in the pipeline tab you can select the first sub tab. It's called something like "vertex array" or something like that (all the way on the left, before vertex shader). Once in that tab you can inspect the data that goes in and out of the vertex shader and see if any bogus data is being used

Looking at the "VTX" tab on the particles.glsl shader, I see one buffer going into 6 different slots - looking at those I see all zeros. I assume that's the input, I'm not entirely sure where the output is? If I switch to the "VS" tab, I see FrameData and MaterialUniforms which both look pretty sane based on how I configured the process material.

If I hop over to the particles_copy.glsl draw call, on the "VTX" tab its inputs look basically the same as the last one. If I switch to the "VS", it gets 4 uniforms that are all zeros except for "frame_remainder" which is just some random value between 0.0 and 1.0.

And finally on the one that seems to be intended to do tho actual rendering, in the "VTX" tab there's 5 slots, this time not all zeros! Unfortunately, I don't really know how to interpret this data. If I switch over to the "VS" tab, there's 4 uniforms and the SceneData and MultiviewData UBO's. Those all look roughly how I'd expect (of course, I can't really interpret matrices by eye balling them :-))

Sorry, I couldn't make more informed analysis of the data :-/

I've uploaded the capture I saved from Renderdoc, in case you (or someone else) can interpret the data better.

@dsnopek
Copy link
Contributor Author

dsnopek commented Oct 15, 2023

Alright, I've spent more time staring at the data! This time I ran the MRP with Renderdoc on my desktop using the MobileVRInterface, where it's working fine, and compared that data with what I'm seeing in Renderdoc on the Quest.

Looking at data in and out (I figured out how to find the output data :-)) of the draw call that appears to be the one doing the rendering, I'm seeing this locally:

Selection_081

Notice the last component of the instance_xform1 is a normal-ish sized number, and the gl_Position output are also fairly normal numbers.

And here's from the Quest 2:

Selection_080

Notice how the 4th component of instance_xform1 is a crazy huge number, and the gl_Position output are all Nan!

So, I think this qualifies as "bogus data" :-)

@dsnopek
Copy link
Contributor Author

dsnopek commented Oct 15, 2023

The weird data on the Quest seems to start with ALL the data (color, velocity_flags, custom, xform_1, xform_2 and xform_3) being fed into particles.glsl being all zeros. That leads to the output data to being almost all zeros (there's a couple of random non-zero numbers in there?).

And then on particles_copy.glsl it's getting that "almost all zeros data", and outputting those vec4's (that make up the instance transform matrices) with the 4th component having a giant negative number.

And from there to the NaNs when doing the rendering draw call.

I guess this needs to be tied back to code somehow, but I'm not sure I'll be able to do that :-)

@dsnopek
Copy link
Contributor Author

dsnopek commented Oct 15, 2023

Hm. Could the crazy huge negative number in the 4th component of those vec4's come from this code in particles_copy.glsl?:

#define FLT_MAX float(3.402823466e+38)

void main() {
	// Set scale to zero and translate to -INF so particle will be invisible
	// even for materials that ignore rotation/scale (i.e. billboards).
	mat4 txform = mat4(vec4(0.0), vec4(0.0), vec4(0.0), vec4(-FLT_MAX, -FLT_MAX, -FLT_MAX, 0.0));

And, if so, why doesn't the same thing show up when running this on my desktop?

Is there some floating-point number trick that's supposed to be happening here that doesn't work on Quest?

UPDATE:

Or, perhaps, it's the next line not evaluating to true on the Quest:

if (bool(floatBitsToUint(velocity_flags.w) & PARTICLE_FLAG_ACTIVE)) {

When that evaluates to true, it'll set txform to a saner value that should actually lead to the particles being shown!

@dsnopek
Copy link
Contributor Author

dsnopek commented Oct 15, 2023

I did another capture with Renderdoc on the Quest 2, and got different results than the saved capture I've been digging deep into. :-/

In this one, I'm seeing all zeros going into particles.glsl and particles_copy.glsl. It's not showing me the output values (it says "Error obtaining vertex data via transform feedback").

But when it gets to the actual rendering of the particles, the instance_formX vec4's have all zeros in them, rather than the 4th component being -INF. And on the output side, instead of gl_Position being all NaN, they are all the exact same point (although, it's a fairly normal looking point, within ~1-2 meters from the origin).

So, in conclusion, I have no idea what's going on. :-) I'm going to put this down for now.

@BastiaanOlij
Copy link
Contributor

I haven't looked into how GPU particles work on OpenGL but could this be the same issue we had with updating vertex buffers for animations?

I.e. the system spitting the dummy because our framebuffer is still current and our framebuffer being multiview, even thought the framebuffer is irrelevant with these functions?

You're probably aware @dsnopek but just in case, Meta has a special version of renderdoc with a number of extra features build in specific for Adreno GPUs, worth using.

@dsnopek
Copy link
Contributor Author

dsnopek commented Oct 21, 2023

While digging into issue #83733, I noticed something interesting.

When I load up a scene that uses GPUParticles3D in the Oculus browser, it works just fine! I can see it running over and over again in the 2D window. However, when press the "Enter XR" button to switch to WebXR, then the particles are no longer rendered.

So, it seems to be something specific to rendering the particles when in multiview. However, this doesn't happen when rendering in multiview with the MobileVRInterface on my desktop computer. So, it seems to be a bug that only happens on the Quest, but only when rendering in multiview.

I.e. the system spitting the dummy because our framebuffer is still current and our framebuffer being multiview, even thought the framebuffer is irrelevant with these functions?

Yeah, based what I learned above when trying this with WebXR, that seems possible. Perhaps the particle shaders that do the actual particle simulation are getting thrown off by running in multiview?

You're probably aware @dsnopek but just in case, Meta has a special version of renderdoc with a number of extra features build in specific for Adreno GPUs, worth using.

Yep, I'm aware, but their fork only has a Windows build and I do 99.99% of my development on Linux, so I haven't tried using it when debugging this issue.

@dsnopek
Copy link
Contributor Author

dsnopek commented Oct 21, 2023

Based on @BastiaanOlij's suggestion that this problem could be just like PR #79772, I attempted to apply the same solution as used in that PR and... it fixes it!

I just posted PR #83756 with the fix

@akien-mga akien-mga modified the milestones: 4.x, 4.3, 4.2 Oct 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants