SFML community forums

Help => Graphics => Topic started by: Jose Luis on April 05, 2013, 01:54:17 pm

Title: Why it could be slower render with a sf::VertexArray than using sf::Sprites ?
Post by: Jose Luis on April 05, 2013, 01:54:17 pm
Thanks in advance, the point is the next. I have making a little particle engine, the problem come when i tried to optimize it using a vertexarray to render it. The first implementation, using sf::Sprites, could render 10K particles without problem in my machine, but when I have changed to a sf::VertexArray implementation the render process become slower, it cannot mantain the framerate with 3K particles. What Could I be doing wrong?.

One thing more, I belive noticed the problem is in the RenderWindow::draw call because I have monitoring the program with and without this call. I let you some code snippet. Thanks again.
void System::draw (sf::RenderWindow& theWindow)
{
   mVertices.clear();

   std::list<Particle>::const_iterator it;
   for(it = mParticles.begin();it != mParticles.end();it++)
   {

      sf::Transform anTransform;

      anTransform.translate(it->getPosition().x,it->getPosition().y);
      anTransform.rotate(it->getAngle());
      anTransform.scale(it->getScale().x,it->getScale().y);
      sf::Rect<int> anTexRect = it->getTexRect();

      sf::Vector2f anPositions[4];
      anPositions[0] = anTransform.transformPoint(sf::Vector2f(-(anTexRect.width / 2),-(anTexRect.height /2)));
      anPositions[1] = anTransform.transformPoint(sf::Vector2f( (anTexRect.width / 2),-(anTexRect.height /2)));
      anPositions[2] = anTransform.transformPoint(sf::Vector2f( (anTexRect.width / 2), (anTexRect.height /2)));
      anPositions[3] = anTransform.transformPoint(sf::Vector2f(-(anTexRect.width / 2), (anTexRect.height /2)));

      sf::Vector2f anTexCoords[4];
      anTexCoords[0] = sf::Vector2f(anTexRect.left,                  anTexRect.top);
      anTexCoords[1] = sf::Vector2f(anTexRect.left + anTexRect.width, anTexRect.top);
      anTexCoords[2] = sf::Vector2f(anTexRect.left + anTexRect.width, anTexRect.top + anTexRect.height);
      anTexCoords[3] = sf::Vector2f(anTexRect.left,                  anTexRect.top + anTexRect.height);

      for (int i = 0; i < 4;i++)
      {
         mVertices.append(sf::Vertex(anPositions[i], sf::Color(255, 255, 255, 255),anTexCoords[i]));
      }
      theWindow.draw(mVertices,mStates);
   }
 
Title: Re: Why it could be slower render with a sf::VertexArray than using sf::Sprites ?
Post by: Laurent on April 05, 2013, 02:24:09 pm
You're drawing your whole vertex array for every particle. The last line (the draw call) should be outside the loop.
Title: Re: Why it could be slower render with a sf::VertexArray than using sf::Sprites ?
Post by: Jose Luis on April 05, 2013, 03:58:27 pm
I'm very shamed. Thank you.
Title: Re: Why it could be slower render with a sf::VertexArray than using sf::Sprites ?
Post by: Laurent on April 05, 2013, 04:03:16 pm
So what performances do you get now? ;)
Title: Re: Why it could be slower render with a sf::VertexArray than using sf::Sprites ?
Post by: Jose Luis on April 05, 2013, 04:12:09 pm
I cannot prove it right now, but I have done it with a big tiled map and the improvement was very high. When I fix it i'll tell you the result. Thanks a lot again.
Title: Re: Why it could be slower render with a sf::VertexArray than using sf::Sprites ?
Post by: Jose Luis on April 05, 2013, 06:04:37 pm
Great!. Very notable performance improvement.
Title: Re: Why it could be slower render with a sf::VertexArray than using sf::Sprites ?
Post by: Haze on April 05, 2013, 09:33:23 pm
Just wondering, rebuilding a vertex array for each frame (which can induce memory reallocation + copy) is more efficient than drawing each particle one at a time with a different draw call?
Title: Re: Why it could be slower render with a sf::VertexArray than using sf::Sprites ?
Post by: Laurent on April 05, 2013, 10:29:38 pm
There's no reallocation because sf::VertexArray is based on std::vector which never frees its memory until it is destroyed. Moreover, draw calls are very expensive, the graphics card is not designed for many draw calls, but rather for few calls that draw many polygons at once.
Title: Re: Why it could be slower render with a sf::VertexArray than using sf::Sprites ?
Post by: Haze on April 05, 2013, 10:54:51 pm
There's no reallocation because sf::VertexArray is based on std::vector which never frees its memory until it is destroyed.
But the number of particles will increase overtime, so if a vector doesn't have enough memory allocated, a new chunk of memory will be allocated and the old content is copied, then free'd.
But I think I overestimated this, reallocations shouldn't happen often thanks to the vector growing strategy.

Moreover, draw calls are very expensive, the graphics card is not designed for many draw calls, but rather for few calls that draw many polygons at once.
Good to know, thanks for the tip.
Title: Re: Why it could be slower render with a sf::VertexArray than using sf::Sprites ?
Post by: Laurent on April 06, 2013, 08:59:40 am
Quote
But the number of particles will increase overtime, so if a vector doesn't have enough memory allocated, a new chunk of memory will be allocated and the old content is copied, then free'd.
I wouldn't say "over time". The vector will most likely reach its maximum size after a few updates, and if it's still a problem then you can allocate the required memory at init time instead of letting the vector grow.