cpt-max / MonoGame

One framework for creating powerful cross-platform games.
http://www.monogame.net
Other
26 stars 5 forks source link

Indirect drawing does not work at all. No errors but no visible result either. #4

Open k4G17eYWI opened 3 months ago

k4G17eYWI commented 3 months ago

Prerequisites

MonoGame Version

MonoGame.Framework.Compute.Android 3.8.2

Which MonoGame platform are you using?

MonoGame Android Application (mgandroid)

Operating System

Android

Description

I fought a couple of days trying to get my indirect draw shader work on Android device and gained no result. So I've modified your Android example from a direct to an indirect drawing and got the same - nothing is being drawn. Unmodufied sample project works as it should.

this is my modified code:

args.SetData(new DrawInstancedArguments()
{
    InstanceCount = (uint) particleCount,
});
GraphicsDevice.DrawInstancedPrimitivesIndirect(PrimitiveType.PointList, args);

Steps to Reproduce

Deploy project from attachments to an Android device

Minimal Example Repo

No response

Expected Behavior

The example draws particles

Resulting Behavior

The example draws nothing but UI

Files

MonoGame-Shader-Samples-Mobile-compute_gpu_particles.zip

k4G17eYWI commented 3 months ago

Just noticed that I have errors in a console in such case: "there is no vertex array object bound" and in Logcat: "GL Exception occurred during RunIteration GL.GetError() returned 1282"

cpt-max commented 3 months ago

I tried this on Android, I can confirm it. GL.DrawElementsIndirect outputs "there is no vertex array object bound". MonoGame doesn't use vertex array objects currently, only vertex buffer objects. I'm wondering if using a VAO would make it work.

k4G17eYWI commented 3 months ago

But if I replace this one line, it works on My android device:

// GraphicsDevice.DrawInstancedPrimitivesIndirect(PrimitiveType.TriangleList, indirectDrawBuffer1);
GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 6); 

So it could draw from a vertex buffer.

k4G17eYWI commented 3 months ago

I've found an article on this. Long story short: we need a VAO. You might get away without creating one with some OpenGL drivers, but for maximum compatibility, you need to create one. I'll try to do some code sketches today but I have no experience with opengl and VAO is kinda sophisticated matter. If you have some time, please give me some short instruction on how to implement it.

I suppose all the magic of binding lies in the GraphicsDevice.OpenGl.ApplyAttribs(), doesn't it?

k4G17eYWI commented 3 months ago

Correct me if I'm wrong. We only have to create a VAO just to have one and that's all we have to do. We can do it once in the indirect call wraper or even in the GL initialization. The algorithm is:

  1. Create the VAO

    GLuint vao_name;
    glGenVertexArrays(1, &vao_name);
  2. Bind the VAO glBindVertexArray(vao_name);

  3. { do some stuff }

  4. Unbind the VAO

I'm trying to implement it but for now I have Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR) crash...

cpt-max commented 3 months ago

Maybe this wiki page helps: https://wiki.delphigl.com/index.php/Vertex_Array_Object It shows all the needed steps.

k4G17eYWI commented 3 months ago

Fixed also here https://github.com/cpt-max/MonoGame/pull/5