rhi: gl: Use GL_EXT_multisampled_render_to_texture, if present, always
Meaning on the common MSAA path that involves passing in a multisample renderbuffer and a non-multisample resolve texture, i.e. the traditional GLES 3.0 compatible approach, that is used throughout Qt in Qt Quick and elsewhere. When EXT_multisampled_render_to_texture (not to be confused with non-GLES extensions or similarly named non-GLES, core functions), is present, which is relatively rare in practice (probably offered on Mali and Qualcomm perhaps), we could ignore the multisample renderbuffer object completely, and get automatic resolving into the (non-multisample) texture. This is already done on the true texture-based path, mainly because using the sibling extension for multiview is mandatory when dealing with multiview (texture arrays) and MSAA on e.g. the Quest 3. However, the texture-based code path is not generally utilized in the rest of Qt when doing MSAA since renderbuffer+explicit resolve into a texture is GLES 3.0 compatible, whereas multisample textures (and then resolve into a texture) needs GLES 3.1. So 1. use glFramebufferTexture2DMultisampleEXT instead of glFramebufferRenderbuffer when the conditions are met (multisample renderbuffer, there is a resolve texture specified, and the extension is supported), and 2. skip the explicit resolve (glBlitFramebuffer) when the conditions for 1) were met. Do this only for color attachments. As the docs for setDepthResolveTexture() state, we do not actually support depth(stencil) resolving with OpenGL ES in combination with QRhiRenderBuffer, so do not have to worry about that here. Change-Id: I0bf88089c3b1b15a8ccc5652e1f918a2dad215e6 Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
parent
34f127834c
commit
590c85c80b
@ -4616,21 +4616,26 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
|
||||
qWarning("Resolve source (%dx%d) and target (%dx%d) size does not match",
|
||||
rbD->pixelSize().width(), rbD->pixelSize().height(), size.width(), size.height());
|
||||
}
|
||||
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
|
||||
cmd.cmd = QGles2CommandBuffer::Command::BlitFromRenderbuffer;
|
||||
cmd.args.blitFromRenderbuffer.renderbuffer = rbD->renderbuffer;
|
||||
cmd.args.blitFromRenderbuffer.w = size.width();
|
||||
cmd.args.blitFromRenderbuffer.h = size.height();
|
||||
if (resolveTexD->m_flags.testFlag(QRhiTexture::CubeMap))
|
||||
cmd.args.blitFromRenderbuffer.target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + uint(colorAtt.resolveLayer());
|
||||
else
|
||||
cmd.args.blitFromRenderbuffer.target = resolveTexD->target;
|
||||
cmd.args.blitFromRenderbuffer.dstTexture = resolveTexD->texture;
|
||||
cmd.args.blitFromRenderbuffer.dstLevel = colorAtt.resolveLevel();
|
||||
const bool hasZ = resolveTexD->m_flags.testFlag(QRhiTexture::ThreeDimensional)
|
||||
|| resolveTexD->m_flags.testFlag(QRhiTexture::TextureArray);
|
||||
cmd.args.blitFromRenderbuffer.dstLayer = hasZ ? colorAtt.resolveLayer() : 0;
|
||||
cmd.args.blitFromRenderbuffer.isDepthStencil = false;
|
||||
if (caps.glesMultisampleRenderToTexture) {
|
||||
// colorAtt.renderBuffer() is not actually used for anything if OpenGL ES'
|
||||
// auto-resolving GL_EXT_multisampled_render_to_texture is used.
|
||||
} else {
|
||||
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
|
||||
cmd.cmd = QGles2CommandBuffer::Command::BlitFromRenderbuffer;
|
||||
cmd.args.blitFromRenderbuffer.renderbuffer = rbD->renderbuffer;
|
||||
cmd.args.blitFromRenderbuffer.w = size.width();
|
||||
cmd.args.blitFromRenderbuffer.h = size.height();
|
||||
if (resolveTexD->m_flags.testFlag(QRhiTexture::CubeMap))
|
||||
cmd.args.blitFromRenderbuffer.target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + uint(colorAtt.resolveLayer());
|
||||
else
|
||||
cmd.args.blitFromRenderbuffer.target = resolveTexD->target;
|
||||
cmd.args.blitFromRenderbuffer.dstTexture = resolveTexD->texture;
|
||||
cmd.args.blitFromRenderbuffer.dstLevel = colorAtt.resolveLevel();
|
||||
const bool hasZ = resolveTexD->m_flags.testFlag(QRhiTexture::ThreeDimensional)
|
||||
|| resolveTexD->m_flags.testFlag(QRhiTexture::TextureArray);
|
||||
cmd.args.blitFromRenderbuffer.dstLayer = hasZ ? colorAtt.resolveLayer() : 0;
|
||||
cmd.args.blitFromRenderbuffer.isDepthStencil = false;
|
||||
}
|
||||
} else if (caps.glesMultisampleRenderToTexture) {
|
||||
// Nothing to do, resolving into colorAtt.resolveTexture() is automatic,
|
||||
// colorAtt.texture() is in fact not used for anything.
|
||||
@ -6060,7 +6065,18 @@ bool QGles2TextureRenderTarget::create()
|
||||
}
|
||||
} else if (renderBuffer) {
|
||||
QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, renderBuffer);
|
||||
rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), GL_RENDERBUFFER, rbD->renderbuffer);
|
||||
if (rbD->sampleCount() > 1 && rhiD->caps.glesMultisampleRenderToTexture && colorAtt.resolveTexture()) {
|
||||
// Special path for GLES and GL_EXT_multisampled_render_to_texture: ignore
|
||||
// the (multisample) renderbuffer and give the resolve texture to GL. (so
|
||||
// no explicit resolve; depending on GL implementation internals, this may
|
||||
// play nicer with tiled architectures)
|
||||
QGles2Texture *resolveTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
|
||||
const GLenum faceTargetBase = resolveTexD->flags().testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : resolveTexD->target;
|
||||
rhiD->glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), faceTargetBase + uint(colorAtt.resolveLayer()),
|
||||
resolveTexD->texture, colorAtt.level(), rbD->sampleCount());
|
||||
} else {
|
||||
rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + uint(attIndex), GL_RENDERBUFFER, rbD->renderbuffer);
|
||||
}
|
||||
if (attIndex == 0) {
|
||||
d.pixelSize = rbD->pixelSize();
|
||||
d.sampleCount = rbD->samples;
|
||||
|
Loading…
x
Reference in New Issue
Block a user