glMultiDrawElementsIndirect custom drawID with multiple instances per DrawElementsIndirectCommand
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
|
show 1 more comment
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
Can you explain what you mean by "a custom drawID"? Are you talking about the value ofgl_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
|
show 1 more comment
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
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
opengl
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 ofgl_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
|
show 1 more comment
Can you explain what you mean by "a custom drawID"? Are you talking about the value ofgl_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
|
show 1 more comment
1 Answer
1
active
oldest
votes
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.
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 toglDraw*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
|
show 10 more comments
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
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 toglDraw*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
|
show 10 more comments
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.
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 toglDraw*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
|
show 10 more comments
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.
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.
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 toglDraw*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
|
show 10 more comments
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 toglDraw*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
|
show 10 more comments
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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