It seems like vertexes are stored in some ineffective way (why they take so much of memory?)It seems like you store them in a ineffective way. Do you duplicate the tile textures?
Or it has to be that way and vertex array is overrated?They are in so far overrated as people think they magically solve any performance problems. Their main advantage in comparison to sf::Sprite is (besides flexibility) the reduction of draw calls.
Here's the memory usage calculation:This is for the texture, not the vertex array. And only in the case where tiles are needlessly duplicated.
It seems like you store them in a ineffective way. Do you duplicate the tile textures?
I doubt how it could be improved really.You missed the most important part of my post. Do you store the whole map, including all the invisible parts, in a vertex array? If so, you have your answer.
sf::Vertex size is 48 bytes. So it should be 190mb and not 240mb anyway.Since sf::VertexArray uses a std::vector internally, it may allocate more than necessary to allow faster growing. If this is an issue, call shrink_to_fit(), but keep in mind that this results in a copy of all vertices.
You missed the most important part of my post. Do you store the whole map, including all the invisible parts, in a vertex array? If so, you have your answer.
Okay, I get it. I will just divide world in a few vertex arrays and draw only visible one(s).That's a good idea for static tile sets.
]That's a good idea for static tile sets.
Alternatively, you can rebuild the vertex array directly from the visible tiles. Especially if tiles are animated or change over time, you will need a more dynamic approach.
However when I draw a map which is 1000 x 1000 32px tiles, memory usage is 300mb and FPS is 19. That's very bad, I need maps of that size in my game.Well, yes you might need maps of that size in your game, but nobody said you need to render it all, all the time. The only way you would be able to realistically see all the detail would be on a 32000x32000 (1 Gigapixel) screen. Don't give the industry these kinds of ideas yet please ::).
Debug and release builds change nothing here. Is it a bug in SFML that memory usage and fps are that bad with increasing number of vertexes? It seems like vertexes are stored in some ineffective way (why they take so much of memory?)sf::VertexArray stores its data in system RAM for you to manipulate as much as you want. As soon as you draw it, it takes the long journey across your PCIe bus to your graphics RAM and waits there until the GPU renders it to the screen. Keep in mind, this happens EVERY frame because SFML doesn't use VBOs. Given that a single sf::Vertex contains an sf::Vector2f for position data, an sf::Vector2f for texture coordinate data and a sf::Color for color data, that sums up to 2*4+2*4+4*1=20 bytes per vertex. Because sf::Vertex is not polymorphic, the size of its members should constitute its own size. No idea where you got the 65 bytes (or 48 bytes) from... How the data is stored in graphics RAM is another question. It is an internal detail and something we don't need to know about, but I have a feeling it isn't more than the space requirement in system RAM.
Also I think that vertex array should be stored on GPU side rather than on RAM, correct?
It looks like one vertex takes 65 bytes of RAM which is quite a lot. It should be a lightweight object stored on GPU side I think.
I hope that rebuilding 30x25 tiles vertex array every frame won't have a big impact of performance.Certainly not. For my platformer Zloxx II (http://www.bromeon.ch/games/zloxx), I created sf::Sprites every frame anew and drew them individually, using a similar amount of tiles (vertex arrays in SFML didn't exist at that time). That was no problem, even on netbooks or older desktops...
sf::Vertex size is 48 bytes.Is it really? What system and compiler is that?
If an sf::Vertex is 20 bytes large and you have 1001*1001 of them (1000*1000 tiles) you should end up with an sf::VertexArray of at least 20MB.Binary, a tile is 4 vertices... ;D
Hmm yeah forgot that sf::VertexArray needlessly duplicatesQuoteIf an sf::Vertex is 20 bytes large and you have 1001*1001 of them (1000*1000 tiles) you should end up with an sf::VertexArray of at least 20MB.Binary, a tile is 4 vertices... ;D
Quotesf::Vertex size is 48 bytes.Is it really? What system and compiler is that?
std::vector itself and other internal things can't take 160mb of memory...Why not? Let's assume the vector has a grow factor of 2 (typically it's not 2 in STL implementations) and the following worst case scenario occurs:
Hmm yeah forgot that sf::VertexArray needlessly duplicates vertices position data... oh well don't use them myself anyways ::). Using indexed VBOs you could slash so much off that requirement...But.. OpenGL :'( programming... it's hard like OpenGL :'(
(typically it's not 2 in STL implementations).GCC and its STL like to troll apparently, not only operator[] does not assert at all(!!), the vector new length is calculated like: size + max(size,1) so it goes from 0 to 1and then keeps doubling... and netrick is on Linux (http://en.sfml-dev.org/forums/index.php?topic=12347.msg85970#msg85970) so.. yeah, it's actually exactly 80 mbs allocated for 4 million pushed vertices. It probably could sum up and the virtual memory, minor page faults from stl structures that grow in advance, dlls and so on might make it seem worse: http://www.frogatto.com/?p=3
GCC and its STL like to troll apparently, not only operator[] does not assert at all(!!)Have you tried enabling the debug mode? If you don't enable it, the debug checks are disabled, obviously.
To explain why the factor 2 is a particularly bad choice: It represents exactly the threshold that inhibits the usage of previously allocated memory. Growing by a factor of 2 is the worst possible allocation strategy.It's a tradeoff. Factor of 1.5 copies more often, factor of 2 wastes more memory.
Hmm yeah forgot that sf::VertexArray needlessly duplicatesverticesposition data... oh well don't use them myself anyways ::). Using indexed VBOs you could slash so much off that requirement...
Can you explain to me where these redundant vertices could be slashed off? Having recently implemented a tmx loader in openGL using indexed VBOs, I came to the conclusion that it's not really very viable, because the only cullable vertices would be those where two adjacent tiles on the screen were also adjacent in the tileset, in which case you'd safe 2 vertices per occurance, which IMO doesn't happen that often (as compared to eg. the same ground tile repeated over huge parts of the map).The idea is that you use indexing, yes... but you don't advance all attributes at the same pace, i.e. glVertexAttribDivisor. As you probably noticed, there is no way of going around newer OpenGL if you want all the performance you can get ;). If you use your own VBO for tile rendering you can already drop the redundant color data (-20%). If you are really crazy, you could write your own shader to render the tiles with minimal data. Think about it, you are just iterating through a grid and changing the texture that is applied to each quad along the way. You don't have to provide much besides basic information about the grid structure and the type data at each tile. Haven't done this myself, however it seems theoretically possible (maybe something I might try when I get really bored ::)).
Also, on the topic of the wasted std::vector memory: If the amount of vertices per tile and the amount of tiles is known before hand, why not just call vector.reserve(count) at the beginning (avoiding all reallocations) and avoid the waster memory?You can do this already by using sf::VertexArray::reserve() and just indexing the data instead of constantly appending, or even better just specifying at construction how large the sf::VertexArray should be, however many beginners haven't had the privilege of being part of this discussion yet ;).
The idea is that you use indexing, yes... but you don't advance all attributes at the same pace, i.e. glVertexAttribDivisor. As you probably noticed, there is no way of going around newer OpenGL if you want all the performance you can get ;). If you use your own VBO for tile rendering you can already drop the redundant color data (-20%). If you are really crazy, you could write your own shader to render the tiles with minimal data. Think about it, you are just iterating through a grid and changing the texture that is applied to each quad along the way. You don't have to provide much besides basic information about the grid structure and the type data at each tile. Haven't done this myself, however it seems theoretically possible (maybe something I might try when I get really bored ::)).
If you are really crazy, you could write your own shader to render the tiles with minimal data. Think about it, you are just iterating through a grid and changing the texture that is applied to each quad along the way. You don't have to provide much besides basic information about the grid structure and the type data at each tile. Haven't done this myself, however it seems theoretically possible (maybe something I might try when I get really bored ::)).Like Dbug's shader that I improved or even more minimal?
I had a look, it looks pretty minimal. Doubt I can beat that without a few months worth of thinking ;D.I feel flattered, I probably shouldn't because I written it based on dbug's comments and code but I do. ;D
Man... now what will I do when I get bored ::)...SFGU.. :-X I dunno, hex or isometric tile shader? ;D