I am rendering a primitive in Vulkan which has repeated vertices which are processed differently by the vertex shader depending on their index in the vertex buffer. All repeated vertices are consecutive, so if a, b, c are vertices the buffer might look like [a,a,a,b,b,b,c,c,c]
, and I need to be able to tell in my vertex shader whether this is the first, second or third time it's seeing the same vertex.
If I simply submit the same vertex a number of times into the vertex buffer, I can use gl_VertexIndex
(or gl_VertexID
in OpenGL) to determine what number repetition of the same vertex it is, and then process each repetition differently as needed.
However, I would like to use index buffers to avoid duplicating the vertices in memory. When using index buffers gl_VertexIndex
is the same value each time the same index appears, as it is an index into the vertex buffer which only has one copy of each vertex for index buffers to be worthwhile. This means in the vertex shader I cannot differentiate between the first, second or third repetition of a vertex.
Is there a built-in variable like gl_VertexIndex
I can use, eg gl_IndexBufferIndex
which tells me what index in the index buffer this vertex came from? Or, how many times this vertex has already been encountered in the index buffer? And if not, is there an efficient means to send this information to the vertex shader on a per-vertex basis?
According to the Vulkan Specification 1.2.146 §8.7.1, the vertex shading must be repeated for the same index unless it is guaranteed an identical result, so this should be possible:
If the same vertex is specified multiple times in a draw command (e.g. by including the same index value multiple times in an index buffer) the implementation may reuse the results of vertex shading if it can statically determine that the vertex shader invocations will produce identical results.
I need to be able to tell in my vertex shader whether this is the first, second or third time it's seeing the same vertex.
You can't. The way Vulkan (and every other rendering API) defines "the same vertex" is by the vertex index (or more specifically, by the vertex/instance index pair, but that's irrelevant for this question). If the system gets the same vertex index within a draw call, it is permitted to assume that the vertex shader will produce the same output values from that vertex, and therefore the VS invocation may be skipped thanks to the post-T&L cache.
This is what that text you quoted is saying.
If you really need to do what you're talking about, then you're going to have to do vertex fetching on your own. That is, you make the "true" vertex index array an attribute, and in the VS, you use that index to read the actual attribute data from an SSBO. This allows you to fetch the same data, despite the vertex index being different.