glMultiDrawElementsIndirect custom drawID with multiple instances per DrawElementsIndirectCommand












1















If I setup a custom ascending integer drawID vertex buffer stream for per instance data with:



glVertexAttribDivisor(drawIDVertexStreamIdx, 1)


Using glMultiDrawElementsIndirect() given:



struct DrawElementsIndirectCommand
{
uint count;
uint instanceCount;
uint firstIndex;
uint baseVertex;
uint baseInstance;
};


When setting the instanceCount to more than one, I am confused looking at old notes and online about what exactly happens regards the drawID passed to the shader?



If say there are two DrawElementsIndirectCommand records invoked from one glMultiDrawElementsIndirect(), with the first record having an instanceCount of 3, and the second an instanceCount of say 1, what do the instances actually see in the shader? (Assuming the drawID vertex stream contains 0,1,2,3 etc)



Are they supposed to see 0,1,2 for the first DrawElementsIndirectCommand record instances, and 3 for the second DrawElementsIndirectCommand record instance?



All the examples I can find online seem to specifically set instanceCount to one and rely on multiple DrawElementsIndirectCommand records which makes me now doubt this understanding is correct?



const int CustomDrawIDIdx = 1;
const int VertexCount = 4;
DrawElementsIndirectCommand drawCallRecords[2] =
{
{ VertexCount, 3, 0, 0, 0 },
{ VertexCount, 1, 0, 0, 0 },
};

...
// Attempt to set up custom drawID from a vertex attribute, where the vertex stream for it is a sequence of integers 0, 1, 2 etc
glVertexAttribIPointer(CustomDrawIDIdx, 1, GL_UNSIGNED_INT, 0, NULL);
glVertexAttribDivisor(CustomDrawIDIdx, 1);
...

glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, &drawCallRecords, 2, 0);


In the vertex shader:



layout (location = 1) in uint customDrawID;

void main()
{
bool match = (customDrawID== gl_InstanceID);
...
}


So this should cause 4 actual draw calls, as actual draw calls caused by glMultiDrawElementsIndirect() are determined by the number DrawElementsIndirectCommand records and their contained instance counts.



For each draw call gl_InstanceID should start from zero and count up for each instance, but go back to zero after each DrawElementsIndirectCommand record is processed?



So gl_InstanceID should do (0, 1, 2) for drawCallRecords[0], and then (0) for drawCallRecords[1]? What does the customDrawID do?



I am also curious if ARB_shader_draw_parameters on nVidia (GTX1070+) is still not recommended compared to using a custom drawID from a vertex stream?



*** UPDATE to reflect the answer by the very patient and helpful Nicol Bolas:



So given:



DrawElementsIndirectCommand drawCallRecords[2] =
{
{ VertexCount, 3, 0, 0, 0 },
{ VertexCount, 1, 0, 0, 3 /*baseInstance will push us along in customDrawID vertex stream*/ },
};


Then customDrawID will then do (0, 1, 2) and (3) across all instances in the multidrawindirect.



Which means that each drawn instance across the TWO draw calls, and the 3 + 1 total instances drawn (3 instances of one 'object', 1 instance of another 'object'), in one multidrawindirect call could reference completely unique transformation matrices for example. And in essence that emulates the functionality of gl_DrawID as long as you keep bumping the baseInstance like that (exclusive sum style) for each DrawElementsIndirectCommand record.



The baseInstance in each DrawElementsIndirectCommand record will push the offset into the customDrawID vertex stream, giving a customDrawID that is unique to each instance across all objects drawn.










share|improve this question

























  • Can you explain what you mean by "a custom drawID"? Are you talking about the value of gl_DrawID or the value of something else?

    – Nicol Bolas
    Nov 24 '18 at 18:31











  • By custom drawID I mean a value sourced from a vertex buffer stream not the built in gl_DrawID: openglsuperbible.com/2013/10/16/the-road-to-one-million-draws

    – iam
    Nov 24 '18 at 18:53











  • Another example is: g-truc.net/post-0518.html

    – iam
    Nov 24 '18 at 18:57











  • And slides 31-33: slideshare.net/CassEveritt/approaching-zero-driver-overhead

    – iam
    Nov 24 '18 at 19:01











  • I don't see where any of those sources say that shader_draw_parameters is "not recommended" for this purpose.

    – Nicol Bolas
    Nov 24 '18 at 19:55
















1















If I setup a custom ascending integer drawID vertex buffer stream for per instance data with:



glVertexAttribDivisor(drawIDVertexStreamIdx, 1)


Using glMultiDrawElementsIndirect() given:



struct DrawElementsIndirectCommand
{
uint count;
uint instanceCount;
uint firstIndex;
uint baseVertex;
uint baseInstance;
};


When setting the instanceCount to more than one, I am confused looking at old notes and online about what exactly happens regards the drawID passed to the shader?



If say there are two DrawElementsIndirectCommand records invoked from one glMultiDrawElementsIndirect(), with the first record having an instanceCount of 3, and the second an instanceCount of say 1, what do the instances actually see in the shader? (Assuming the drawID vertex stream contains 0,1,2,3 etc)



Are they supposed to see 0,1,2 for the first DrawElementsIndirectCommand record instances, and 3 for the second DrawElementsIndirectCommand record instance?



All the examples I can find online seem to specifically set instanceCount to one and rely on multiple DrawElementsIndirectCommand records which makes me now doubt this understanding is correct?



const int CustomDrawIDIdx = 1;
const int VertexCount = 4;
DrawElementsIndirectCommand drawCallRecords[2] =
{
{ VertexCount, 3, 0, 0, 0 },
{ VertexCount, 1, 0, 0, 0 },
};

...
// Attempt to set up custom drawID from a vertex attribute, where the vertex stream for it is a sequence of integers 0, 1, 2 etc
glVertexAttribIPointer(CustomDrawIDIdx, 1, GL_UNSIGNED_INT, 0, NULL);
glVertexAttribDivisor(CustomDrawIDIdx, 1);
...

glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, &drawCallRecords, 2, 0);


In the vertex shader:



layout (location = 1) in uint customDrawID;

void main()
{
bool match = (customDrawID== gl_InstanceID);
...
}


So this should cause 4 actual draw calls, as actual draw calls caused by glMultiDrawElementsIndirect() are determined by the number DrawElementsIndirectCommand records and their contained instance counts.



For each draw call gl_InstanceID should start from zero and count up for each instance, but go back to zero after each DrawElementsIndirectCommand record is processed?



So gl_InstanceID should do (0, 1, 2) for drawCallRecords[0], and then (0) for drawCallRecords[1]? What does the customDrawID do?



I am also curious if ARB_shader_draw_parameters on nVidia (GTX1070+) is still not recommended compared to using a custom drawID from a vertex stream?



*** UPDATE to reflect the answer by the very patient and helpful Nicol Bolas:



So given:



DrawElementsIndirectCommand drawCallRecords[2] =
{
{ VertexCount, 3, 0, 0, 0 },
{ VertexCount, 1, 0, 0, 3 /*baseInstance will push us along in customDrawID vertex stream*/ },
};


Then customDrawID will then do (0, 1, 2) and (3) across all instances in the multidrawindirect.



Which means that each drawn instance across the TWO draw calls, and the 3 + 1 total instances drawn (3 instances of one 'object', 1 instance of another 'object'), in one multidrawindirect call could reference completely unique transformation matrices for example. And in essence that emulates the functionality of gl_DrawID as long as you keep bumping the baseInstance like that (exclusive sum style) for each DrawElementsIndirectCommand record.



The baseInstance in each DrawElementsIndirectCommand record will push the offset into the customDrawID vertex stream, giving a customDrawID that is unique to each instance across all objects drawn.










share|improve this question

























  • Can you explain what you mean by "a custom drawID"? Are you talking about the value of gl_DrawID or the value of something else?

    – Nicol Bolas
    Nov 24 '18 at 18:31











  • By custom drawID I mean a value sourced from a vertex buffer stream not the built in gl_DrawID: openglsuperbible.com/2013/10/16/the-road-to-one-million-draws

    – iam
    Nov 24 '18 at 18:53











  • Another example is: g-truc.net/post-0518.html

    – iam
    Nov 24 '18 at 18:57











  • And slides 31-33: slideshare.net/CassEveritt/approaching-zero-driver-overhead

    – iam
    Nov 24 '18 at 19:01











  • I don't see where any of those sources say that shader_draw_parameters is "not recommended" for this purpose.

    – Nicol Bolas
    Nov 24 '18 at 19:55














1












1








1


0






If I setup a custom ascending integer drawID vertex buffer stream for per instance data with:



glVertexAttribDivisor(drawIDVertexStreamIdx, 1)


Using glMultiDrawElementsIndirect() given:



struct DrawElementsIndirectCommand
{
uint count;
uint instanceCount;
uint firstIndex;
uint baseVertex;
uint baseInstance;
};


When setting the instanceCount to more than one, I am confused looking at old notes and online about what exactly happens regards the drawID passed to the shader?



If say there are two DrawElementsIndirectCommand records invoked from one glMultiDrawElementsIndirect(), with the first record having an instanceCount of 3, and the second an instanceCount of say 1, what do the instances actually see in the shader? (Assuming the drawID vertex stream contains 0,1,2,3 etc)



Are they supposed to see 0,1,2 for the first DrawElementsIndirectCommand record instances, and 3 for the second DrawElementsIndirectCommand record instance?



All the examples I can find online seem to specifically set instanceCount to one and rely on multiple DrawElementsIndirectCommand records which makes me now doubt this understanding is correct?



const int CustomDrawIDIdx = 1;
const int VertexCount = 4;
DrawElementsIndirectCommand drawCallRecords[2] =
{
{ VertexCount, 3, 0, 0, 0 },
{ VertexCount, 1, 0, 0, 0 },
};

...
// Attempt to set up custom drawID from a vertex attribute, where the vertex stream for it is a sequence of integers 0, 1, 2 etc
glVertexAttribIPointer(CustomDrawIDIdx, 1, GL_UNSIGNED_INT, 0, NULL);
glVertexAttribDivisor(CustomDrawIDIdx, 1);
...

glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, &drawCallRecords, 2, 0);


In the vertex shader:



layout (location = 1) in uint customDrawID;

void main()
{
bool match = (customDrawID== gl_InstanceID);
...
}


So this should cause 4 actual draw calls, as actual draw calls caused by glMultiDrawElementsIndirect() are determined by the number DrawElementsIndirectCommand records and their contained instance counts.



For each draw call gl_InstanceID should start from zero and count up for each instance, but go back to zero after each DrawElementsIndirectCommand record is processed?



So gl_InstanceID should do (0, 1, 2) for drawCallRecords[0], and then (0) for drawCallRecords[1]? What does the customDrawID do?



I am also curious if ARB_shader_draw_parameters on nVidia (GTX1070+) is still not recommended compared to using a custom drawID from a vertex stream?



*** UPDATE to reflect the answer by the very patient and helpful Nicol Bolas:



So given:



DrawElementsIndirectCommand drawCallRecords[2] =
{
{ VertexCount, 3, 0, 0, 0 },
{ VertexCount, 1, 0, 0, 3 /*baseInstance will push us along in customDrawID vertex stream*/ },
};


Then customDrawID will then do (0, 1, 2) and (3) across all instances in the multidrawindirect.



Which means that each drawn instance across the TWO draw calls, and the 3 + 1 total instances drawn (3 instances of one 'object', 1 instance of another 'object'), in one multidrawindirect call could reference completely unique transformation matrices for example. And in essence that emulates the functionality of gl_DrawID as long as you keep bumping the baseInstance like that (exclusive sum style) for each DrawElementsIndirectCommand record.



The baseInstance in each DrawElementsIndirectCommand record will push the offset into the customDrawID vertex stream, giving a customDrawID that is unique to each instance across all objects drawn.










share|improve this question
















If I setup a custom ascending integer drawID vertex buffer stream for per instance data with:



glVertexAttribDivisor(drawIDVertexStreamIdx, 1)


Using glMultiDrawElementsIndirect() given:



struct DrawElementsIndirectCommand
{
uint count;
uint instanceCount;
uint firstIndex;
uint baseVertex;
uint baseInstance;
};


When setting the instanceCount to more than one, I am confused looking at old notes and online about what exactly happens regards the drawID passed to the shader?



If say there are two DrawElementsIndirectCommand records invoked from one glMultiDrawElementsIndirect(), with the first record having an instanceCount of 3, and the second an instanceCount of say 1, what do the instances actually see in the shader? (Assuming the drawID vertex stream contains 0,1,2,3 etc)



Are they supposed to see 0,1,2 for the first DrawElementsIndirectCommand record instances, and 3 for the second DrawElementsIndirectCommand record instance?



All the examples I can find online seem to specifically set instanceCount to one and rely on multiple DrawElementsIndirectCommand records which makes me now doubt this understanding is correct?



const int CustomDrawIDIdx = 1;
const int VertexCount = 4;
DrawElementsIndirectCommand drawCallRecords[2] =
{
{ VertexCount, 3, 0, 0, 0 },
{ VertexCount, 1, 0, 0, 0 },
};

...
// Attempt to set up custom drawID from a vertex attribute, where the vertex stream for it is a sequence of integers 0, 1, 2 etc
glVertexAttribIPointer(CustomDrawIDIdx, 1, GL_UNSIGNED_INT, 0, NULL);
glVertexAttribDivisor(CustomDrawIDIdx, 1);
...

glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, &drawCallRecords, 2, 0);


In the vertex shader:



layout (location = 1) in uint customDrawID;

void main()
{
bool match = (customDrawID== gl_InstanceID);
...
}


So this should cause 4 actual draw calls, as actual draw calls caused by glMultiDrawElementsIndirect() are determined by the number DrawElementsIndirectCommand records and their contained instance counts.



For each draw call gl_InstanceID should start from zero and count up for each instance, but go back to zero after each DrawElementsIndirectCommand record is processed?



So gl_InstanceID should do (0, 1, 2) for drawCallRecords[0], and then (0) for drawCallRecords[1]? What does the customDrawID do?



I am also curious if ARB_shader_draw_parameters on nVidia (GTX1070+) is still not recommended compared to using a custom drawID from a vertex stream?



*** UPDATE to reflect the answer by the very patient and helpful Nicol Bolas:



So given:



DrawElementsIndirectCommand drawCallRecords[2] =
{
{ VertexCount, 3, 0, 0, 0 },
{ VertexCount, 1, 0, 0, 3 /*baseInstance will push us along in customDrawID vertex stream*/ },
};


Then customDrawID will then do (0, 1, 2) and (3) across all instances in the multidrawindirect.



Which means that each drawn instance across the TWO draw calls, and the 3 + 1 total instances drawn (3 instances of one 'object', 1 instance of another 'object'), in one multidrawindirect call could reference completely unique transformation matrices for example. And in essence that emulates the functionality of gl_DrawID as long as you keep bumping the baseInstance like that (exclusive sum style) for each DrawElementsIndirectCommand record.



The baseInstance in each DrawElementsIndirectCommand record will push the offset into the customDrawID vertex stream, giving a customDrawID that is unique to each instance across all objects drawn.







opengl






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 25 '18 at 6:47







iam

















asked Nov 24 '18 at 17:49









iamiam

6471718




6471718













  • Can you explain what you mean by "a custom drawID"? Are you talking about the value of gl_DrawID or the value of something else?

    – Nicol Bolas
    Nov 24 '18 at 18:31











  • By custom drawID I mean a value sourced from a vertex buffer stream not the built in gl_DrawID: openglsuperbible.com/2013/10/16/the-road-to-one-million-draws

    – iam
    Nov 24 '18 at 18:53











  • Another example is: g-truc.net/post-0518.html

    – iam
    Nov 24 '18 at 18:57











  • And slides 31-33: slideshare.net/CassEveritt/approaching-zero-driver-overhead

    – iam
    Nov 24 '18 at 19:01











  • I don't see where any of those sources say that shader_draw_parameters is "not recommended" for this purpose.

    – Nicol Bolas
    Nov 24 '18 at 19:55



















  • Can you explain what you mean by "a custom drawID"? Are you talking about the value of gl_DrawID or the value of something else?

    – Nicol Bolas
    Nov 24 '18 at 18:31











  • By custom drawID I mean a value sourced from a vertex buffer stream not the built in gl_DrawID: openglsuperbible.com/2013/10/16/the-road-to-one-million-draws

    – iam
    Nov 24 '18 at 18:53











  • Another example is: g-truc.net/post-0518.html

    – iam
    Nov 24 '18 at 18:57











  • And slides 31-33: slideshare.net/CassEveritt/approaching-zero-driver-overhead

    – iam
    Nov 24 '18 at 19:01











  • I don't see where any of those sources say that shader_draw_parameters is "not recommended" for this purpose.

    – Nicol Bolas
    Nov 24 '18 at 19:55

















Can you explain what you mean by "a custom drawID"? Are you talking about the value of gl_DrawID or the value of something else?

– Nicol Bolas
Nov 24 '18 at 18:31





Can you explain what you mean by "a custom drawID"? Are you talking about the value of gl_DrawID or the value of something else?

– Nicol Bolas
Nov 24 '18 at 18:31













By custom drawID I mean a value sourced from a vertex buffer stream not the built in gl_DrawID: openglsuperbible.com/2013/10/16/the-road-to-one-million-draws

– iam
Nov 24 '18 at 18:53





By custom drawID I mean a value sourced from a vertex buffer stream not the built in gl_DrawID: openglsuperbible.com/2013/10/16/the-road-to-one-million-draws

– iam
Nov 24 '18 at 18:53













Another example is: g-truc.net/post-0518.html

– iam
Nov 24 '18 at 18:57





Another example is: g-truc.net/post-0518.html

– iam
Nov 24 '18 at 18:57













And slides 31-33: slideshare.net/CassEveritt/approaching-zero-driver-overhead

– iam
Nov 24 '18 at 19:01





And slides 31-33: slideshare.net/CassEveritt/approaching-zero-driver-overhead

– iam
Nov 24 '18 at 19:01













I don't see where any of those sources say that shader_draw_parameters is "not recommended" for this purpose.

– Nicol Bolas
Nov 24 '18 at 19:55





I don't see where any of those sources say that shader_draw_parameters is "not recommended" for this purpose.

– Nicol Bolas
Nov 24 '18 at 19:55












1 Answer
1






active

oldest

votes


















3















So this should cause 4 actual draw calls, as actual draw calls caused by glMultiDrawElementsIndirect() are determined by the number DrawElementsIndirectCommand records and their contained instance counts.




No. Instances and "draw calls" are not the same thing.



A single draw call is defined as if by a call to glDraw*InstancedBaseVertexBaseInstance; that's what happens when the system reads a single entry from the array of draw data. That single draw call includes all instances. Instancing is a thing that happens within a draw call.



This is also why per-instance values are not guaranteed to be dynamically uniform expressions.



Individual draws within a multi-draw command are, gl_DrawID aside, completely separate from one another. They do not interact. The values your shader gets for instanced arrays or gl_InstanceID would be no different from issuing each draw call separately.



Your "custom drawID" is not a draw ID at all; it is an instanced array value. Therefore, it follows the rules of instancing, and cares nothing for which draw call it is in.






bool match = (customDrawID== gl_InstanceID); 



No.



Even if the actual array you use to feed customDrawID is just a zero-based integer index, instances arrays and gl_InstanceID don't work the same way.



gl_InstanceID ignores the base instance. Instance arrays do not. As such, the instance value fetched from any instance array will always be offset first by the base instance.



So if you want the customDrawID for a specific draw call to start from a particular value, then you set baseInstance to be the instance index of that particular value. So given a zero-based integer index array, if you want a particular draw call to have its first instance receive the customDrawID value of "3", you set baseInstance to 3.






share|improve this answer


























  • It's specifically the behaviour of a 'custom drawID' sourced from a vertex buffer stream/attribute (where the vertex buffer is a list of sequential integers) that I am interested in (so I can actually profile it against gl_DrawID correctly).

    – iam
    Nov 25 '18 at 3:53











  • @iam: That only affects how you use my answer. Your "custom drawID" is not a draw ID; it's just an instanced value, and therefore acts in accord with the rules of instancing. Which I state in the first and last paragraphs.

    – Nicol Bolas
    Nov 25 '18 at 4:07













  • Sorry this isn't clear to me still. With "instances all happen within a draw call" does that mean one DrawElementsIndirectCommand record is a draw call or all DrawElementsIndirectCommand records issued from one glMultiDrawElementsIndirect() are counted as one draw call from the instancing point of view? In the former case I would then expect to see (0, 0, 0) and (0) as the custom drawID in the example I state in the question, in the latter I would expect (0, 1, 2) and (3).

    – iam
    Nov 25 '18 at 4:48











  • Or actually are you saying I would see (0, 1, 2) and (0). And that without using the real gl_drawID there is no way to differentiate between the DrawElementsIndirectCommand records?

    – iam
    Nov 25 '18 at 4:51











  • @iam: What you call "records" in your multidraw command are more correctly called "draw calls". Because that's what they are: indirect rendering is defined exactly as if the implementation read the data structure and made a call to glDraw*InstancedBaseVertexBaseInstance with the parameters read from the data structure. A multi-draw-indirect call is just doing that more than once. But each draw's parameters are completely independent of any other draw's parameters.

    – Nicol Bolas
    Nov 25 '18 at 4:57













Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53460871%2fglmultidrawelementsindirect-custom-drawid-with-multiple-instances-per-drawelemen%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3















So this should cause 4 actual draw calls, as actual draw calls caused by glMultiDrawElementsIndirect() are determined by the number DrawElementsIndirectCommand records and their contained instance counts.




No. Instances and "draw calls" are not the same thing.



A single draw call is defined as if by a call to glDraw*InstancedBaseVertexBaseInstance; that's what happens when the system reads a single entry from the array of draw data. That single draw call includes all instances. Instancing is a thing that happens within a draw call.



This is also why per-instance values are not guaranteed to be dynamically uniform expressions.



Individual draws within a multi-draw command are, gl_DrawID aside, completely separate from one another. They do not interact. The values your shader gets for instanced arrays or gl_InstanceID would be no different from issuing each draw call separately.



Your "custom drawID" is not a draw ID at all; it is an instanced array value. Therefore, it follows the rules of instancing, and cares nothing for which draw call it is in.






bool match = (customDrawID== gl_InstanceID); 



No.



Even if the actual array you use to feed customDrawID is just a zero-based integer index, instances arrays and gl_InstanceID don't work the same way.



gl_InstanceID ignores the base instance. Instance arrays do not. As such, the instance value fetched from any instance array will always be offset first by the base instance.



So if you want the customDrawID for a specific draw call to start from a particular value, then you set baseInstance to be the instance index of that particular value. So given a zero-based integer index array, if you want a particular draw call to have its first instance receive the customDrawID value of "3", you set baseInstance to 3.






share|improve this answer


























  • It's specifically the behaviour of a 'custom drawID' sourced from a vertex buffer stream/attribute (where the vertex buffer is a list of sequential integers) that I am interested in (so I can actually profile it against gl_DrawID correctly).

    – iam
    Nov 25 '18 at 3:53











  • @iam: That only affects how you use my answer. Your "custom drawID" is not a draw ID; it's just an instanced value, and therefore acts in accord with the rules of instancing. Which I state in the first and last paragraphs.

    – Nicol Bolas
    Nov 25 '18 at 4:07













  • Sorry this isn't clear to me still. With "instances all happen within a draw call" does that mean one DrawElementsIndirectCommand record is a draw call or all DrawElementsIndirectCommand records issued from one glMultiDrawElementsIndirect() are counted as one draw call from the instancing point of view? In the former case I would then expect to see (0, 0, 0) and (0) as the custom drawID in the example I state in the question, in the latter I would expect (0, 1, 2) and (3).

    – iam
    Nov 25 '18 at 4:48











  • Or actually are you saying I would see (0, 1, 2) and (0). And that without using the real gl_drawID there is no way to differentiate between the DrawElementsIndirectCommand records?

    – iam
    Nov 25 '18 at 4:51











  • @iam: What you call "records" in your multidraw command are more correctly called "draw calls". Because that's what they are: indirect rendering is defined exactly as if the implementation read the data structure and made a call to glDraw*InstancedBaseVertexBaseInstance with the parameters read from the data structure. A multi-draw-indirect call is just doing that more than once. But each draw's parameters are completely independent of any other draw's parameters.

    – Nicol Bolas
    Nov 25 '18 at 4:57


















3















So this should cause 4 actual draw calls, as actual draw calls caused by glMultiDrawElementsIndirect() are determined by the number DrawElementsIndirectCommand records and their contained instance counts.




No. Instances and "draw calls" are not the same thing.



A single draw call is defined as if by a call to glDraw*InstancedBaseVertexBaseInstance; that's what happens when the system reads a single entry from the array of draw data. That single draw call includes all instances. Instancing is a thing that happens within a draw call.



This is also why per-instance values are not guaranteed to be dynamically uniform expressions.



Individual draws within a multi-draw command are, gl_DrawID aside, completely separate from one another. They do not interact. The values your shader gets for instanced arrays or gl_InstanceID would be no different from issuing each draw call separately.



Your "custom drawID" is not a draw ID at all; it is an instanced array value. Therefore, it follows the rules of instancing, and cares nothing for which draw call it is in.






bool match = (customDrawID== gl_InstanceID); 



No.



Even if the actual array you use to feed customDrawID is just a zero-based integer index, instances arrays and gl_InstanceID don't work the same way.



gl_InstanceID ignores the base instance. Instance arrays do not. As such, the instance value fetched from any instance array will always be offset first by the base instance.



So if you want the customDrawID for a specific draw call to start from a particular value, then you set baseInstance to be the instance index of that particular value. So given a zero-based integer index array, if you want a particular draw call to have its first instance receive the customDrawID value of "3", you set baseInstance to 3.






share|improve this answer


























  • It's specifically the behaviour of a 'custom drawID' sourced from a vertex buffer stream/attribute (where the vertex buffer is a list of sequential integers) that I am interested in (so I can actually profile it against gl_DrawID correctly).

    – iam
    Nov 25 '18 at 3:53











  • @iam: That only affects how you use my answer. Your "custom drawID" is not a draw ID; it's just an instanced value, and therefore acts in accord with the rules of instancing. Which I state in the first and last paragraphs.

    – Nicol Bolas
    Nov 25 '18 at 4:07













  • Sorry this isn't clear to me still. With "instances all happen within a draw call" does that mean one DrawElementsIndirectCommand record is a draw call or all DrawElementsIndirectCommand records issued from one glMultiDrawElementsIndirect() are counted as one draw call from the instancing point of view? In the former case I would then expect to see (0, 0, 0) and (0) as the custom drawID in the example I state in the question, in the latter I would expect (0, 1, 2) and (3).

    – iam
    Nov 25 '18 at 4:48











  • Or actually are you saying I would see (0, 1, 2) and (0). And that without using the real gl_drawID there is no way to differentiate between the DrawElementsIndirectCommand records?

    – iam
    Nov 25 '18 at 4:51











  • @iam: What you call "records" in your multidraw command are more correctly called "draw calls". Because that's what they are: indirect rendering is defined exactly as if the implementation read the data structure and made a call to glDraw*InstancedBaseVertexBaseInstance with the parameters read from the data structure. A multi-draw-indirect call is just doing that more than once. But each draw's parameters are completely independent of any other draw's parameters.

    – Nicol Bolas
    Nov 25 '18 at 4:57
















3












3








3








So this should cause 4 actual draw calls, as actual draw calls caused by glMultiDrawElementsIndirect() are determined by the number DrawElementsIndirectCommand records and their contained instance counts.




No. Instances and "draw calls" are not the same thing.



A single draw call is defined as if by a call to glDraw*InstancedBaseVertexBaseInstance; that's what happens when the system reads a single entry from the array of draw data. That single draw call includes all instances. Instancing is a thing that happens within a draw call.



This is also why per-instance values are not guaranteed to be dynamically uniform expressions.



Individual draws within a multi-draw command are, gl_DrawID aside, completely separate from one another. They do not interact. The values your shader gets for instanced arrays or gl_InstanceID would be no different from issuing each draw call separately.



Your "custom drawID" is not a draw ID at all; it is an instanced array value. Therefore, it follows the rules of instancing, and cares nothing for which draw call it is in.






bool match = (customDrawID== gl_InstanceID); 



No.



Even if the actual array you use to feed customDrawID is just a zero-based integer index, instances arrays and gl_InstanceID don't work the same way.



gl_InstanceID ignores the base instance. Instance arrays do not. As such, the instance value fetched from any instance array will always be offset first by the base instance.



So if you want the customDrawID for a specific draw call to start from a particular value, then you set baseInstance to be the instance index of that particular value. So given a zero-based integer index array, if you want a particular draw call to have its first instance receive the customDrawID value of "3", you set baseInstance to 3.






share|improve this answer
















So this should cause 4 actual draw calls, as actual draw calls caused by glMultiDrawElementsIndirect() are determined by the number DrawElementsIndirectCommand records and their contained instance counts.




No. Instances and "draw calls" are not the same thing.



A single draw call is defined as if by a call to glDraw*InstancedBaseVertexBaseInstance; that's what happens when the system reads a single entry from the array of draw data. That single draw call includes all instances. Instancing is a thing that happens within a draw call.



This is also why per-instance values are not guaranteed to be dynamically uniform expressions.



Individual draws within a multi-draw command are, gl_DrawID aside, completely separate from one another. They do not interact. The values your shader gets for instanced arrays or gl_InstanceID would be no different from issuing each draw call separately.



Your "custom drawID" is not a draw ID at all; it is an instanced array value. Therefore, it follows the rules of instancing, and cares nothing for which draw call it is in.






bool match = (customDrawID== gl_InstanceID); 



No.



Even if the actual array you use to feed customDrawID is just a zero-based integer index, instances arrays and gl_InstanceID don't work the same way.



gl_InstanceID ignores the base instance. Instance arrays do not. As such, the instance value fetched from any instance array will always be offset first by the base instance.



So if you want the customDrawID for a specific draw call to start from a particular value, then you set baseInstance to be the instance index of that particular value. So given a zero-based integer index array, if you want a particular draw call to have its first instance receive the customDrawID value of "3", you set baseInstance to 3.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 25 '18 at 6:21

























answered Nov 24 '18 at 18:30









Nicol BolasNicol Bolas

289k33480651




289k33480651













  • It's specifically the behaviour of a 'custom drawID' sourced from a vertex buffer stream/attribute (where the vertex buffer is a list of sequential integers) that I am interested in (so I can actually profile it against gl_DrawID correctly).

    – iam
    Nov 25 '18 at 3:53











  • @iam: That only affects how you use my answer. Your "custom drawID" is not a draw ID; it's just an instanced value, and therefore acts in accord with the rules of instancing. Which I state in the first and last paragraphs.

    – Nicol Bolas
    Nov 25 '18 at 4:07













  • Sorry this isn't clear to me still. With "instances all happen within a draw call" does that mean one DrawElementsIndirectCommand record is a draw call or all DrawElementsIndirectCommand records issued from one glMultiDrawElementsIndirect() are counted as one draw call from the instancing point of view? In the former case I would then expect to see (0, 0, 0) and (0) as the custom drawID in the example I state in the question, in the latter I would expect (0, 1, 2) and (3).

    – iam
    Nov 25 '18 at 4:48











  • Or actually are you saying I would see (0, 1, 2) and (0). And that without using the real gl_drawID there is no way to differentiate between the DrawElementsIndirectCommand records?

    – iam
    Nov 25 '18 at 4:51











  • @iam: What you call "records" in your multidraw command are more correctly called "draw calls". Because that's what they are: indirect rendering is defined exactly as if the implementation read the data structure and made a call to glDraw*InstancedBaseVertexBaseInstance with the parameters read from the data structure. A multi-draw-indirect call is just doing that more than once. But each draw's parameters are completely independent of any other draw's parameters.

    – Nicol Bolas
    Nov 25 '18 at 4:57





















  • It's specifically the behaviour of a 'custom drawID' sourced from a vertex buffer stream/attribute (where the vertex buffer is a list of sequential integers) that I am interested in (so I can actually profile it against gl_DrawID correctly).

    – iam
    Nov 25 '18 at 3:53











  • @iam: That only affects how you use my answer. Your "custom drawID" is not a draw ID; it's just an instanced value, and therefore acts in accord with the rules of instancing. Which I state in the first and last paragraphs.

    – Nicol Bolas
    Nov 25 '18 at 4:07













  • Sorry this isn't clear to me still. With "instances all happen within a draw call" does that mean one DrawElementsIndirectCommand record is a draw call or all DrawElementsIndirectCommand records issued from one glMultiDrawElementsIndirect() are counted as one draw call from the instancing point of view? In the former case I would then expect to see (0, 0, 0) and (0) as the custom drawID in the example I state in the question, in the latter I would expect (0, 1, 2) and (3).

    – iam
    Nov 25 '18 at 4:48











  • Or actually are you saying I would see (0, 1, 2) and (0). And that without using the real gl_drawID there is no way to differentiate between the DrawElementsIndirectCommand records?

    – iam
    Nov 25 '18 at 4:51











  • @iam: What you call "records" in your multidraw command are more correctly called "draw calls". Because that's what they are: indirect rendering is defined exactly as if the implementation read the data structure and made a call to glDraw*InstancedBaseVertexBaseInstance with the parameters read from the data structure. A multi-draw-indirect call is just doing that more than once. But each draw's parameters are completely independent of any other draw's parameters.

    – Nicol Bolas
    Nov 25 '18 at 4:57



















It's specifically the behaviour of a 'custom drawID' sourced from a vertex buffer stream/attribute (where the vertex buffer is a list of sequential integers) that I am interested in (so I can actually profile it against gl_DrawID correctly).

– iam
Nov 25 '18 at 3:53





It's specifically the behaviour of a 'custom drawID' sourced from a vertex buffer stream/attribute (where the vertex buffer is a list of sequential integers) that I am interested in (so I can actually profile it against gl_DrawID correctly).

– iam
Nov 25 '18 at 3:53













@iam: That only affects how you use my answer. Your "custom drawID" is not a draw ID; it's just an instanced value, and therefore acts in accord with the rules of instancing. Which I state in the first and last paragraphs.

– Nicol Bolas
Nov 25 '18 at 4:07







@iam: That only affects how you use my answer. Your "custom drawID" is not a draw ID; it's just an instanced value, and therefore acts in accord with the rules of instancing. Which I state in the first and last paragraphs.

– Nicol Bolas
Nov 25 '18 at 4:07















Sorry this isn't clear to me still. With "instances all happen within a draw call" does that mean one DrawElementsIndirectCommand record is a draw call or all DrawElementsIndirectCommand records issued from one glMultiDrawElementsIndirect() are counted as one draw call from the instancing point of view? In the former case I would then expect to see (0, 0, 0) and (0) as the custom drawID in the example I state in the question, in the latter I would expect (0, 1, 2) and (3).

– iam
Nov 25 '18 at 4:48





Sorry this isn't clear to me still. With "instances all happen within a draw call" does that mean one DrawElementsIndirectCommand record is a draw call or all DrawElementsIndirectCommand records issued from one glMultiDrawElementsIndirect() are counted as one draw call from the instancing point of view? In the former case I would then expect to see (0, 0, 0) and (0) as the custom drawID in the example I state in the question, in the latter I would expect (0, 1, 2) and (3).

– iam
Nov 25 '18 at 4:48













Or actually are you saying I would see (0, 1, 2) and (0). And that without using the real gl_drawID there is no way to differentiate between the DrawElementsIndirectCommand records?

– iam
Nov 25 '18 at 4:51





Or actually are you saying I would see (0, 1, 2) and (0). And that without using the real gl_drawID there is no way to differentiate between the DrawElementsIndirectCommand records?

– iam
Nov 25 '18 at 4:51













@iam: What you call "records" in your multidraw command are more correctly called "draw calls". Because that's what they are: indirect rendering is defined exactly as if the implementation read the data structure and made a call to glDraw*InstancedBaseVertexBaseInstance with the parameters read from the data structure. A multi-draw-indirect call is just doing that more than once. But each draw's parameters are completely independent of any other draw's parameters.

– Nicol Bolas
Nov 25 '18 at 4:57







@iam: What you call "records" in your multidraw command are more correctly called "draw calls". Because that's what they are: indirect rendering is defined exactly as if the implementation read the data structure and made a call to glDraw*InstancedBaseVertexBaseInstance with the parameters read from the data structure. A multi-draw-indirect call is just doing that more than once. But each draw's parameters are completely independent of any other draw's parameters.

– Nicol Bolas
Nov 25 '18 at 4:57






















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53460871%2fglmultidrawelementsindirect-custom-drawid-with-multiple-instances-per-drawelemen%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Costa Masnaga

Fotorealismo

Sidney Franklin