#glMultiDrawArraysIndirect Draws One Instance
32 messages · Page 1 of 1 (latest)
In my constructor:
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &IndirectBuffer);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(16)); // I've neglected to wrap glVertexAttribPointer, so this is all manually done in the constructor, don't mind it
glEnableVertexAttribArray(1);
glVertexAttribDivisor(1, 1);
glBindVertexArray(0);
In the draw method:
if (CommandBuffer.empty()) [[unlikely]]
return;
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, this->capacity(), this->data(), GL_DYNAMIC_DRAW);
glBindVertexArray(vao);
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, IndirectBuffer);
glBufferData(GL_DRAW_INDIRECT_BUFFER,
CommandBuffer.size() * sizeof(DrawArraysIndirectCommand),
CommandBuffer.data(), GL_DYNAMIC_DRAW);
glMultiDrawArraysIndirect(GL_TRIANGLES, nullptr, static_cast<GLsizei>(CommandBuffer.size()), sizeof(DrawArraysIndirectCommand));
glBindVertexArray(0);
Vertex shader:
#version 430 core
layout(location = 0) in vec3 aPos;
layout(location = 1) in vec4 aColor;
out vec4 vertexColor;
void main()
{
gl_Position = vec4(aPos, 1.0);
vertexColor = aColor;
}
Fragment shader:
#version 430 core
in vec4 vertexColor;
out vec4 FragColor;
void main()
{
FragColor = vertexColor;
}
CommandBuffer is a vector of
struct DrawArraysIndirectCommand {
GLuint count;
GLuint instanceCount;
GLuint first;
GLuint baseInstance;
};
and is set up per-instance as count: the amount of vertices, instanceCount: 1, first: the offset in the vector, baseInstance: same as first
Depth test is enabled, if that helps.
I'm missing something about instancing, and I'd very much appreciate any help.
"in my constructor" red flag
also very strange that you're interleaving your vertex data and instance data
in any case, check renderdoc
Yeah
and make sure you have debug message callback installed to catch errors
Setting first and baseinstance feels a bit off. Wonder if one om should be 0?
So, baseInstance should have been zero. first should have been represented in the amount of vertices instead of bytes.
your second attribute is instance rate, but you're reading it from your vertex buffer and at an offset. that sounds very hard to use correctly
from the attributes you've described your buffer looks to be a tightly packed list of:
struct Vertex {
vec4 pos;
vec4 instanceData;
};
which forces you to either have the same number of instances as you have vertices, or to have a tonne of wasted space in your buffer
- if you ever want to change the instance data, that's going to be a massive pain in the ass, because you have to somehow do that without touching the actual vertex data you want to instance
hopefully that answers your❓
This runs on a custom allocator, so changing the amount of vertices is not an issue. Vertex is defined as (basically a __m128 Position, __m128 Color). Reading instances from the buffer at an offset is effectively the same as using pointers, and there is an actual conversion to a pointer that is possible, so it is, in effect, the same as using traditional dynamic allocation except it's.. customized, possibly more cache-local, etc.
i don't really understand how any of that relates to what i said. my point is that your Vertex struct does not compose only a single vertex. storing instance data interleaved with vertex data is extremely unusual at best
you're not going to see better cache locality because for every instance you need to read every vertex anyway, and since everything is interleaved, you're only going to be able to fit half the actual vertex data in cache
even if you only have a single instance, you're still allocating space for as many instances as you have vertices
and like I said, changing that instance data is going to be awful. you're either going to need to spam glbuffersubdata or map and do a tonne of sparse writes, neither of which are great
it seems overly complicated for no reason
Vertices being closer in memory should improve cache locality. I've only just begun hearing about cache locality, so if you could explain why I'm wrong, I would appreciate it.
If you mean instances, where the mesh is the set of vertices or some set of offsets ruled in the shader from a position/quaternion structure and the in-general data is somewhere else (like if the entire mesh should be a certain color retrieved by reference), then I agree under the scenario where I would want that. Everything is per-vertex because the vertex data is not supposed to be per-instance.
But, I don't know if I'm getting what exactly you're getting at.
For every vector of vertices added, the buffer would be updated once. In the draw method, glbufferdata is used when the size needs to change (the arena size changed) and glbuffersubdata when not.
I think. I'm currently not at my work station, so I don't remember what my final result was. I just remember trying to move onto textures and getting stuck because bindless textures sound great but I don't know how supported they actually are, and that alternatives kinda suck.
Why is that, by that way? What's wrong with having a dedicated class for a rendering context?
complex logic in constructors is just almost always a bad idea. and it's a very common beginner mistake to try and over model graphics stuff with classes. that may not be what you're doing necessarily but it is very common
then you have a bug. your colour attribute IS instance rate since you have set an attribute divisor
Actually, I recall changing the constructor to just generate the buffers. This is all a testing phase, and I fully understand why the constructor I sent here is bad.
I'm somewhat confused. I mean, I removed the devisor at some point, but I recall even when the divisor was there, it worked as soon as I changed my command structure.
i can not see what you have removed or added, i can only see what you have posted here and comment on that
and what you have posted here is incorrect
if you have fixed it already then great, but in that case we have absolutely nothing to comment on
Yes, I have. I actually posted my fix before your Sept. 3rd response.
that is not what I'm talking about