Jump to content
  • Advertisement
EddieK

OpenGL ES OpenGL ES 2.0 Android slow rendering times

Recommended Posts

Hi I am having this problem where I am drawing 4000 squares on screen, using VBO's and IBO's but the framerate on my Huawei P9 is only 24 FPS. Considering it has 8-core CPU and a pretty powerful GPU, I don't think it is not capable of drawing 4000 textured squares at 60FPS.

I checked the DMMS and found out that most of the time spent was by the put() method of the FloatBuffer, but the strange thing is that if I'm drawing these squares outside of the view frustum, the FPS increases. And I'm not using frustum culling. 

If you have any ideas what could be causing this, please share them with me. Thank you in advance.

Share this post


Link to post
Share on other sites
Advertisement

This is speculation based on how I've read your post, but hopefully it's helpful..

EDIT: I'm guessing this is the same project as the "Packed VBO w/ indexing" post, so I removed the less relevant stuff. 

Regarding put() : The way I'm interpreting  this is that you're filling FloatBuffers and sending new vertices for each object every frame. If that's the case, then you're spending a lot of unnecessary time filling the buffers and sending them to the GPU. A square is a square - The same 1-unit-to-a-side vertex buffer can be created exactly once and then used for all your draws by setting the square's  position/scale/rotation in the vertex shader using uniforms. In your case, this also means you'll probably want to tint the squares with a single uniform for color, instead of vertex colors (Unless having different-colored corners is very important to your project). 

For now, this means moving your FloatBuffer usage and glBufferData calls to only happen once during startup if they aren't already. When you're in your draw loop, you can now just call glBindBuffer, glUniform, and glDrawElements. 

Edited by Alukien

Share this post


Link to post
Share on other sites
3 hours ago, EddieK said:

I checked the DMMS and found out that most of the time spent was by the put() method of the FloatBuffer

This sounds like you are updating the vertices of the quads on a frame-by-frame basis. Why? What are you trying to accomplish?

3 hours ago, EddieK said:

the strange thing is that if I'm drawing these squares outside of the view frustum, the FPS increases.

This makes it sound as if you are fillrate bound. Which is probably caused by having a lot of overlapping quads, causing the same pixels to be rasterised many times.

Rendering performance typically isn't a linear function of the number of triangles rendered. It's also some function of the number of pixels that have to be rasterised, the complexity of shaders, the number of distinct textures/shaders, etc.

Share this post


Link to post
Share on other sites

As swiftcoder says, it is most likely you are fillrate bound. You may also be calling OpenGL in a sub-optimal way but that is less likely to be causing the 24fps.

Android (and mobile devices in general) tends to have far lower fill rates than desktop (and also use tiled rendering). This is afaik partly to keep power use low and conserve battery. A lot of thought has to go into optimizing shaders, overdraw, transparency etc to minimize fill. Many techniques that you might take for granted on desktop are not feasible on mobile. A lot of devices just about have the horsepower to fill the screen once, and that's it.

I would highly advise you to get hold of several older, low end devices to develop / test on, as your lowest targets will give you a better idea of bottlenecks as you go along, and certain shaders will malfunction / simply not work on some devices. Precision in shaders in particular becomes a key issue in my experience. You may also have to introduce different codepaths / shaders depending on device caps.

https://www.facebook.com/permalink.php?story_fbid=1923486231219218&id=100006735798590

https://www.gamedev.net/blogs/entry/2264243-android-build-and-performance/

Share this post


Link to post
Share on other sites

To add to what others have mentioned, the description you gave in lacking any meaningful info for other to provide/suggest a solution.

1. How was timing done? I keep mentioning this in every other beginner post. FPS is NOT a good performance metric. Give us absolute clock time...meaning seconds, milliseconds, nanosecond
2. Where or what is FloatBuffer  and how is it implemented?
3. What does your shaders look like ?
4. What does your rendering pass look like?

Too many unknown..if what I'm trying to get at.

Share this post


Link to post
Share on other sites

additionally I guess your app window has the size of the screen, depending on depth test enabled fragment shaders kill your framerate

Share this post


Link to post
Share on other sites

My shaders look like this:

Fragment shader:

precision lowp float;

uniform sampler2D texture;

varying vec4 outColor;
varying vec2 outTexCoords;
varying vec3 outNormal;

void main()
{
    vec4 color = texture2D(texture, outTexCoords) * outColor;
    gl_FragColor = vec4(color.r,color.g,color.b,color.a);
}

Vertex shader:

uniform mat4 MVPMatrix; // model-view-projection matrix
uniform mat4 projectionMatrix;

attribute vec4 position;
attribute vec2 textureCoords;
attribute vec4 color;
attribute vec3 normal;

varying vec4 outColor;
varying vec2 outTexCoords;
varying vec3 outNormal;

void main()
{
    outNormal = normal;
    outTexCoords = textureCoords;
	outColor = color;
	gl_Position = MVPMatrix * position;
}

My rendering code:

    public void bind(){
        int stride = (2 + 3 + 4) * 4;

        vertexBuffer.put(vertexArray, 0, vertexCount);
        indexBuffer.put(indexArray, 0, indexCount);

        this.vertexBuffer.position(0);
        this.indexBuffer.position(0);

        GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, buffers[0]);
        GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, vertexBytesAdded,
                vertexBuffer, GLES20.GL_STATIC_DRAW);

        ShaderAttributes attributes = graphicsSystem.getShader().getAttributes();
        GLES20.glVertexAttribPointer(attributes.getAttributeID(Attribute.Position), dimensions, GLES20.GL_FLOAT, false, stride, 0);
        attributes.enableAttribute(Attribute.Position);

        GLES20.glVertexAttribPointer(attributes.getAttributeID(Attribute.Color), 4, GLES20.GL_FLOAT, false, stride, 3 * 4);
        attributes.enableAttribute(Attribute.Color);

        GLES20.glVertexAttribPointer(attributes.getAttributeID(Attribute.TextureCoords), 2, GLES20.GL_FLOAT, false, stride, (4 + 3) * 4);
        attributes.enableAttribute(Attribute.TextureCoords);

        GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
        GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBytesAdded,
                indexBuffer, GLES20.GL_STATIC_DRAW);

        vertexBytesAdded = 0;
        indexBytesAdded = 0;
        vertexCount = 0;
        indexCount = 0;
    }

    public void draw(int mode, int count){
        if(hasIndices){
            GLES20.glDrawElements(GLES20.GL_TRIANGLES, count, GLES20.GL_UNSIGNED_SHORT, 0);
        }else{
            GLES20.glDrawArrays(mode, 0, count);
        }

    }

 

Is there anything I can improve to increase the framerate? I'm really out of ideas here, it seems like I tried everything and I still can't get past 3000 triangles without the framerate dropping below 60. I read somewhere that MALI-400 is capable of 30 million polygons per second and I am getting only around 500,000.

Share this post


Link to post
Share on other sites
8 minutes ago, EddieK said:

I'm really out of ideas here, it seems like I tried everything

You are still going to have to explain to us why you appear to be rewriting your vertex buffers every frame. That's going to be using a significant chunk of bandwidth, and causing some fun pipeline stalls.

Can you show us a screenshot of a rendered frame? It's hard to talk about this without seeing how much overdraw you have, how much depth testing is going on, etc.

Share this post


Link to post
Share on other sites
3 minutes ago, swiftcoder said:

You are still going to have to explain to us why you appear to be rewriting your vertex buffers every frame. That's going to be using a significant chunk of bandwidth, and causing some fun pipeline stalls.

Can you show us a screenshot of a rendered frame? It's hard to talk about this without seeing how much overdraw you have, how much depth testing is going on, etc.

Well because I need to update the vertex positions and their colors every frame. How else am I supposed to update the vertices? Sorry, but I am a newbie when it comes to OpenGL. 

Screenshot_20180222-225508.png

Share this post


Link to post
Share on other sites

I figured out that I need to use glBufferSubData() instead. Tried it, but it was even slower

Edited by EddieK

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
  • Advertisement
  • Popular Tags

  • Similar Content

    • By Ibragim Vykov
      Hi, everyone! I'm a self-taught indie developer. After two years of learning programming and gamedev, I finally released my first game. It's a hardcore arcade with simple one-tap control. Check it out please, it would mean a lot to me. And also I'd be very interested to hear your feedback.
      Get it on Google Play: 
      https://play.google.com/store/apps/details?id=com.ibragames.circlevsspikes 
      Official trailer:
      https://www.youtube.com/watch?v=oTbQHaD_nWo

    • By N Drew
      I am working on a 2D SideScroller game in my own made game engine using SFML and C++.I am searching for 2D artists,especially pixel artist for making and animating characters,backgrounds and other props that can be made in any Drawing Program.The artist will become part of the team of Hammer Studios and he got a part of the Revenue Sharing.If you are interested send me a mail at:ghiurcutaandrei@gmail.com .If you are not an artist but you want to be a part of our Team,Soon we will be recruiting an C++ AI programmers that worked in SFML/OpenGL.
      We work together using Discord.

    • By Ds ds
      Hi, my name is Andres, I'm a programmer with a technician degree and a Diploma in C#, looking for a project in Unity to start my career in game development. I don't do it for a paid but a recognition and start a portfolio, preferably a 2D game. Thanks for read, have a nice day. 
       
    • By Inbar_xz
      I'm using the OPENGL with eclipse+JOGL.
      My goal is to create movement of the camera and the player.
      I create main class, which create some box in 3D and hold 
      an object of PlayerAxis.
      I create PlayerAxis class which hold the axis of the player.
      If we want to move the camera, then in the main class I call to 
      the func "cameraMove"(from PlayerAxis) and it update the player axis.
      That's work good.
      The problem start if I move the camera on 2 axis, 
      for example if I move with the camera right(that's on the y axis)
      and then down(on the x axis) -
      in some point the move front is not to the front anymore..
      In order to move to the front, I do
      player.playerMoving(0, 0, 1);
      And I learn that in order to keep the front move, 
      I need to convert (0, 0, 1) to the player axis, and then add this.
      I think I dont do the convert right.. 
      I will be glad for help!

      Here is part of my PlayerAxis class:
       
      //player coordinate float x[] = new float[3]; float y[] = new float[3]; float z[] = new float[3]; public PlayerAxis(float move_step, float angle_move) { x[0] = 1; y[1] = 1; z[2] = -1; step = move_step; angle = angle_move; setTransMatrix(); } public void cameraMoving(float angle_step, String axis) { float[] new_x = x; float[] new_y = y; float[] new_z = z; float alfa = angle_step * angle; switch(axis) { case "x": new_z = addVectors(multScalar(z, COS(alfa)), multScalar(y, SIN(alfa))); new_y = subVectors(multScalar(y, COS(alfa)), multScalar(z, SIN(alfa))); break; case "y": new_x = addVectors(multScalar(x, COS(alfa)), multScalar(z, SIN(alfa))); new_z = subVectors(multScalar(z, COS(alfa)), multScalar(x, SIN(alfa))); break; case "z": new_x = addVectors(multScalar(x, COS(alfa)), multScalar(y, SIN(alfa))); new_y = subVectors(multScalar(y, COS(alfa)), multScalar(x, SIN(alfa))); } x = new_x; y = new_y; z = new_z; normalization(); } public void playerMoving(float x_move, float y_move, float z_move) { float[] move = new float[3]; move[0] = x_move; move[1] = y_move; move[2] = z_move; setTransMatrix(); float[] trans_move = transVector(move); position[0] = position[0] + step*trans_move[0]; position[1] = position[1] + step*trans_move[1]; position[2] = position[2] + step*trans_move[2]; } public void setTransMatrix() { for (int i = 0; i < 3; i++) { coordiTrans[0][i] = x[i]; coordiTrans[1][i] = y[i]; coordiTrans[2][i] = z[i]; } } public float[] transVector(float[] v) { return multiplyMatrixInVector(coordiTrans, v); }  
      and in the main class i have this:
       
      public void keyPressed(KeyEvent e) { if (e.getKeyCode()== KeyEvent.VK_ESCAPE) { System.exit(0); //player move } else if (e.getKeyCode()== KeyEvent.VK_W) { //front //moveAmount[2] += -0.1f; player.playerMoving(0, 0, 1); } else if (e.getKeyCode()== KeyEvent.VK_S) { //back //moveAmount[2] += 0.1f; player.playerMoving(0, 0, -1); } else if (e.getKeyCode()== KeyEvent.VK_A) { //left //moveAmount[0] += -0.1f; player.playerMoving(-1, 0, 0); } else if (e.getKeyCode()== KeyEvent.VK_D) { //right //moveAmount[0] += 0.1f; player.playerMoving(1, 0, 0); } else if (e.getKeyCode()== KeyEvent.VK_E) { //moveAmount[0] += 0.1f; player.playerMoving(0, 1, 0); } else if (e.getKeyCode()== KeyEvent.VK_Q) { //moveAmount[0] += 0.1f; player.playerMoving(0, -1, 0); //camera move } else if (e.getKeyCode()== KeyEvent.VK_I) { //up player.cameraMoving(1, "x"); } else if (e.getKeyCode()== KeyEvent.VK_K) { //down player.cameraMoving(-1, "x"); } else if (e.getKeyCode()== KeyEvent.VK_L) { //right player.cameraMoving(-1, "y"); } else if (e.getKeyCode()== KeyEvent.VK_J) { //left player.cameraMoving(1, "y"); } else if (e.getKeyCode()== KeyEvent.VK_O) { //right round player.cameraMoving(-1, "z"); } else if (e.getKeyCode()== KeyEvent.VK_U) { //left round player.cameraMoving(1, "z"); } }  
      finallt found it.... i confused with the transformation matrix row and col. thanks anyway!
    • By Doommy
      If someone could assist me through this I would be really grateful. I'm using SharpDX/C#/WinForms but I think this could more apply to directx in general.
      I'm very new to graphics programming and I'm really just trying to do something as simple as displaying a rectangle to the screen.
      Here is my issue:
      I have the below code:
      ----------------------------------------------------------
       var desc = new SwapChainDescription()
                  {
                      BufferCount         = 1,
                      ModeDescription     = new ModeDescription(1024, 768, new Rational(60, 1), Format.R8G8B8A8_UNorm),
                      IsWindowed          = false,
                      OutputHandle        = form.Handle,
                      SampleDescription   = new SampleDescription(1, 0),
                      SwapEffect          = SwapEffect.Discard,
                      Usage               = Usage.RenderTargetOutput
                  };
      I'm not sure if the window is loading in full screen. Actually to make it go full screen I actually have to set the forms property to: this.WindowState        = FormWindowState.Maximized; but that only seems lke Im using a C# code to maximize the form. For instance if I don't set the form to maximize, the form loads at the original size if IsWindowed is set to false. I recall with directx programing using dx7, when I set full screen you could actually see what looked like a display resolution change. I'm not seeing that. It pretty much looks like the form is loaded at the same size as the screen and not the value I provide in modeDescription. This is not what I want as well because I want to set the display to 1024x768 to avoid stretching of my graphics in wide screens.
      Can someone help me make sense of this please.
    • By bartekm777
      Hello
      About me
      Lvl 28   Programmer (day job: non-gamedev-programmer, making games as a hobby for about 2 years) Some vector art experience - tried to make some assets on my own using vector software and scripts   Some design experience (designing my own games ) About game
      Turn-based fantasy rpg inspired by games like Heroes 3 (also WoG mod), NEO Scavenger, Battle Brothers I would like to create easy to use editor for creating custom scenarios (similar to the one from Heroes 3) World and story are clean slate, I did some drafts but I'm not good at it so it's possibly subject to change I decided to create graphics using vector software + scripts to make it faster (rpg's tend to have lots of assets), also it's more precise and easier to create tileable graphics (for example: rivers, paths) No sound/music work has been done yet Who do I look for?
      Definitely someone with 2d art skills  I would like to focus more on programming 2D animator (skletal animations are preferred) Additional programmer could make development faster Someone for creating sounds/music/both It's a hobby project, I work on it in my free time. In case the project make it to the finish line and get shipped  - I can offer rev-share  
      Below should be few screens of what I already did (about 2 months of work) - some graphics, editor prototype screenshot and game prototype screenshot




    • By Anikieth
      What softwares should I prefer for like really basic game development,and basic requirements for starting into this
    • By this. games
      [Free]
      Looking For: 2d Artist and Animator.
      Requirements: Experience in 2d art and ability to commit to 1-2 years of work.
      Payment: Rev-Share (Think Free as the product may not end up being sold)
      Description: An 3/4 view 2d game with a Sci-fi style. The game is based on a man who was put into stasis for punishment for his crimes. He has woken up 100 years later and must now regain his position at the top of the criminal underworld by killing his opponents. There will be a "Hub World" city and then PCG gang hideouts where you fight enemies. The assets required will be tile sets for the different hideouts, assets for the city ie buildings streets etc. and characters both the player and a number of enemies.
       
      Send resume and portfolio to thisdotgames@gmail.com if you are interested.
    • By Liquifire
      So I'm making this basic 2D engine using Haxe Kha, and i just need to integrate some physics. Just basic collision detection and gravity on basic shapes, nothing too detailed. But i want to try not to write it myself, so i just want suggestions on what open source phyisics engines i could use, and that wont be impossible to integrate. Thanks in advance.
    • By Hive Entertainment
      Hey everyone we are looking for a 2d artist for health bars, inventory, items, weapons ect. Unfortunately I can not pay at this point in time however if you are interested please let me know and I am sure we can work something out. I am also looking for landscape modelers in 3d message me for more details or email me at hiveentertainmenttech@gmail.com




  • Advertisement
  • Popular Now

  • Forum Statistics

    • Total Topics
      631349
    • Total Posts
      2999473
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!