Shader storage buffers with variable length structures

I am planning to create a game with square tile based map.
There are 6 types of tiles:

  • Horizontal tile with no height (0)
  • Horizontal tile with height != 0
  • (North or East direction) sloped planar tile
  • Tile with 2 non-planar triangles (edge between 2 triangles can be / or )
  • Cliff to connect neighbor tiles with different heights

All textures for tile mosaic and pickup bonus (pickup bonus + mosaic = multitexture) are stored in a 2d texture array. So for every tile, only the index (or indices) of texture array needed.

Any of these tiles has its own structure, different from other types both in contents and size. To differentiate one tile structure from another, first integer member in every structure contains type information. (e.g. A horizontal tile with no height needs 3 integers and a tile with 2 non-planar triangles needs 11 integers. Another horizontal tile with no height needs 4 integers because needs 2 textures).

My design is like this:

  • Tile based map is made up from West to East stripes of tiles.
  • There is a (read-only) shader storage buffer with all structures of tiles in game map.
  • Vertex shader is a pass-through shader. Every vertex1d (POINT) is a tile (see next).
  • Vertex array buffer, has nothing to do with vertices. It has only the pointer to shader storage buffer of tile data for the specific tile.
  • Geometry shader takes vertex1d from vertex shader and access the shader storage buffer with vertex1d as pointer (offset).
  • Geometry shader creates everything for the tile: vertices, texcoords for one or more textures, normals etc. Tile is a 2-triangle triangle-strip.
  • Because structures in shader storage buffer varies, I prefer a big array of integers

Questions:

  • Is this design viable? (It is a silly question, but I am beginner)
  • For sure, to avoid all of these, discard geometry shader and add all things in vertex array buffer, is faster. But how slower can be my design? 2 times slower or 1000 times slower?

Is this design viable?

Define “viable”.

It is something that could be implemented, yes. But really… why bother?

Think about what you’re doing. For every tile, you have to have a geometry shader generate mesh data for that tile. This must happen every single time you render.

Whereas if you’re just throwing triangles at the system, you just throw triangles at the system. It’s just reading triangles out of a buffer, doing some matrix multiplying, and rendering them. GPUs are fast at that because… that’s what they’re for.

Unless your tiles actually change, and change frequently, you’re probably losing performance relative to simply using vertex data and modifying it as needed.

The advantage that your system provides is less memory consumption per-tile. The way you’re describing things, each tile requires one integer: the tile index that it uses. Whereas the equivalent sequence of triangles for a tile could require 128 bytes or more.

The downside is that the GS has to spend a lot of time reading (potentially cached) memory and resolving that data into vertex data. Not to mention, GS’s have limits on how much data they can output (though for GL 4.x, those limits have reasonable minimums). If you’re trying to output dozens of triangles from a single GS invocation, that may well fail.