QOpenGLTexture::allocateStorage 导致 GL_INVALID_VALUE 错误
Posted
技术标签:
【中文标题】QOpenGLTexture::allocateStorage 导致 GL_INVALID_VALUE 错误【英文标题】:QOpenGLTexture::allocateStorage causes GL_INVALID_VALUE error 【发布时间】:2017-03-20 16:38:30 【问题描述】:我已将其提炼为琐碎的 Qt 代码,其中唯一有趣的是 synchronize()
中处理纹理的几行代码。我从allocateStorage
行得到一个 GL_INVALID_VALUE。有谁知道为什么?我怀疑这可能是由于我传递给这个函数的参数。
我的代码:
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickFramebufferObject>
#include <QOpenGLFramebufferObject>
#include <QOpenGLFunctions>
#include <QOpenGLTexture>
class MyItem : public QQuickFramebufferObject
Q_OBJECT
public:
Renderer* createRenderer() const;
;
class MyItemRenderer : public QQuickFramebufferObject::Renderer, protected QOpenGLFunctions
public:
MyItemRenderer()
initializeOpenGLFunctions();
void render()
QOpenGLFramebufferObject* createFramebufferObject(const QSize &size)
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
return new QOpenGLFramebufferObject(size, format);
protected:
void synchronize(QQuickFramebufferObject* qqfbo)
Q_UNUSED(qqfbo)
QOpenGLTexture tex(QOpenGLTexture::Target2D);
tex.setSize(100, 100);
tex.allocateStorage(QOpenGLTexture::BGRA, QOpenGLTexture::Int8);
qDebug() << "starting loop";
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR)
qDebug("\tgl error: 0x%x", err, 0, 16);
;
QQuickFramebufferObject::Renderer* MyItem::createRenderer() const
return new MyItemRenderer();
int main(int argc, char **argv)
QGuiApplication app(argc, argv);
qmlRegisterType<MyItem>("MyItem", 1, 0, "MyItem");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
#include "main.moc"
main.qml
import QtQuick 2.0
import MyItem 1.0
import QtQuick.Window 2.2
Window
visible: true
width: 400
height: 400
MyItem
anchors.fill: parent
【问题讨论】:
【参考方案1】:查看QOpenGLTexture::createMutableTexture
和QOpenGLTexture::allocateStorage()
(无参数版本)的来源后,我发现allocateStorage
的两个参数重载真的,真的 误导。文档使它看起来像它的 2 个 args 将用作纹理的 internal format(实现中 glTexImage2D
调用的第 3 个 arg),而实际上它们仅用作"source-data-to-transfer-from-system-RAM" 格式/类型(glTexImage2D
的第 7 和第 8 个参数),在将空指针传递给 glTexImage2D
的情况下,根本不重要除了边缘 OpenGL ES 2 情况。
实际上为纹理请求某种内部格式的方法是在调用tex.allocateStorage
之前调用tex.setFormat
。所以我用这个替换了我的allocateStorage
行:
tex.setFormat(QOpenGLTexture::RGBA8_UNorm);
tex.allocateStorage();
这样就修复了错误。
【讨论】:
好吧,也听到另一个铃声,allocateStorage
的参数的两种枚举类型清楚地表明它们是关于外部格式,而不是内部格式......
Qt 的 GL 包装器是灾难。+1 为答案,否则我可能会花费数小时来弄清楚。设计此 API 的人并不真正了解 OpenGL:/【参考方案2】:
你有...
QOpenGLTexture tex(QOpenGLTexture::Target2D);
根据docs,它实际上并没有创建底层纹理对象。我想你需要...
tex.create();
在设置大小和分配存储之前。所以...
QOpenGLTexture tex(QOpenGLTexture::Target2D);
if (!tex.create())
/*
* Take appropriate action.
*/
tex.setSize(100, 100);
tex.allocateStorage(QOpenGLTexture::BGRA, QOpenGLTexture::Int8);
编辑 1:
实际上,查看代码似乎tex.allocateStorage
应该在必要时分配一个纹理ID。但是,如果由于某种原因(例如没有当前上下文)失败,那么这可能会导致您看到的问题。
【讨论】:
谢谢,但我在allocateStorage
之后打印了tex.isCreated()
,我得到了true
。【参考方案3】:
在“分配存储”期间,您正在向 opeGL 驱动程序传达有关纹理存储格式的信息。
对于“GL_BGRA 或 GL_RGBA”格式,OpenGL 建议使用“GL_UNSIGNED_BYTE”,
在 Qt 中----“QOpenGLTexture::BGRA
”(用于 GL_BGRA)和“QOpenGLTexture::UInt8
”(用于 GL_UNSIGNED_BYTE)。
https://www.khronos.org/opengl/wiki/Textures_-_more
所以你的分配存储功能基于(openGL 推荐)应该是
tex.allocateStorage(QOpenGLTexture::BGRA, QOpenGLTexture::UInt8);
【讨论】:
以上是关于QOpenGLTexture::allocateStorage 导致 GL_INVALID_VALUE 错误的主要内容,如果未能解决你的问题,请参考以下文章