Commit 2f6d6a84 authored by Laszlo Agocs's avatar Laszlo Agocs

gl: Add support for depth textures

parent 7188859e
...@@ -1310,13 +1310,13 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb, ...@@ -1310,13 +1310,13 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb,
enqueueResourceUpdates(cb, resourceUpdates); enqueueResourceUpdates(cb, resourceUpdates);
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb); QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
bool needsColorClear = true; bool wantsColorClear = true;
bool needsDsClear = true; bool wantsDsClear = true;
QD3D11RenderTargetData *rtD = rtData(rt); QD3D11RenderTargetData *rtD = rtData(rt);
if (rt->type() == QRhiRenderTarget::RtTexture) { if (rt->type() == QRhiRenderTarget::RtTexture) {
QD3D11TextureRenderTarget *rtTex = QRHI_RES(QD3D11TextureRenderTarget, rt); QD3D11TextureRenderTarget *rtTex = QRHI_RES(QD3D11TextureRenderTarget, rt);
needsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents); wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
needsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents); wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
} }
cbD->currentTarget = rt; cbD->currentTarget = rt;
...@@ -1330,9 +1330,9 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb, ...@@ -1330,9 +1330,9 @@ void QRhiD3D11::beginPass(QRhiCommandBuffer *cb,
clearCmd.cmd = QD3D11CommandBuffer::Command::Clear; clearCmd.cmd = QD3D11CommandBuffer::Command::Clear;
clearCmd.args.clear.rt = rt; clearCmd.args.clear.rt = rt;
clearCmd.args.clear.mask = 0; clearCmd.args.clear.mask = 0;
if (rtD->colorAttCount && needsColorClear) if (rtD->colorAttCount && wantsColorClear)
clearCmd.args.clear.mask |= QD3D11CommandBuffer::Command::Color; clearCmd.args.clear.mask |= QD3D11CommandBuffer::Command::Color;
if (rtD->dsAttCount && needsDsClear) if (rtD->dsAttCount && wantsDsClear)
clearCmd.args.clear.mask |= QD3D11CommandBuffer::Command::Depth | QD3D11CommandBuffer::Command::Stencil; clearCmd.args.clear.mask |= QD3D11CommandBuffer::Command::Depth | QD3D11CommandBuffer::Command::Stencil;
const QVector4D rgba = colorClearValue.rgba(); const QVector4D rgba = colorClearValue.rgba();
......
...@@ -180,6 +180,14 @@ QT_BEGIN_NAMESPACE ...@@ -180,6 +180,14 @@ QT_BEGIN_NAMESPACE
#define GL_RGBA16F 0x881A #define GL_RGBA16F 0x881A
#endif #endif
#ifndef GL_DEPTH_COMPONENT16
#define GL_DEPTH_COMPONENT16 0x81A5
#endif
#ifndef GL_DEPTH_COMPONENT32F
#define GL_DEPTH_COMPONENT32F 0x8CAC
#endif
#ifndef GL_PRIMITIVE_RESTART_FIXED_INDEX #ifndef GL_PRIMITIVE_RESTART_FIXED_INDEX
#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 #define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69
#endif #endif
...@@ -314,11 +322,10 @@ bool QRhiGles2::create(QRhi::Flags flags) ...@@ -314,11 +322,10 @@ bool QRhiGles2::create(QRhi::Flags flags)
caps.bgraExternalFormat = f->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat); caps.bgraExternalFormat = f->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat);
caps.bgraInternalFormat = caps.bgraExternalFormat && actualFormat.renderableType() == QSurfaceFormat::OpenGLES; caps.bgraInternalFormat = caps.bgraExternalFormat && actualFormat.renderableType() == QSurfaceFormat::OpenGLES;
caps.r8Format = f->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats); caps.r8Format = f->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats);
caps.r16Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats); caps.r16Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats);
caps.floatFormats = actualFormat.version() >= qMakePair(3, 0); caps.floatFormats = actualFormat.version() >= qMakePair(3, 0);
caps.depthTexture = actualFormat.version() >= qMakePair(3, 0);
caps.srgbCapableDefaultFramebuffer = f->hasOpenGLExtension(QOpenGLExtensions::SRGBFrameBuffer); caps.srgbCapableDefaultFramebuffer = f->hasOpenGLExtension(QOpenGLExtensions::SRGBFrameBuffer);
...@@ -467,7 +474,7 @@ bool QRhiGles2::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture ...@@ -467,7 +474,7 @@ bool QRhiGles2::isTextureFormatSupported(QRhiTexture::Format format, QRhiTexture
case QRhiTexture::D16: case QRhiTexture::D16:
Q_FALLTHROUGH(); Q_FALLTHROUGH();
case QRhiTexture::D32: case QRhiTexture::D32:
return false; return caps.depthTexture;
case QRhiTexture::BGRA8: case QRhiTexture::BGRA8:
return caps.bgraExternalFormat; return caps.bgraExternalFormat;
...@@ -1767,8 +1774,8 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb, ...@@ -1767,8 +1774,8 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb,
enqueueResourceUpdates(cb, resourceUpdates); enqueueResourceUpdates(cb, resourceUpdates);
QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
bool needsColorClear = true; bool wantsColorClear = true;
bool needsDsClear = true; bool wantsDsClear = true;
QGles2RenderTargetData *rtD = nullptr; QGles2RenderTargetData *rtD = nullptr;
QGles2CommandBuffer::Command fbCmd; QGles2CommandBuffer::Command fbCmd;
fbCmd.cmd = QGles2CommandBuffer::Command::BindFramebuffer; fbCmd.cmd = QGles2CommandBuffer::Command::BindFramebuffer;
...@@ -1781,8 +1788,8 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb, ...@@ -1781,8 +1788,8 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb,
{ {
QGles2TextureRenderTarget *rtTex = QRHI_RES(QGles2TextureRenderTarget, rt); QGles2TextureRenderTarget *rtTex = QRHI_RES(QGles2TextureRenderTarget, rt);
rtD = &rtTex->d; rtD = &rtTex->d;
needsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents); wantsColorClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveColorContents);
needsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents); wantsDsClear = !rtTex->m_flags.testFlag(QRhiTextureRenderTarget::PreserveDepthStencilContents);
fbCmd.args.bindFramebuffer.fbo = rtTex->framebuffer; fbCmd.args.bindFramebuffer.fbo = rtTex->framebuffer;
} }
break; break;
...@@ -1795,13 +1802,12 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb, ...@@ -1795,13 +1802,12 @@ void QRhiGles2::beginPass(QRhiCommandBuffer *cb,
cbD->currentTarget = rt; cbD->currentTarget = rt;
Q_ASSERT(rtD->attCount == 1 || rtD->attCount == 2);
QGles2CommandBuffer::Command clearCmd; QGles2CommandBuffer::Command clearCmd;
clearCmd.cmd = QGles2CommandBuffer::Command::Clear; clearCmd.cmd = QGles2CommandBuffer::Command::Clear;
clearCmd.args.clear.mask = 0; clearCmd.args.clear.mask = 0;
if (rtD->attCount > 0 && needsColorClear) if (rtD->colorAttCount && wantsColorClear)
clearCmd.args.clear.mask |= GL_COLOR_BUFFER_BIT; clearCmd.args.clear.mask |= GL_COLOR_BUFFER_BIT;
if (rtD->attCount > 1 && needsDsClear) if (rtD->dsAttCount && wantsDsClear)
clearCmd.args.clear.mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; clearCmd.args.clear.mask |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
const QVector4D rgba = colorClearValue.rgba(); const QVector4D rgba = colorClearValue.rgba();
...@@ -1822,28 +1828,31 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource ...@@ -1822,28 +1828,31 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb);
if (cbD->currentTarget->type() == QRhiRenderTarget::RtTexture) { if (cbD->currentTarget->type() == QRhiRenderTarget::RtTexture) {
QGles2TextureRenderTarget *rtTex = QRHI_RES(QGles2TextureRenderTarget, cbD->currentTarget); QGles2TextureRenderTarget *rtTex = QRHI_RES(QGles2TextureRenderTarget, cbD->currentTarget);
// handle only 1 color attachment and only (msaa) renderbuffer
const QVector<QRhiColorAttachment> colorAttachments = rtTex->m_desc.colorAttachments(); const QVector<QRhiColorAttachment> colorAttachments = rtTex->m_desc.colorAttachments();
const QRhiColorAttachment &colorAtt(colorAttachments[0]); if (!colorAttachments.isEmpty()) {
if (colorAtt.resolveTexture()) { // handle only 1 color attachment and only (msaa) renderbuffer
Q_ASSERT(colorAtt.renderBuffer()); const QRhiColorAttachment &colorAtt(colorAttachments[0]);
QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, colorAtt.renderBuffer()); if (colorAtt.resolveTexture()) {
const QSize size = colorAtt.resolveTexture()->pixelSize(); Q_ASSERT(colorAtt.renderBuffer());
if (rbD->pixelSize() != size) { QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, colorAtt.renderBuffer());
qWarning("Resolve source (%dx%d) and target (%dx%d) size does not match", const QSize size = colorAtt.resolveTexture()->pixelSize();
rbD->pixelSize().width(), rbD->pixelSize().height(), size.width(), size.height()); if (rbD->pixelSize() != size) {
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;
cmd.cmd = QGles2CommandBuffer::Command::BlitFromRenderbuffer;
cmd.args.blitFromRb.renderbuffer = rbD->renderbuffer;
cmd.args.blitFromRb.w = size.width();
cmd.args.blitFromRb.h = size.height();
QGles2Texture *colorTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
const GLenum faceTargetBase = colorTexD->m_flags.testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X
: colorTexD->target;
cmd.args.blitFromRb.target = faceTargetBase + colorAtt.resolveLayer();
cmd.args.blitFromRb.texture = colorTexD->texture;
cmd.args.blitFromRb.dstLevel = colorAtt.resolveLevel();
cbD->commands.append(cmd);
} }
QGles2CommandBuffer::Command cmd;
cmd.cmd = QGles2CommandBuffer::Command::BlitFromRenderbuffer;
cmd.args.blitFromRb.renderbuffer = rbD->renderbuffer;
cmd.args.blitFromRb.w = size.width();
cmd.args.blitFromRb.h = size.height();
QGles2Texture *colorTexD = QRHI_RES(QGles2Texture, colorAtt.resolveTexture());
const GLenum faceTargetBase = colorTexD->m_flags.testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : colorTexD->target;
cmd.args.blitFromRb.target = faceTargetBase + colorAtt.resolveLayer();
cmd.args.blitFromRb.texture = colorTexD->texture;
cmd.args.blitFromRb.dstLevel = colorAtt.resolveLevel();
cbD->commands.append(cmd);
} }
} }
...@@ -2090,6 +2099,16 @@ bool QGles2Texture::prepareBuild(QSize *adjustedSize) ...@@ -2090,6 +2099,16 @@ bool QGles2Texture::prepareBuild(QSize *adjustedSize)
glformat = GL_RGBA; glformat = GL_RGBA;
gltype = GL_FLOAT; gltype = GL_FLOAT;
break; break;
case QRhiTexture::D16:
glintformat = GL_DEPTH_COMPONENT16;
glformat = GL_DEPTH_COMPONENT;
gltype = GL_UNSIGNED_SHORT;
break;
case QRhiTexture::D32:
glintformat = GL_DEPTH_COMPONENT32F;
glformat = GL_DEPTH_COMPONENT;
gltype = GL_FLOAT;
break;
default: default:
Q_UNREACHABLE(); Q_UNREACHABLE();
glintformat = GL_RGBA; glintformat = GL_RGBA;
...@@ -2283,12 +2302,13 @@ bool QGles2TextureRenderTarget::build() ...@@ -2283,12 +2302,13 @@ bool QGles2TextureRenderTarget::build()
release(); release();
const QVector<QRhiColorAttachment> colorAttachments = m_desc.colorAttachments(); const QVector<QRhiColorAttachment> colorAttachments = m_desc.colorAttachments();
Q_ASSERT(!colorAttachments.isEmpty()); Q_ASSERT(!colorAttachments.isEmpty() || m_desc.depthTexture());
Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture()); Q_ASSERT(!m_desc.depthStencilBuffer() || !m_desc.depthTexture());
const bool hasDepthStencil = m_desc.depthStencilBuffer() || m_desc.depthTexture();
if (colorAttachments.count() > 1) if (colorAttachments.count() > 1)
qWarning("QGles2TextureRenderTarget: Multiple color attachments are not supported"); qWarning("QGles2TextureRenderTarget: Multiple color attachments are not supported");
if (m_desc.depthTexture()) if (m_desc.depthTexture() && !rhiD->caps.depthTexture)
qWarning("QGles2TextureRenderTarget: Depth texture is not supported and will be ignored"); qWarning("QGles2TextureRenderTarget: Depth texture is not supported and will be ignored");
if (!rhiD->ensureContext()) if (!rhiD->ensureContext())
...@@ -2297,36 +2317,46 @@ bool QGles2TextureRenderTarget::build() ...@@ -2297,36 +2317,46 @@ bool QGles2TextureRenderTarget::build()
rhiD->f->glGenFramebuffers(1, &framebuffer); rhiD->f->glGenFramebuffers(1, &framebuffer);
rhiD->f->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); rhiD->f->glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
const QRhiColorAttachment &colorAtt(colorAttachments.constFirst()); if (!colorAttachments.isEmpty()) {
QRhiTexture *texture = colorAtt.texture(); const QRhiColorAttachment &colorAtt(colorAttachments.constFirst());
QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer(); QRhiTexture *texture = colorAtt.texture();
Q_ASSERT(texture || renderBuffer); QRhiRenderBuffer *renderBuffer = colorAtt.renderBuffer();
Q_ASSERT(texture || renderBuffer);
d.rp = QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc); if (texture) {
d.attCount = 1; QGles2Texture *texD = QRHI_RES(QGles2Texture, texture);
Q_ASSERT(texD->texture && texD->specified);
if (texture) { const GLenum faceTargetBase = texD->flags().testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target;
QGles2Texture *texD = QRHI_RES(QGles2Texture, texture); rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, faceTargetBase + colorAtt.layer(), texD->texture, colorAtt.level());
Q_ASSERT(texD->texture && texD->specified); d.pixelSize = texD->pixelSize();
const GLenum faceTargetBase = texD->flags().testFlag(QRhiTexture::CubeMap) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : texD->target; d.sampleCount = 1;
rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, faceTargetBase + colorAtt.layer(), texD->texture, colorAtt.level()); } else if (renderBuffer) {
d.pixelSize = texD->pixelSize(); QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, renderBuffer);
d.sampleCount = 1; rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbD->renderbuffer);
} else if (renderBuffer) { d.pixelSize = rbD->pixelSize();
QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, renderBuffer); d.sampleCount = rbD->samples;
rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbD->renderbuffer); }
d.pixelSize = rbD->pixelSize(); d.colorAttCount = 1;
d.sampleCount = rbD->samples; } else {
d.colorAttCount = 0;
} }
d.dpr = 1;
if (m_desc.depthStencilBuffer()) { if (hasDepthStencil) {
QGles2RenderBuffer *rbD = QRHI_RES(QGles2RenderBuffer, m_desc.depthStencilBuffer()); if (m_desc.depthStencilBuffer()) {
rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbD->renderbuffer); QGles2RenderBuffer *depthRbD = QRHI_RES(QGles2RenderBuffer, m_desc.depthStencilBuffer());
rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbD->renderbuffer); rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRbD->renderbuffer);
d.attCount += 1; rhiD->f->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthRbD->renderbuffer);
} else {
QGles2Texture *depthTexD = QRHI_RES(QGles2Texture, m_desc.depthTexture());
rhiD->f->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexD->texture, 0);
}
d.dsAttCount = 1;
} else {
d.dsAttCount = 0;
} }
d.dpr = 1;
d.rp = QRHI_RES(QGles2RenderPassDescriptor, m_renderPassDesc);
GLenum status = rhiD->f->glCheckFramebufferStatus(GL_FRAMEBUFFER); GLenum status = rhiD->f->glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_NO_ERROR && status != GL_FRAMEBUFFER_COMPLETE) { if (status != GL_NO_ERROR && status != GL_FRAMEBUFFER_COMPLETE) {
qWarning("Framebuffer incomplete: 0x%x", status); qWarning("Framebuffer incomplete: 0x%x", status);
...@@ -2600,7 +2630,8 @@ bool QGles2SwapChain::buildOrResize() ...@@ -2600,7 +2630,8 @@ bool QGles2SwapChain::buildOrResize()
rt.d.pixelSize = pixelSize; rt.d.pixelSize = pixelSize;
rt.d.dpr = m_window->devicePixelRatio(); rt.d.dpr = m_window->devicePixelRatio();
rt.d.sampleCount = qBound(1, m_sampleCount, 64); rt.d.sampleCount = qBound(1, m_sampleCount, 64);
rt.d.attCount = m_depthStencil ? 2 : 1; rt.d.colorAttCount = 1;
rt.d.dsAttCount = m_depthStencil ? 1 : 0;
rt.d.srgbUpdateAndBlend = m_flags.testFlag(QRhiSwapChain::sRGB); rt.d.srgbUpdateAndBlend = m_flags.testFlag(QRhiSwapChain::sRGB);
frameCount = 0; frameCount = 0;
......
...@@ -132,7 +132,8 @@ struct QGles2RenderTargetData ...@@ -132,7 +132,8 @@ struct QGles2RenderTargetData
QSize pixelSize; QSize pixelSize;
float dpr = 1; float dpr = 1;
int sampleCount = 1; int sampleCount = 1;
int attCount = 0; int colorAttCount = 0;
int dsAttCount = 0;
bool srgbUpdateAndBlend = false; bool srgbUpdateAndBlend = false;
}; };
...@@ -562,6 +563,7 @@ public: ...@@ -562,6 +563,7 @@ public:
r8Format(false), r8Format(false),
r16Format(false), r16Format(false),
floatFormats(false), floatFormats(false),
depthTexture(false),
srgbCapableDefaultFramebuffer(false) srgbCapableDefaultFramebuffer(false)
{ } { }
int maxTextureSize; int maxTextureSize;
...@@ -576,6 +578,7 @@ public: ...@@ -576,6 +578,7 @@ public:
uint r8Format : 1; uint r8Format : 1;
uint r16Format : 1; uint r16Format : 1;
uint floatFormats : 1; uint floatFormats : 1;
uint depthTexture : 1;
uint srgbCapableDefaultFramebuffer : 1; uint srgbCapableDefaultFramebuffer : 1;
} caps; } caps;
bool inFrame = false; bool inFrame = false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment