当我尝试在我的 ATI HD 5770 上运行它时,我注意到我的一个计算着色器出现错误。我发现当我在着色器中访问多个 SSB 时问题就开始了,尽管 GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 为 8。
经过一番摆弄后,我将有问题的着色器简化为这个 MWE:
#version 430
layout(local_size_x = 1) in;
buffer A { float a[]; };
buffer B { uint b[]; };
layout(r32i) uniform iimage2D outputImage;
void main() {
a[0] = -2;
b.length();
imageStore(outputImage, ivec2(gl_GlobalInvocationID.xy),
ivec4(a[0], 0, 0, 0));
}
当我按原样运行此着色器时,我看不到imageStore
. 删除时,我在图像中b.length();
得到所需的输出。-2
的值在这两种情况下a[0]
都更改为-2
,因此着色器肯定正在运行。
在这两种情况下,着色器都没有编译/链接器错误,glGetError
也不会返回错误。
我在这里做错了吗?
这是(驱动程序)错误吗?毕竟,这不会发生在我的其他 (NVidia) 卡上。
为了完整起见,我使用了这个“最小的”C++ 文件来运行着色器:
#include <cassert>
#include <QGuiApplication>
#include <QOpenGLShaderProgram>
#include <QOffscreenSurface>
#include <QOpenGLBuffer>
#include <QOpenGLContext>
#include <QOpenGLTexture>
#include <QOpenGLFunctions_4_3_Compatibility>
#include <vector>
#include <iostream>
#include <iterator>
int main(int argc, char* argv[]) {
QGuiApplication app(argc, argv);
QOffscreenSurface surface;
surface.create();
QOpenGLContext context;
context.create();
context.makeCurrent(&surface);
QOpenGLShaderProgram program;
program.addShaderFromSourceFile(QOpenGLShader::Compute, "shader.comp");
bool programIsLinked = program.link();
assert(programIsLinked);
QSize size(2, 2);
QOpenGLBuffer bufferA;
bufferA.create();
bufferA.bind();
std::vector<GLfloat> valuesOfBufferA(1, 2);
bufferA.allocate(&valuesOfBufferA.front(),
sizeof(valuesOfBufferA.front()) * valuesOfBufferA.size());
bufferA.release();
QOpenGLTexture texture(QOpenGLTexture::Target2D);
texture.create();
texture.setFormat(QOpenGLTexture::R32I);
texture.setSize(size.width(), size.height());
texture.bind();
texture.allocateStorage();
std::vector<GLint> data;
data.resize(size.width() * size.height(), -1);
texture.setData(QOpenGLTexture::Red_Integer, QOpenGLTexture::Int32,
data.data());
texture.release();
QOpenGLFunctions_4_3_Compatibility* qOGL =
context.versionFunctions<QOpenGLFunctions_4_3_Compatibility>();
qOGL->initializeOpenGLFunctions();
program.bind();
qOGL->glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, bufferA.bufferId());
qOGL->glBindImageTexture(0, texture.textureId(), 0, GL_FALSE, 0,
GL_WRITE_ONLY, texture.format());
qOGL->glDispatchCompute(size.width(), size.height(), 1);
qOGL->glMemoryBarrier(GL_ALL_BARRIER_BITS);
// for good measure :)
qOGL->glFinish();
data.clear();
data.resize(size.width() * size.height(), 0);
glBindTexture(GL_TEXTURE_2D, texture.textureId());
glGetTexImage(GL_TEXTURE_2D, 0, GL_RED_INTEGER, GL_INT, data.data());
glBindTexture(GL_TEXTURE_2D, 0);
bufferA.bind();
bufferA.read(0, valuesOfBufferA.data(),
sizeof(valuesOfBufferA.front()) * valuesOfBufferA.size());
bufferA.release();
assert(GL_NO_ERROR == glGetError());
std::cout << valuesOfBufferA.front() << "\n";
std::copy(data.begin(), data.end(),
std::ostream_iterator<GLint>(std::cout, " "));
std::cout << "\n";
}
更新
似乎有一个类似的问题imageLoad
,它总是在使用超过 2 个 SSBO 时返回 0,在使用 2 个 SSBO 时返回 3,对于少于 2 个 SSBO 的正确值。即使在最新的驱动程序(15.7,之前是 15.5)上也会出现这两个问题。