From 5c922772c3c33287e249916a0ff8b9896f2be0bb Mon Sep 17 00:00:00 2001 From: Jim Albamont Date: Thu, 10 Dec 2020 17:19:14 -0800 Subject: Fix binding of CubeMapArray textures To bind to a specific face: use glFramebufferTextureLayer and calculate the layer as 6 * layer + face. To bind to a specific cubemap: There is no way in OpenGL to directly bind to an entire cubemap within the array. Instead bind to the entire texture as for a CubeMap with AllFaces. It is up to the drawing code to select the right cubemap and face, 6 * layer + face Change-Id: Ib9e1a598503eeba1fa729677944aba6d799f90b2 Reviewed-by: Paul Lemire (cherry picked from commit 94ab90f93dc5338338f30e6d78854b55353d3cb8) Reviewed-by: Qt Cherry-pick Bot --- .../opengl/graphicshelpers/graphicshelpergl3_2.cpp | 4 +- .../opengl/graphicshelpers/graphicshelpergl3_3.cpp | 4 +- .../opengl/graphicshelpers/graphicshelpergl4.cpp | 4 +- .../graphicshelpergl4/tst_graphicshelpergl4.cpp | 107 +++++++++++++++++++++ 4 files changed, 113 insertions(+), 6 deletions(-) diff --git a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp index cb0a62224..8e843bca7 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp +++ b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp @@ -512,8 +512,8 @@ void GraphicsHelperGL3_2::bindFrameBufferAttachment(QOpenGLTexture *texture, con if (target == QOpenGLTexture::Target1DArray || target == QOpenGLTexture::Target2DArray || target == QOpenGLTexture::Target2DMultisampleArray || target == QOpenGLTexture::Target3D) m_funcs->glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attr, texture->textureId(), attachment.m_mipLevel, attachment.m_layer); - else if (target == QOpenGLTexture::TargetCubeMapArray) - m_funcs->glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, attr, attachment.m_face, texture->textureId(), attachment.m_mipLevel, attachment.m_layer); + else if (target == QOpenGLTexture::TargetCubeMapArray && attachment.m_face != QAbstractTexture::AllFaces) + m_funcs->glFramebufferTextureLayer( GL_DRAW_FRAMEBUFFER, attr, texture->textureId(), attachment.m_mipLevel, attachment.m_layer * 6 + (attachment.m_face - QAbstractTexture::CubeMapPositiveX)); else if (target == QOpenGLTexture::TargetCubeMap) m_funcs->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attr, attachment.m_face, texture->textureId(), attachment.m_mipLevel); else diff --git a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp index f5a61aa4b..3a8c8bde8 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp +++ b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp @@ -493,8 +493,8 @@ void GraphicsHelperGL3_3::bindFrameBufferAttachment(QOpenGLTexture *texture, con if (target == QOpenGLTexture::Target1DArray || target == QOpenGLTexture::Target2DArray || target == QOpenGLTexture::Target2DMultisampleArray || target == QOpenGLTexture::Target3D) m_funcs->glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attr, texture->textureId(), attachment.m_mipLevel, attachment.m_layer); - else if (target == QOpenGLTexture::TargetCubeMapArray) - m_funcs->glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, attr, attachment.m_face, texture->textureId(), attachment.m_mipLevel, attachment.m_layer); + else if (target == QOpenGLTexture::TargetCubeMapArray && attachment.m_face != QAbstractTexture::AllFaces) + m_funcs->glFramebufferTextureLayer( GL_DRAW_FRAMEBUFFER, attr, texture->textureId(), attachment.m_mipLevel, attachment.m_layer * 6 + (attachment.m_face - QAbstractTexture::CubeMapPositiveX)); else if (target == QOpenGLTexture::TargetCubeMap && attachment.m_face != QAbstractTexture::AllFaces) m_funcs->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attr, attachment.m_face, texture->textureId(), attachment.m_mipLevel); else diff --git a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp index 96e055870..f23dd8485 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp +++ b/src/plugins/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp @@ -841,8 +841,8 @@ void GraphicsHelperGL4::bindFrameBufferAttachment(QOpenGLTexture *texture, const if (target == QOpenGLTexture::Target1DArray || target == QOpenGLTexture::Target2DArray || target == QOpenGLTexture::Target2DMultisampleArray || target == QOpenGLTexture::Target3D) m_funcs->glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attr, texture->textureId(), attachment.m_mipLevel, attachment.m_layer); - else if (target == QOpenGLTexture::TargetCubeMapArray) - m_funcs->glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, attr, attachment.m_face, texture->textureId(), attachment.m_mipLevel, attachment.m_layer); + else if (target == QOpenGLTexture::TargetCubeMapArray && attachment.m_face != QAbstractTexture::AllFaces) + m_funcs->glFramebufferTextureLayer( GL_DRAW_FRAMEBUFFER, attr, texture->textureId(), attachment.m_mipLevel, attachment.m_layer * 6 + (attachment.m_face - QAbstractTexture::CubeMapPositiveX)); else if (target == QOpenGLTexture::TargetCubeMap && attachment.m_face != QAbstractTexture::AllFaces) m_funcs->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attr, attachment.m_face, texture->textureId(), attachment.m_mipLevel); else diff --git a/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp b/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp index 8f86f38ce..6cb03b514 100644 --- a/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp +++ b/tests/auto/render/opengl/graphicshelpergl4/tst_graphicshelpergl4.cpp @@ -469,6 +469,113 @@ private Q_SLOTS: m_func->glDeleteFramebuffers(1, &fboId); } } + + // TargetCubeMapArray + { + // GIVEN + QOpenGLTexture texture(QOpenGLTexture::TargetCubeMapArray); + texture.setSize(512, 512); + texture.setFormat(QOpenGLTexture::RGBA32F); + texture.setMinificationFilter(QOpenGLTexture::Linear); + texture.setMagnificationFilter(QOpenGLTexture::Linear); + texture.setWrapMode(QOpenGLTexture::ClampToEdge); + texture.setLayers(4); + if (!texture.create()) + qWarning() << "Texture creation failed"; + texture.allocateStorage(); + QVERIFY(texture.isStorageAllocated()); + GLint error = m_func->glGetError(); + QVERIFY(error == 0); + + { // Check All Faces + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + attachment.m_face = Qt3DRender::QAbstractTexture::AllFaces; + + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + + // Texture should be layered and attached to layer 0 since CubeMapArray textures + // are bound to entire texture, not a specific layer + GLint textureIsLayered = 0; + m_func->glGetFramebufferAttachmentParameteriv( + GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_LAYERED, &textureIsLayered); + QCOMPARE(textureIsLayered, GL_TRUE); + + GLint textureLayer = 0; + m_func->glGetFramebufferAttachmentParameteriv( + GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, &textureLayer); + QCOMPARE(textureLayer, 0); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + { // Check Specific Faces + + // GIVEN + GLuint fboId; + m_func->glGenFramebuffers(1, &fboId); + + // THEN + QVERIFY(fboId != 0); + + // WHEN + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboId); + + Attachment attachment; + attachment.m_point = QRenderTargetOutput::Color0; + attachment.m_face = Qt3DRender::QAbstractTexture::CubeMapNegativeZ; + attachment.m_layer = 1; + + m_glHelper.bindFrameBufferAttachment(&texture, attachment); + + // THEN + GLenum status = m_func->glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + QVERIFY(status == GL_FRAMEBUFFER_COMPLETE); + + error = m_func->glGetError(); + QVERIFY(error == 0); + + GLint textureIsLayered = 0; + m_func->glGetFramebufferAttachmentParameteriv( + GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_LAYERED, &textureIsLayered); + QCOMPARE(textureIsLayered, GL_FALSE); + + GLint textureLayer = 0; + m_func->glGetFramebufferAttachmentParameteriv( + GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, &textureLayer); + // actual layer should be 6 * layer + face + const auto faceNo = + attachment.m_face - Qt3DRender::QAbstractTexture::CubeMapPositiveX; + QCOMPARE(textureLayer, 6 * attachment.m_layer + faceNo); + + // Restore state + m_func->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + m_func->glDeleteFramebuffers(1, &fboId); + } + } } void bindFrameBufferObject() -- cgit v1.2.1