Announcement

Collapse
No announcement yet.

Interesting Draw Call Experiment Result

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    Interesting Draw Call Experiment Result

    Hi everyone, today I realized something about draw calls. I have done some basic tests and results surprised me.

    1- Firstly I put a sky with 1 mesh and 1 material so I had 2 draw calls. As expected.

    2- And I put a cube static mesh from basics tab and draw call increased to 4 from 2. As expected. (1 for mesh and 1 for material)

    3-Then I put a movable skylight. No any change. As expected.

    4-When I put a movable directional light (with 1 cascade). Draw call increased to 6 from 4. This was surprised me because I did not expect that a shadow (from static mesh) brings 2 draw calls.

    This is my first question. Is this usual? Is anyone here to inform us about that?

    5-So I dug a bit more and I put another static mesh which has 2 materials. And it brings 4 draw calls without shadow. If I turn on shadows it brings 8 draw calls (4 calls for shadow.) Isn't something wrong here?

    6- And my last experiment was about skeletal meshes. I put a skeletal mesh which has 1 mesh and 1 materials. It brings 3 draw calls. (this was 2 calls on same static mesh) and when I turn on shadows it brings 5 calls (2 for shadow). Finally, I put another skeletal mesh which has 1 mesh and 2 materials. And it brings 6 draw calls without shadow. And 10 draw calls with shadow.

    These situations were pretty weird to me and I wanted to share here. I hope there is someone here to keep us informed.

    #2
    Static meshes can't be draw without materials so each mesh section is 1 draw call. If Mesh has 10 sections then it's 10 draw calls.
    Shadow mapping basically draw every mesh from light point of view to depth map. So you get 1 draw call per mesh section.

    Comment


      #3
      Originally posted by Kalle_H View Post
      Static meshes can't be draw without materials so each mesh section is 1 draw call. If Mesh has 10 sections then it's 10 draw calls.
      Shadow mapping basically draw every mesh from light point of view to depth map. So you get 1 draw call per mesh section.
      Yes, this is how it should be but somehow the engine adds more draw calls. For example, a mesh with 2 materials without shadow should bring 3 draw calls. But engine calls 4. If I put a movable directional light it bring 4 additional draw calls. (total 8) Let's say shadows call source is material not mesh. Then Shadow cost should be 2 calls. But it isn't

      Comment


        #4
        Are you using Stat SceneRendering to get your metrics?

        There is a significant amount of machinery when rendering the scene.

        Anything from batching, shadows, culling all impact.

        Any results you get from adding removing single meshes need to be taken with a grain of salt...

        BTW - A material by itself is not a draw call. So a single mesh with 1 section and 1 material should add 1 draw call.

        http://casualdistractiongames.com

        Comment


          #5
          Originally posted by MASSIVE Can View Post

          Yes, this is how it should be but somehow the engine adds more draw calls. For example, a mesh with 2 materials without shadow should bring 3 draw calls. But engine calls 4. If I put a movable directional light it bring 4 additional draw calls. (total 8) Let's say shadows call source is material not mesh. Then Shadow cost should be 2 calls. But it isn't
          A directional light shadow on default settings uses multiple cascades. Each cascade will require the objects to be drawn into it.

          If you're interested in doing such low level dive into the draw calls, download and install RenderDoc, go into your editor plugins and enable the RenderDoc plugin. It will add a small icon at the top right of the viewport which you can press at any time to capture the current frame and open it in RenderDoc for examination. There you can see absolutely everything the GPU is doing to render the captured frame, step by step.

          Comment


            #6
            Perhaps you are using the term draw call differently?

            Historically "Draw Call" often refers to a specific group of functions that are implemented by the underlying graphics api.
            No doubt the term has been around for a long time and is vague and confusing.

            OpenGL, Vulkan, Metal all implement "Draw Calls".

            In general, the draw call refers to sending a vertex buffer down the pipeline for rendering by the gpu.
            These vertices will be rasterized and the resultant fragment will be rendered using the currently bound GPU state.
            The current state refers to the currently bound set of textures and shaders.
            NOTE - The calls that do the actual binding of gpu state are not typically referred to as "Draw Calls".

            Lets use some really old legacy OpenGL to illustrate ( there are much better ways to do this but this is simple to show )
            Suppose you have a model with three parts to it and three textures.

            Notice there are 3 calls to glDrawArrays. glDrawArrays is a "Draw Call" in OpenGL. It sends the buffer down the pipeline.
            The other calls to glVertexPointer and glTexCoordPointer set state. These are not "draw calls"
            Code:
             // Enable state
            glEnableClientState(GL_VERTEX_ARRAY);
            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
            
            // Set your used arrays
            glVertexPointer(3, GL_FLOAT, 0, vertices.data());
            glTexCoordPointer(2, GL_FLOAT, 0, textureCoords.data());
            
            // Draw first section
            glDrawArrays(GL_TRIANGLES, 0, size); // 'size' is the number of your vertices.
            glVertexPointer(3, GL_FLOAT, 0, vertices2.data());
            glTexCoordPointer(2, GL_FLOAT, 0, textureCoords2.data());
            
            // Draw second section
            glDrawArrays(GL_TRIANGLES, 0, size); // 'size' is the number of your vertices.
            glVertexPointer(3, GL_FLOAT, 0, vertices2.data());
            glTexCoordPointer(2, GL_FLOAT, 0, textureCoords2.data());
            
            // Draw third section
            glDrawArrays(GL_TRIANGLES, 0, size); // 'size' is the number of your vertices.
            glVertexPointer(3, GL_FLOAT, 0, vertices3.data());
            glTexCoordPointer(2, GL_FLOAT, 0, textureCoords3.data());
            
            // Reset initial state
            glDisableClientState(GL_VERTEX_ARRAY);
            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
            Hence 3 draw calls.

            https://www.pcper.com/reviews/Editor...What-Can-It-Do
            http://casualdistractiongames.com

            Comment


              #7
              Originally posted by IronicParadox

              I'm almost positive that it's two draw calls per mesh(single mesh+single material). One for geometry and one for the material.
              Draw call means that you draw some geometry with some shader. At least you need vertex shader but optionally there can be tesselation stages, geometry shader and pixel shader.
              You cannot draw a material. Material is just high level abstraction for shaders. Shader is the program that is run for every vertice and pixel that those vertices produce. Shaders can't be run without input.
              So draw call are just number of the mesh sections plus the draw calls needed for shadow rendering. For single cascade directional shadows you get as many draw calls as sections.

              Comment


                #8
                Originally posted by Kalle_H View Post

                Draw call means that you draw some geometry with some shader. At least you need vertex shader but optionally there can be tesselation stages, geometry shader and pixel shader.
                You cannot draw a material. Material is just high level abstraction for shaders. Shader is the program that is run for every vertice and pixel that those vertices produce. Shaders can't be run without input.
                So draw call are just number of the mesh sections plus the draw calls needed for shadow rendering. For single cascade directional shadows you get as many draw calls as sections.
                Yeah, that's right. It was late and I wasn't thinking clearly. I was thinking of material slots aka mesh sections lol...

                I'm still pretty sure about the part involving having multiple dynamic shadow casting lights though. So if you had a mesh with four sections and three dynamic lights influencing the mesh, you'd tack on 12 draw calls(single cascade). Which would take it up to 16 draw calls for the whole object. Unless it batches all of the lights together in a single call? I'd definitely have to test this out to be sure.
                Last edited by IronicParadox; 06-13-2018, 11:59 AM.

                Comment


                  #9
                  Originally posted by IronicParadox View Post

                  Yeah, that's right. It was late and I wasn't thinking clearly. I was thinking of material slots aka mesh sections lol...

                  I'm still pretty sure about the part involving having multiple dynamic shadow casting lights though. So if you had a mesh with four sections and three dynamic lights influencing the mesh, you'd tack on 12 draw calls(single cascade). Which would take it up to 16 draw calls for the whole object. Unless it batches all of the lights together in a single call? I'd definitely have to test this out to be sure.
                  Lights cannot be batched. Shadow pass could render all the sections at once if all sections use same depth pass material. But I don't think it does so. If material does not use WPO, masked blend mode or depth offset then material does not need custom depth pass shader. This is the most common case so it could be quite big saving for draw calls. Has to test this up.

                  Comment


                    #10
                    Originally posted by Kalle_H View Post

                    Lights cannot be batched. Shadow pass could render all the sections at once if all sections use same depth pass material. But I don't think it does so. If material does not use WPO, masked blend mode or depth offset then material does not need custom depth pass shader. This is the most common case so it could be quite big saving for draw calls. Has to test this up.
                    Yeah, I tested it out. Each dynamic light adds in extra draw calls per mesh section. Each cascade level adds more as well.

                    Here are some results from a blank level. I made sure to remove the character model from the 3rd person BP. Put a blocking volume in for a floor and made a static mesh comprised on four sections. I also used a default cube as well.

                    With no lights and no model: 0 draw calls

                    Default cube and no lights: 2 draw calls
                    Default cube and one dynamic light+one cascade: 3 draw calls
                    Default cube and one dynamic light+two cascades: 3 draw calls
                    Default cube and one dynamic light+three cascades: 4 draw calls
                    Default cube and one dynamic light+four cascades: 4 draw calls

                    Default cube and three dynamic lights+four cascades: 6 draw calls
                    Default cube and six dynamic lights+four cascades: 9 draw calls

                    Four piece static mesh and no lights: 5 draw calls
                    Four piece static mesh and one dynamic light+one cascade: 6 draw calls
                    Four piece static mesh and one dynamic light+two cascades: 6 draw calls
                    Four piece static mesh and one dynamic light+three cascades: 7 draw calls
                    Four piece static mesh and one dynamic light+four cascades: 7 draw calls

                    Four piece static mesh and three dynamic lights+four cascades: 11 draw calls
                    Four piece static mesh and six dynamic lights+four cascades: 17 draw calls

                    The numbers sometimes fluctuate because it looks like it's reusing information from previous frames in a cache. If I recall correctly, they implemented this in a few releases ago. If the static mesh hasn't moved, the lights haven't moved, and nothing has gotten in the way to disturb the shadows, then there's no reason to update them.

                    Comment

                    Working...
                    X