我在OGL计算着色器上编写光线跟踪,以便将数据传递给我使用缓冲区的着色器。
当vec2输出缓冲区的大小(等于射线数乘以面数)达到~30Mb时,映射缓冲区的尝试将稳定返回空指针。范围映射也会失败。
我在ogl文档中找不到任何关于GL_SHADER_STORAGE_BUFFER限制的信息,但也许有人可以帮助我,是~30Mb的限制还是这种映射失败可能是因为某些不同的原因?
除了多次调用shader之外,还有什么方法可以避免这种情况吗?
着色器中的数据声明:
#version 440
layout(std430, binding=0) buffer rays{
vec4 r[];
};
layout(std430, binding=1) buffer faces{
vec4 f[];
};
layout(std430, binding=2) buffer outputs{
vec2 o[];
};
uniform int face_count;
uniform vec4 origin;调用代码(使用一些Qt5包装器):
QOpenGLBuffer ray_buffer;
QOpenGLBuffer face_buffer;
QOpenGLBuffer output_buffer;
QVector<QVector2D> output;
output.resize(rays[r].size()*faces.size());
if(!ray_buffer.create()) { /*...*/ }
if(!ray_buffer.bind()) { /*...*/ }
ray_buffer.allocate(rays.data(), rays.size()*sizeof(QVector4D));
if(!face_buffer.create()) { /*...*/ }
if(!face_buffer.bind()) { /*...*/ }
face_buffer.allocate(faces.data(), faces.size()*sizeof(QVector4D));
if(!output_buffer.create()) { /*...*/ }
if(!output_buffer.bind()) { /*...*/ }
output_buffer.allocate(output.size()*sizeof(QVector2D));
ogl->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ray_buffer.bufferId());
ogl->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, face_buffer.bufferId());
ogl->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, output_buffer.bufferId());
int face_count = faces.size();
compute.setUniformValue("face_count", face_count);
compute.setUniformValue("origin", pos);
ogl->glDispatchCompute(rays.size()/256, faces.size(), 1);
ray_buffer.destroy();
face_buffer.destroy();
QVector2D* data = (QVector2D*)output_buffer.map(QOpenGLBuffer::ReadOnly);发布于 2017-02-06 18:57:18
首先,您必须了解OpenGL规范为各种值(以MAX_{*}前缀开头的值)定义了最小值maxima。这意味着实现至少需要提供指定的数量作为最大值,但可以根据实现人员的需要自由增加限制。这样,开发人员至少可以依赖一些上限,但仍然可以为可能更大的值做准备。
第23节-状态表总结了先前在相应部分中指定的内容。您要查找的信息可以在表23.64 -依赖于实现的聚合着色器限制(续)中找到。如果您想知道哪个状态属于何处(因为存在每个对象的状态、准全局状态、程序状态等),请转到第23节。
着色器存储缓冲区的最小最大大小由符号常量MAX_SHADER_STORAGE_BLOCK_SIZE表示,如core specification的7.8一节所示。
自从它们被采用到核心中以来,所需的大小(即最小最大值)已显著增加。在核心OpenGL 4.3和4.4中,最小最大值是pow(2, 24) (或16MB加上1个字节的基本机器单位和1MB = 1024^2字节)-在核心OpenGL 4.5中,此值现在为pow(2, 27) (或128MB)
摘要:当对OpenGL状态有疑问时,请参阅核心规范的第23节。
发布于 2017-02-06 18:12:10
SSBO可以大得多。OpenGL规范保证UBO的大小可以达到16KB (实现可以允许它们更大)。该规范保证SSBOs最大可达128MB。大多数实现都会让您分配的大小达到GPU内存限制。
OpenGL < 4.5只保证16MiB (OpenGL 4.5将最小值增加到128MiB),您可以尝试使用glGet()查询是否可以绑定更多。
GLint64 max;
glGetInteger64v(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &max);发布于 2017-02-24 11:45:36
事实上,问题似乎出在Qt包装器中。我没有深入研究,但当我将QOpenGLBuffer的create(),bind(),allocate()和map()改为glCreateBuffers(),glBindBuffer(),glNamedBufferData()和glMapNamedBuffer(),所有这些都是通过QOpenGLFunctions_4_5_Core调用的,内存问题在我达到2 2Gb (这是图形处理器的物理内存限制)之前就解决了。
我犯的第二个错误是没有使用glMemoryBarrier(),但在使用QOpenGLBuffer时它并没有帮助。
https://stackoverflow.com/questions/42062621
复制相似问题