Geometry Shader Output Limits

I am trying to determine the maximum number of vertices a geometry shader is able to output. I am trying to use the below code but the value printed out via an exception (128) works and my code gives me half that (64). I am using Java/JOGL and #version 150 for my shader. I am dividing by two because my geometry shader is outputting glPosition and a vec4 for color to my fragment shader.


Math.min(gl.glGetInteger(GL3.GL_MAX_GEOMETRY_OUTPUT_VERTICES), gl.glGetInteger(GL3.GL_MAX_GEOMETRY_OUTPUT_COMPONENTS) / 2);

The output is


MAX_GEOMETRY_OUTPUT_VERTICES = 1024
GEOMETRY_OUTPUT_COMPONENTS = 128

The spec says the max number of vertices shouldn’t exceed the MAX_GEOMETRY_OUTPUT_VERTICES and the product of the number of compunents and the value of MAX_GEOMETRY_OUTPUT_COMPONENTS. What exactly is a component? Why does the math say the value SHOULD be 64 when 128 works? How are you supposed to compute the max number of vertices allowed to be outputted by a geometry shader?

Any help would be appreciated; thanks!

  • Stephen

The number of output vertices and the number of output components are unrelated.

MAX_*_OUTPUT_COMPONENT, which exists for both VERTEX and GEOMETRY, refers to the number of individual values you can output. A vec4 takes up 4 components. A float takes up 1 component.

So it’s a count of the total number of values you can squeeze out of the geometry shader per vertex. It’s the number of values you can declare as out in the geometry shader. It has nothing to do with the number of times you can call EmitVertex.

The spec states


There are two implementation-dependent limits on the value of
GEOMETRY_VERTICES_OUT; it may not exceed the value of
MAX_GEOMETRY_OUTPUT_VERTICES, and the product of the total
number of vertices and the sum of all components of all
active output variables may not exceed the value of
MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS.

http://www.opengl.org/registr/doc/glspec42.core.20110808.pdf
Page 149

So does this mean that MAX_GEOMETRY_VERTICES_OUT is the maximum number of vertices you can emit and that MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS / components is the maximum number of float able to be outputted per vertex? Because this is not the case. I’m outputting 8 floats (position and color) and MAX_GEOMETRY_VERTICES_OUT = 1024 and it will only let me output 128 (MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = 128). Or is the MAX_GEOMETRY_VERTICES_OUT / component floats <= MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS? (1024 / 8 <= 128 which is true)?

So does this mean that MAX_GEOMETRY_VERTICES_OUT is the maximum number of vertices you can emit and that MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS / components is the maximum number of float able to be outputted per vertex?

No. The spec means exactly what it says.

There is a limit on the number of vertices you can output from a geometry shader. There is a limit on the number of components you can output per-vertex. And there is a limit on the total number of components you can output per-geometry shader instance. That is, you can only write out so much stuff in one execution of a GS.

For example, my HD 3300 can output 1024 vertices max. It can output 128 componets per-vertex maximum. But it cannot output 1024 vertices that each have 128 components, because the total number of components a single geometry shader can output is 16384. 1024*128 is 131072. which is rather larger than 16384.

Therefore, given my hardware, the only way to output 1024 vertices is to write 16 components or less. Even if I write 8 components, I can still only wrote 1024 vertices, because that’s the vertex limit.

If I’m only writing 64 vertices, then I can write 128 components to each of those vertices. If I write 32 vertices, I can still only write 128 components, because that’s the component limit.

I highly doubt that MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS is 128 for you. It would make no sense for MAX_GEOMETRY_VERTICES_OUT to be so large that you could never actually use it, even if you were outputting a single float. What hardware are you using?

Scratch that: it can’t be 128. The spec requires a minimum value of 1024 for MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS.

So, I think I’ve figured out my mistake.

Requirements:

  1. GEOMETRY_VERTICES_OUT must be less than MAX_GEOMETRY_OUTPUT_VERTICES

  2. MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS >= components * GEOMETRY_VERTICES_OUT

Which gives me:

  1. GEOMETRY_VERTICES_OUT <= 1024
  2. GEOMETRY_VERTICES_OUT <= 1024 / 8

So, my GEOMETRY_VERTICES_OUT must be less than 128. My dev system that had an ATI FirePro V9800 card was causing me to mis-understand as well. It gave an error stating that GEOMETRY_VERTICES_OUT must be less than MAX_GEOMETRY_OUTPUT_VERTICES only so when the nVidia system ran it, I wasn’t taking into account the other piece. By chance, part two of the equation on the ATI system just happened to be >1024 so the output vertices value of 1024 was okay.

Though, when I query GEOMETRY_VERTICES_OUT on the ATI system, it returns 0 and the nVidia system returns the valid 128 value; not sure why. Probably a bug…

ATI System for those that read this later and want clarification:

MAX_GEOMETRY_OUTPUT_VERTICES = 1024
MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = 16384

So, 16384 / 8 components > 1024; so GEOMETRY_VERTICES_OUT = 1024 was valid.

Alfonse, thanks for the reply. It came in as I was typing up my results. Yes, the MAX_GEOMETRY_OUTPUT_VERTICES on the nVidia card is 1024 as is the MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS.

The OpenGL spec is a bit tough to parse sometimes; I appreciate the help.