0

This comes out of what Nintendo is doing with their GX interface...

In GX, you have a CP command to set the primitive type, followed by the vertex count, followed by the vertex data described by vertex attributes.
This would be followed by another primitive type.

In hex, this would look something like:

90 0003
00 0000 0000 0000
00 0001 0001 0001
00 0002 0002 0002

0x90 describes a triangle primitive while 0x0003 describes 3 contained vertexes (or facepoints).

The actual facepoints are described by the attributes:
0x00 would be the XF influence matrix index
0x0000 would be the vertice index
0x0000 would be the normal index
0x0000 would be the UV[0] index

Note: the attributes could also describe many more types of indices, or even direct data.

So I was wondering if there was a way to pass this data directly to a buffer and operate on it via the GPU.
(Of course some conversion would be needed to make things compatible)

Tcll
  • 7,140
  • 1
  • 20
  • 23
  • I see this was marked as a possible duplicate, but I don't see the linked question mentioning anything about changing primitives on the fly... yes this deals with indexing, which is more than already supported, but that's not the focus of this question. – Tcll Dec 16 '16 at 03:58
  • 1
    The only reason the GPU can't process that vertex data as is is because each vertex's data is not one index but several. So multi-indexing techniques are exactly what you need. It's simply a matter of adapting it to the specifics of the GameCube. – Nicol Bolas Dec 16 '16 at 04:22

1 Answers1

2

You can use the ability of more advanced hardware to allow the use of multiple indices. This requires explicit shader code. It also requires that the shader know and understand the format of the data, so that it can process it correctly. Some of this description can be handled through uniforms, but be aware that in-shader logic will be done for every vertex. So building a shader specifically around a format would probably be more efficient.

The biggest problem you have is that each vertex's data in the array is oddly formatted. You can have mis-aligned shorts and so forth. So processing it requires extra care. To handle the 7-byte vertices as shown above, you would need to do this:

uniform usamplerBuffer vertexData; //Format is unsigned bytes.

uniform samplerBuffer positionArray;
uniform samplerBuffer normalArray;
uniform samplerBuffer texCoordArray;

uint ExtractShortFromVertex(in uint firstIndex)
{
    uint highByte = texelFetch(vertexData, firstIndex);
    uint lowByte = texelFetch(vertexData, firstIndex + 1);
    return (highByte << 8) | lowByte;
}

void main()
{
    uint baseIndex = gl_VertexID * 7;
    uint matrixIndex =      texelFetch(vertexData, baseIndex);

    uint positionIndex =    ExtractShortFromVertex(baseIndex + 1);
    uint normalIndex =      ExtractShortFromVertex(baseIndex + 3);
    uint texCoordIndex =    ExtractShortFromVertex(baseIndex + 5);

    vec4 position =     texelFetch(positionArray, positionIndex);
    vec4 normal =       texelFetch(normalArray, normalIndex);
    vec4 texCoord =     texelFetch(texCoordArray, texCoordIndex);

    //Do your stuff
}

Obviously, if you have direct data in there, you're going to need specialized logic to extract it.

vertexData is a buffer object (accessed as a buffer texture) which stores the GX data as you presented it. Of course, it should point only to the actual per-vertex data, not to the 90 0003 prefix. That you will still have to handle manually. So the CPU will still need fast access to the data, so that when it calls glDrawArrays, it can pass the right primitive and draw count.

Note that the format for vertexData is GL_R8UI, since we need byte-wise access.

Dealing with "direct data" is more troublesome, since that requires converting a sequence of bytes into a complex type like a float or somesuch. But modern GLSL does have a number of functions that ought to be able to get that done.

It might be possible to use Compute Shaders to process certain aspects of each rendering command. The goal here would be to turn them into indirect rendering commands.

The problem is that, while indirect commands can have different vertex counts, what they cannot do is change uniform data, programs, or the primitive type. So there would be no way to build a sequence of indirect commands where the format changes between different commands. Not without the CPU knowing about it and issuing different draw call parameters based on it.

At which point, you may as well let the CPU just process the commands itself.

Community
  • 1
  • 1
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Alright thank you, at best it looks like I'll have to organize the primitives into arrays and use primitive reset to deal with the indexes from there... I do believe there was something that could use vertex attributes to deal with the indexes in the format as is, not sure if I have that reference though, but I'll definitely consider your suggestions :) – Tcll Dec 16 '16 at 12:46
  • I know something I might be able to do, but it'll put a bit more work on the GPU, not sure if per frame is a side effect... but pass the entire command list to a shader and process each facepoint from there (converting to triangles manually). If per frame can't be avoided by that though, converting to primitive arrays once on the CPU might just be the best option. – Tcll Dec 16 '16 at 13:07
  • Yes I do have that reference: (line 234) https://www.dropbox.com/s/z8a8v3urgr2dtdr/3d_viewer.py?dl=0 it's not with indices, but it can be upgraded. – Tcll Dec 16 '16 at 15:18
  • 1
    @Tcll: "*I do believe there was something that could use vertex attributes to deal with the indexes in the format as is*" One reason why I avoided trying to make the array of GX vertex values into attributes directly is that they're *misaligned*. And misaligned attributes, while *technically* legal in OpenGL, can lead to degraded performance. – Nicol Bolas Dec 16 '16 at 16:00
  • Ah so for better performance, it's simply better to split everything up and assign everything manually e.g. vert indices, normal indices, weight indices, etc. Thanks for the clarification :) – Tcll Dec 16 '16 at 19:42