"transfered"数组缓冲区的不同大小的着色器存储缓冲区内容
Shader Storage Buffer contents of varying size "transfered" to Array Buffer
我正在计算着色器中计算的位置实例化对象。我想将包含位置的计算着色器的输出绑定到数组缓冲区以进行绘制,但我无法使其工作。我为索引算法道歉,我对记忆对齐非常偏执,放弃了所有向量。
相关代码简化:
初始化:
//x, y, z, 1 stored in succession
/*float*/positions = new float[maxPositionCount * 4];
//initialize positions_vbo
glGenBuffers(1, &position_vbo);
glBindBuffer(GL_ARRAY_BUFFER, position_vbo);
glBindBuffer(GL_ARRAY_BUFFER, 0);
//initialize positionsOUT_ssbo
glGenBuffers(1, &positionsOUT_ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, positionsOUT_ssbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * maxPositionCount * sizeof(float), NULL, GL_DYNAMIC_COPY);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, positionsOUT_ssbo);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
//initialize positionCounter
glGenBuffers(1, &positionCount_acb);
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, positionCount_acb);
glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 7, positionCount_acb);
glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
绘制循环:
//initialize the counter
posCount = 0;
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 7, positionCount_acb);
glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), &posCount);
//send other data to compute shader in order to calculate positions
//dispatch and wait
//....
//retrieve the counter
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 7, positionCount_acb);
glGetBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), &positionCount_acb);
//retrieve the positions (1)
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 8, positionsOUT_ssbo);
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, posCount * 4 * sizeof(float), positions);
//bind position_vbo (2)
glBindBuffer(GL_ARRAY_BUFFER, position_vbo);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(float) * posCount, posCount > 0 ? &positions[0] : NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glVertexAttribDivisor(2, 1);
//instead of (1)+(2) I would like to know if something like this is possible
//glBindBuffer(GL_ARRAY_BUFFER, positionsOUT_ssbo);
//glEnableVertexAttribArray(2);
//glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
//glVertexAttribDivisor(2, 1);
//bind vertex array and draw the object instances
glBindVertexArray(vertexArrayOfTheObjectImDrawing);
glDrawElementsInstanced(GL_TRIANGLES, objectSharedVertexCount, GL_UNSIGNED_SHORT, 0, posCount);
计算着色器:
layout(local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
//just in case they are relevant somehow
//can set and get them fine but they have fixed size (maxPositionCount)
//---------v
layout(std430, binding=4) buffer A {
int a[ ];
};
layout(std430, binding=5) buffer B {
int b[ ];
};
layout(std430, binding=6) buffer C {
int c1,c2,c3,c4,c5;
};
//----------^
layout(binding = 7, offset = 0) uniform atomic_uint returnedPositionsIndex;
layout(std430, binding=8) buffer pos_Out
{
float positionsOUT[ ];
};
void main()
{
ivec3 currentPos = gl_GlobalInvocationID.xyz;
if (I_want_that_position_returned(currentPos))
{
uint i = atomicCounterIncrement(returnedPositionsIndex);
positionsOUT[i * 4 + 0] = float(index3D.x);
positionsOUT[i * 4 + 1] = float(index3D.y);
positionsOUT[i * 4 + 2] = float(index3D.z);
positionsOUT[i * 4 + 3] = 1.0;
}
}
顶点着色器:
uniform mat4 worldViewProjection;
layout(location = 1) in vec4 vertPosition;
layout(location = 2) in vec4 position;
int main() {
gl_Position = worldViewProjection * (vertPosition + position);
}
通常它在上崩溃
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, posCount * 4 * sizeof(float), positions);
调用,即使它是程序中唯一未注释的行。调试错误:
Exception thrown at 0x0000000001A132A9 (atio6axx.dll) in asd.exe:
0xC0000005: Access violation writing location 0x0000000000000000.
我已经尝试过通过预先调用glBufferData(…positions)来初始化数据。将使用正确的计数检索原子计数器。此外,是否有一种方法可以在不复制和绑定到positions_vbo的情况下从positionsOUT_ssbo发送位置数据?
EDIT:崩溃修复,初始化时重新声明变量"positions"。。
编辑2:我在上面评论的行确实是将ssbo的内容直接"绑定"到数组缓冲区的一种方式。如果有更好的方法,请随意分享。
这太令人尴尬了。我在初始化阶段重新声明了类变量的位置,在draw循环中屏蔽了这个位置。现在工作正常。谢谢你指引我正确的方向!
根据你的评论,我在下面转载了我的原始评论作为回应。
我看到您有float* positions = new float[maxPositionCount * 4];
,但我从来没有看到什么时候真正将值添加到这个数组中,所以据我所知,这是一个未初始化的内存块。
然后调用glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, posCount * 4 * sizeof(float), positions);
,它似乎发送了这个未初始化的内存块,这个内存块可能被设置为零,并解释了为什么会出现Access violation writing location 0x0000000000000000.
错误。
- 如何在cpp.中使用协议缓冲区存储大缓冲区/数组(char/int)
- 在 Linux 中存储区域设置名称的缓冲区大小应该是多少?
- 将结构数据存储在循环缓冲区中
- 如果我在 C++ 中为 int 提供双精度,输入缓冲区中存储了什么?
- 为什么存储对象地址在缓冲区中会导致内存泄漏并删除它们
- 无需额外复制即可存储和访问 deque<vectors> 缓冲区 (c++)?
- DirectX:在矢量缓冲区中存储多个顶点
- 将二进制数据缓冲区存储在协议缓冲区消息中
- 将int转换为十六进制并将其存储到char缓冲区中
- 一个粒子太多:GL_INVALID_VALUE生成错误。<start> 不满足着色器存储缓冲区的最低对齐要求
- Arduino - 将来自FRAM的值存储到缓冲区中
- 打开"GL着色器存储缓冲区对象"以替换"顶点属性"
- Win32:在缓冲区中存储多行文本
- 着色器存储缓冲区中的 OpenGL 顶点
- 着色器存储缓冲区的所有值在几何着色器中均为 0
- 录制音频,存储在缓冲区中,然后通过PulseAudio将字节写入声卡
- 如何读取存储在输入流缓冲区中的字符数
- 使用stdvector作为库中存储的缓冲区和在另一个库中使用此缓冲区的困难
- OpenGL:着色器存储缓冲区映射/绑定
- 将缓冲区存储到变量中