Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 2 of 2 FirstFirst 12
Results 11 to 17 of 17

Thread: Primitive Restart with a twist

  1. #11
    Advanced Member Frequent Contributor
    Join Date
    Apr 2009
    Posts
    578
    This suggestion is much more (for me) than a convenience. This is essentially providing a (simple) means to specify a value that changes rarely. Alfhoneses suggestion that rather than making the index follow, but have another value running around that increments whenever primitive restart happens has legs in it and not a bad idea; it just means that one gets the value through another lookup into an array, buffer object or something else. My suggestion with or without Alfhonses modification to it means that the entries in the vertex cache should be discarded at primitive restart. For my use case, that will have no impact on performance because a fixed primitive uses the same value. In general, this idea is just to avoid using up the extra memory and attribute slot needed to get the same functionality. Doing it the way I have to now, the vertex cache is a miss anyways.

  2. #12
    Member Regular Contributor malexander's Avatar
    Join Date
    Aug 2009
    Location
    Ontario
    Posts
    302
    Not that I'm adverse to any of the suggestions above, I can see cases where they would be useful. But in the interests of discussion, if it changes rarely, would drawing them as separate batches with a uniform change between them suffice? Or perhaps a GLSL "gl_ArrayID" extension for glMultiDrawArrays/Elements(), with geometry with the same attribute grouped together?

  3. #13
    Advanced Member Frequent Contributor
    Join Date
    Apr 2009
    Posts
    578
    Rarely in my case, and to what wish to apply this, means that the indices named between the primitive restart are disjoint, so for my use case the vertex cache issue is mute. For record, my use case is user interfaces, where the index is an index for "what node" to use... UI drawing has a tendency to have an enormous number of nodes where each node does not have a huge number of triangles to it... so breaking each node into a separate draw call is performance suicide.

    Another way to get similar to what I want is to add glMultiDrawElements the ability to specify (or have it given) for each index range,


    glMultiDrawElements(mode, count, primitivetype, indices, primcount);


    is functionally equivalent to

    Code :
    for(unsigned int i=0; i<primcount; ++i)
    {
       "gl_SomeNiceName=i";
       glDrawElements(mode, count[i], primitivetype, indices[i]);
    }

    this would also give me what I am after, but I prefer the primitive restart index because glMultiDrawElements method forces the bookkeeping updating of the arrays to use more than the primitive restart way in my use case.
    Last edited by kRogue; 05-03-2013 at 02:59 AM.

  4. #14
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,136
    This would potentially break with GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT indices; how do you specify a value of gl_SomeNiceName greater than 255 or 65535 in those cases?

    If you want to have an input attribute that changes rarely, you can use glVertexAttrib calls to set it, with much greater flexibility but admittedly at the cost of breaking a batch.

  5. #15
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948
    If you want to have an input attribute that changes rarely, you can use glVertexAttrib calls to set it, with much greater flexibility but admittedly at the cost of breaking a batch.
    Has anyone done any kind of comparative performance analysis between setting a uniform value and setting a non-array attribute?

  6. #16
    Junior Member Regular Contributor
    Join Date
    Dec 2009
    Posts
    198
    Quote Originally Posted by Alfonse Reinheart View Post
    Has anyone done any kind of comparative performance analysis between setting a uniform value and setting a non-array attribute?
    Nvidia called this "pseudo instancing", and showed some significant performance gains on old GPUs by using vertex attributes. Performance on DX10+ GPUs may be different.

  7. #17
    Advanced Member Frequent Contributor
    Join Date
    Apr 2009
    Posts
    578
    This would potentially break with GL_UNSIGNED_BYTE or GL_UNSIGNED_SHORT indices; how do you specify a value of gl_SomeNiceName greater than 255 or 65535 in those cases?
    Break is not the correct word, the correct word is that it is much more limited. The value taken from the index stream has the range by the index stream type, thus if drawing with GL_UNSIGNED_BYTE, then the value is an integer in the range [0,255] and for GL_UNSIGNED_SHORT is it in integer in the rage [0, 65535].

    Alfonse's suggestion of having the value start at 0 and increment whenever restart is encountered is nice though, and though using that would be harder, it is growing on me.

    Additionally, looking at the way of tweaking
    glMultiDrawElements, one can see that there are roads open for other tweaks. Another way forward is a draw_indirect2 idea as follows by tweaking GL_ARB_draw_indirect

    Code :
     
    typedef struct {   GLuint count;   GLuint primCount;   GLuint firstIndex;   GLint  baseVertex;   GLuint reservedMustBeZero;   GLuint someNiceName;} DrawElements2IndirectCommand
     
    DrawElementsIndirect2(enum mode, enum type, const void *indirect);means:
    DrawElements2IndirectCommand *cmd = (DrawElementsIndirectCommand *)indirect;
    "gl_SomeNiceName=someNiceName";
    DrawElementsInstancedBaseVertex(mode, cmd->count, type, cmd->firstIndex * size-of-type, cmd->primCount, cmd->baseVertex);


    which by itself is not so interesting, but then augment
    GL_ARB_multi_draw_indirect to a GL_ARB_multi_draw_indirect2. Going further, the data for someNiceName does NOT then really need to be a 32-bit unsigned integer. Instead it can be like a "pseudo-attribute", a munge of bytes and the DrawElementsIndirect2 (and MultiDrawElementsIndirect2) would then have further arguments specifying how to interpret that munge of bytes as follows:

    Code :
    typedef struct {   
       GLuint count;  
       GLuint primCount;  
       GLuint firstIndex;  
       GLint  baseVertex;  
       GLuint reservedMustBeZero;   
       GLubyte someNiceName[]; //variable length
    } DrawElements2IndirectCommand;
     
    DrawElementsIndirect2(enum mode, enum type, const void *indirect);means:
    DrawElements2IndirectCommand *cmd = (DrawElementsIndirectCommand *)indirect;
    "gl_SomeNiceName=someNiceName";
    DrawElementsInstancedBaseVertex(mode, cmd->count, type, cmd->firstIndex * size-of-type, cmd->primCount, cmd->baseVertex, someNiceNameSize, someNiceNameType, someNiceNameNormalized);


    where
    someNiceNameSize, someNiceNameType, someNiceNameNormalized specify, analogous to VertexAttribPointerhow to interpret the bytes at the end of the structure.



Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •