我在OGL计算着色器上编写光线跟踪,将数据传入和使用缓冲区的着色器。
当vec2输出缓冲区的大小(等于光线数量乘以面数)达到~30Mb时,映射缓冲区的尝试稳定返回NULL指针。范围映射也失败。
我无法在ogl文档中找到有关GL_SHADER_STORAGE_BUFFER限制的任何信息,但是也许有人可以帮助我,是〜30Mb限制或者这种映射失败可能因为某些不同而发生?
除了多次调用着色器之外,还有什么方法可以避免这种情况吗?
着色器中的数据声明:
#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);
答案 0 :(得分:3)
首先,您必须了解OpenGL规范为各种值(以MAX_{*}
前缀开头的值)定义 minimum maxima 。这意味着至少需要实现提供指定的数量作为最大值,但可以随着实现者的需要自由增加限制。这样,开发人员至少可以依赖某些上限,但仍然可以为可能更大的值做出规定。
第23节 - 状态表总结了之前在相应章节中指定的内容。您要查找的信息可在表 23.64 - Implementation Dependent Aggregate Shader Limits(续)表中找到。如果你想知道哪个州属于哪里(因为有每个对象状态,准全局状态,程序状态等),你可以转到第23节。
着色器存储缓冲区的最小最大大小由符号常量MAX_SHADER_STORAGE_BLOCK_SIZE
表示,符合core OpenGL 4.5 specification的 7.8 部分。< / p>
自从采用核心后,所需的尺寸(即最小的最大值)显着增加。在核心OpenGL 4.3和4.4中,最小最大值为pow(2, 24)
(或16MB,基本机器单位为1字节,1MB = 1024 ^ 2字节) - 在核心OpenGL 4.5中,此值现为pow(2, 27)
(或128MB) )
摘要:如果对OpenGL状态有疑问,请参阅核心规范的第23节。
答案 1 :(得分:2)
来自OpenGL Wiki:
SSBO可以更大。 OpenGL规范保证UBO可以 最大16KB(实现可以允许它们更大)。该 spec保证SSBO最高可达128MB。大多数实现 将允许您分配大小达到GPU内存限制的大小。
OpenGL&lt; 4.5仅保证16MiB
(OpenGL 4.5将最小值增加到128MiB
),您可以尝试使用glGet()
来查询是否可以绑定更多。
GLint64 max;
glGetInteger64v(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &max);