2015-11-30 40 views
1

我在计算着色器中计算的位置上实例化对象。我想将包含位置的计算着色器的输出绑定到数组缓冲区以进行绘制,但我无法使其工作。我对索引算术表示歉意,我对记忆对齐感到非常偏执,并抛弃所有媒介。不同大小的着色器存储缓冲区内容“转移”到阵列缓冲区

相关的代码被简化了:

初始化:

//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); 
} 

Currrentlly崩溃的

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(...职位)事先初始化数据。原子计数器用正确的计数检索。另外,有没有办法从position_ssbo发送位置数据而不复制并绑定到positions_vbo?

EDIT:崩溃固定,重新声明变量“位置”初始化当..

EDIT2:我上面评论的线是确实的方式来“绑定”的ssbo的内容直到阵列缓冲器。如果有更好的方法,请随时分享。

+0

那真是尴尬。我在初始化阶段重新声明了类变量位置,并将其绘制在绘制循环中。现在工作正常。感谢您指点我正确的方向!有趣的是,我只在最小化代码来测试错误时做到了这一点,并且一开始不工作的原因得到了修复。无论如何,我会留下这个问题的第二部分,因为必须有更好的方法来实现我想要做的事情。 – potis

+0

我已删除我的评论,并将其添加为回复,因为您已指示它解决了您的问题。如果您还需要帮助,*此问题已解决,那么我建议您提出一个单独的问题,而不是尝试向原始帖子中添加更多问题。请考虑投票并接受我的回答。它对我们和整个社区都有好处。这也是我们在这里如何说'谢谢':) – ray

+0

我知道,no1堆栈溢出lurker就在这里:)。虽然我希望对第二部分有所了解,但我怀疑这是否需要重新发布。 – potis

回答

0

Well that was embarassing. I redeclared the class variable positions in the initializing phase, shadowing the one in the draw loop. Works fine now. Thanks for pointing me in the right direction!

根据您的评论,我已经在下面转载了我原来的评论作为回复。


我看到你有float* positions = new float[maxPositionCount * 4];,但我从来没有看到当值实际上是加入到这个数组,所以它是一个未初始化的内存块,据我可以告诉。

然后,您可以拨打glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, posCount * 4 * sizeof(float), positions);看起来发送此未初始化的内存块,它可能被设置为零,并会解释为什么你会得到Access violation writing location 0x0000000000000000.错误。