Jump to content

  • Log In with Google      Sign In   
  • Create Account


DrawIndexedPrimitives takes 20 to 40 FPS to draw


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
28 replies to this topic

#1 LemonBiscuit   Members   -  Reputation: 145

Like
0Likes
Like

Posted 05 February 2014 - 02:12 PM

Hello,

 

I'm trying to display a terrain in my XNA game which is made of 512*512 vertices.

On my laptop, without the terrain, I have 60 FPS. When I display it, I'm running between 25 and 40 FPS.

 

I'm drawing 2 times the terrain: once for the camera, and once for the water reflection (I have an ocean).

 

I optimized a maximum my shaders, and I can tell you the lag doesn't come from here.

 

My draw function is only composed of this:

GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, numberVertices, 0, numberIndices / 3);

I've seen a lot of people drawing million of faces in their game. I "only" have 512288 vertices to draw...

What could I do to optimize this function and get some more FPS?

 

Thank you!

 

 



Sponsor:

#2 Mona2000   Members   -  Reputation: 554

Like
0Likes
Like

Posted 05 February 2014 - 02:55 PM

I optimized a maximum my shaders, and I can tell you the lag doesn't come from here.

 

If that's an assumption I suggest you use a profiler like Intel GPA to check it.



#3 LemonBiscuit   Members   -  Reputation: 145

Like
0Likes
Like

Posted 05 February 2014 - 03:40 PM

No it's not an assumption, I tried removed them and the problem wasn't gone..



#4 mhagain   Crossbones+   -  Reputation: 7413

Like
0Likes
Like

Posted 05 February 2014 - 03:50 PM

There are so many things that could be causing this.  With the amount of code you've posted the best you're going to get are guesses, so here's a few to start with:

  • Try simpler shaders.
  • Try lower resolution textures.
  • Try drawing without your water reflection.
  • Are you reading anything back from the GPU?  (Perhaps for that reflection?)
  • Check your vsync settings.
  • Are you using Sleep calls to control framerate?

It's highly unlikely that the DrawIndexedPrimitive call itself is the culprit.  Instead, there's something running slow that the call depends on, or something that depends on the call and must wait for the call to fully finish before it can start, or something bad in your main loop that's being highlighted by the call.  That's the kind of thing you need to look for.


Edited by mhagain, 05 February 2014 - 03:50 PM.

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#5 RnaodmBiT   Members   -  Reputation: 551

Like
0Likes
Like

Posted 05 February 2014 - 04:12 PM

When you have trouble determining the root cause for why <x> is slowing your game down, you need to profile it. That is, using one of the various tools out there, get the numbers behind all the of the directx calls you are making to determine what exactly is at fault. I would recommend using the Intel Graphics Performance Analyzer (it's free) as mentioned above. I have just started using it and I can tell you it is amazing, once you capture a frame for analysis it displays all of the render calls based on which render target they are operating on. It lets you edit the shader code live, perform experiments such as swapping in a simple pixel shader, using 2x2 size input textures, it even lets you edit the current render states bound to each section of the pipeline. 



#6 newtechnology   Members   -  Reputation: 570

Like
0Likes
Like

Posted 06 February 2014 - 05:41 AM

I guess you're not culling anything?



#7 LemonBiscuit   Members   -  Reputation: 145

Like
0Likes
Like

Posted 06 February 2014 - 07:08 AM

No I'm not culling anything.

 

RnaodmBiT I used your profiler, and as nVidia's one it tells me DrawIndexedPrimitives is taking all the GPU ressources.

 

So I really don't know where it comes from...



#8 mark ds   Members   -  Reputation: 1070

Like
0Likes
Like

Posted 06 February 2014 - 07:40 AM

Are you recreating and/or resending data between draw calls, rather than once up front?



#9 phil_t   Crossbones+   -  Reputation: 3180

Like
1Likes
Like

Posted 06 February 2014 - 09:27 AM


RnaodmBiT I used your profiler, and as nVidia's one it tells me DrawIndexedPrimitives is taking all the GPU ressources.

 

I'm not sure about nVidia's tool, but Intel GPA should tell you whether or not the time is in the vertex shader or pixel shader. It should also let you perform experiments to see what happens if you swap things out with a 1x1 texture (to test if texture cache is the bottleneck), for instance. You might need an Intel GPU for some of the more advanced features to work.

 

You can also do this manually of course. For instance, replace your terrain pixel shader with a dummy one that just outputs a color. How does that affect your frame time? 

 

All we can do on this forum is make wild guesses for you.

 

Can you post your vertex and pixel shaders?


Edited by phil_t, 06 February 2014 - 09:28 AM.


#10 Matias Goldberg   Crossbones+   -  Reputation: 3007

Like
0Likes
Like

Posted 06 February 2014 - 09:38 AM

512*512 is actually a lot of vertices. That translates to 262.144, which forces to use 32-bit indices.

Use instancing to draw four chunks of 256x256 verts (which allow to use 16-bit indices) in one call.

 

Furthermore, if your terrain vertices are generated in a random order, it could be that it's cache unfriendly.

Also, if you're updating your terrain vertices once per frame (and the buffer not created with the wrong flags, i.e. static vs dynamic) it could be causing the hit. When you remove the DrawPrimitive call you notice the performance goes up because the driver may be skipping your terrain vertex updates CPU->GPU entirely.

It could also be that when you put the DP call, your bad uploads cause the driver to stall (force the CPU wait for the GPU to complete)

 

Finally, you don't say that a car takes 100 km/h to arrive to destination, but rather that it took an hour.

Same here, measure your frames in time taken in milliseconds, no it in frames per second.



#11 LemonBiscuit   Members   -  Reputation: 145

Like
0Likes
Like

Posted 06 February 2014 - 06:43 PM

Thank you very much for this idea!

 

I tried to create chunks for my terrain, but it doesn't render the exact way I want. It works pretty great, except for one thing: there are lines between every chunks...

 

Screen:

 

http://puu.sh/6MD7M.jpg

 

Code:

http://pastebin.com/i8i0ajn9

 

 

It's been 7 hours I'm on it, and I just can't find it. Help ! sad.png

 

 

I see that it's not coming from distance between them, but missing vertices..


Edited by LemonBiscuit, 06 February 2014 - 07:05 PM.


#12 phil_t   Crossbones+   -  Reputation: 3180

Like
1Likes
Like

Posted 06 February 2014 - 07:03 PM

Can you fix your code link?

 

How large are your chunks? If you're using 32x32 chunks, for instance, you'll need each chunk to have 33x33 vertices.

 

 

Another option - instead of having to deal with discrete chunks - is to instead have a fixed grid that is just large enough to cover the viewable area, and which moves along with the camera. Then (assuming a heightmap texture) use vertex texture fetch, and calculate the height of the vertex in the vertex shader, sampling from the appropriate point in the heightmap.



#13 LemonBiscuit   Members   -  Reputation: 145

Like
0Likes
Like

Posted 06 February 2014 - 07:08 PM

Thank you for your answer, I updated my link.

I indeed set 33x33 vertices, but the problem come from getHeights() function I guess.

 

As you can see I loop to length-1 and width-1 otherwise it crashes (overflow).

What should I do?



#14 phil_t   Crossbones+   -  Reputation: 3180

Like
1Likes
Like

Posted 06 February 2014 - 07:51 PM


As you can see I loop to length-1 and width-1 otherwise it crashes (overflow).

 

Yeah, that's probably the problem. You need length X width heights in each chunk height data, not (length - 1) X (width - 1).

 

So of course if your entire map is 512x512 (composed of 32x32 chunks, which is 33x33 vertices), then you'll need 513x513 height points. You can just "clamp" the last row/column of your height map to accommodate for this. So loop to length/width, and then this:

 

  1. // Get color value (0 - 255)
  2.                         float amt = heightMapData[(+ offsetX) * oWidth + x + offsetY].R;

 

becomes

 

  1. // Get color value (0 - 255)             
  2.                         float amt = heightMapData[Math.Min(+ offsetX, oHeight - 1) * oWidth + Math.Min(x + offsetY, oWidth - 1)].R;

 

 

 

Also note that you don't need a separate index buffer for each chunk. Every chunk's index buffer will be identical, so you just need one.


Edited by phil_t, 06 February 2014 - 07:52 PM.


#15 LemonBiscuit   Members   -  Reputation: 145

Like
0Likes
Like

Posted 07 February 2014 - 12:38 AM

Aaaaand it works! Thank you very much for your help!

I think I'll manage to get all the things working the way I want now :)



#16 LemonBiscuit   Members   -  Reputation: 145

Like
0Likes
Like

Posted 07 February 2014 - 03:46 PM

I'm still stuck on one point and I'll need your help, again sad.png

 

I managed to divide my weightmap (colors associated to textures) for every chunks, but I still have a tiling offset:

 

http://i.imgur.com/NLmNczt.png

 

(It is the seperation between two chunks)

 

Here is the shader: http://pastebin.com/05N7nqSZ

 

Do you know how I could fix it?

Thank you


Edited by LemonBiscuit, 07 February 2014 - 03:59 PM.


#17 phil_t   Crossbones+   -  Reputation: 3180

Like
1Likes
Like

Posted 07 February 2014 - 04:41 PM

Is one of your sampler states not set to wrap or something? I can't tell you how to fix it, but I can tell you how to start diagnosing it. Just have your shader directly output one of your 5 input textures and see which ones have that discontinuity.



#18 LemonBiscuit   Members   -  Reputation: 145

Like
0Likes
Like

Posted 07 February 2014 - 04:55 PM

Thank you for your always fast answers.

 

Here are my samplers:

http://pastebin.com/0nCE4nzL

 

I tried to remove each one one-per-one, but nothing seems to change.

I have to say I followed a tutorial for this part of texturing (as I said before, I'm a newbie with HLSL :( )



#19 phil_t   Crossbones+   -  Reputation: 3180

Like
0Likes
Like

Posted 07 February 2014 - 06:15 PM

If you just output your weightmap, it still has that obvious discontinuity? Then your UV coordinates are wrong.



#20 LemonBiscuit   Members   -  Reputation: 145

Like
0Likes
Like

Posted 08 February 2014 - 07:37 AM

I can't get them correct, but anyway, now even the normals in the side of the chunks are incorrect (I should get vertices from other chunks to get the normal, etc.) It's getting a little too complex for the little optimization I want to do.. sad.png

 

 

I have another idea to optimize my things.

I generate a few bounding boxes all over my map (16 or 32 for instance).

Then I check at each frame which boxes are in view, and I then adapt the amount of vertices to show.

 

For instance:

 

If the boundingbox containing the last vertices of my terrain is not in view, then the amount of primitives to draw is the amount of vertices - the amount of vertices contained in the box.

 

Same thing for the first ones.


Edited by LemonBiscuit, 08 February 2014 - 08:41 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS