GL_SHADER_STORAGE_BUFFER内存限制

时间:2017-02-06 07:43:30

标签: c++ qt opengl

我在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);

2 个答案:

答案 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);