diff options
author | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-06-28 12:36:35 +0200 |
---|---|---|
committer | Laszlo Agocs <laszlo.agocs@qt.io> | 2019-07-01 17:34:44 +0200 |
commit | 201a22a4d2a3906a2f6cbba1e50d5b83a21a10f6 (patch) | |
tree | 198e3ba88c3d1831ff286b37a8a7004adf803c32 /src/gui/rhi | |
parent | 9452c963c8ab732946f835e5b5a0510c6fed49ee (diff) |
rhi: gl: Add support for instanced drawing
...when having a 3.3+ or ES 3.0+ context.
Change-Id: Ie92815263e190912d8f0b7b92ae6da55e062af05
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/gui/rhi')
-rw-r--r-- | src/gui/rhi/qrhigles2.cpp | 54 | ||||
-rw-r--r-- | src/gui/rhi/qrhigles2_p_p.h | 7 |
2 files changed, 45 insertions, 16 deletions
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index 34052c5a9c..60bbda2d60 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -425,6 +425,7 @@ bool QRhiGles2::create(QRhi::Flags flags) caps.elementIndexUint = f->hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint); caps.depth24 = f->hasOpenGLExtension(QOpenGLExtensions::Depth24); caps.rgba8Format = f->hasOpenGLExtension(QOpenGLExtensions::Sized8Formats); + caps.instancing = caps.ctxMajor >= 3 && (caps.gles || caps.ctxMinor >= 3); nativeHandlesStruct.context = ctx; @@ -665,7 +666,7 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const case QRhi::Timestamps: return false; case QRhi::Instancing: - return false; + return caps.instancing; case QRhi::CustomInstanceStepRate: return false; case QRhi::PrimitiveRestart: @@ -933,7 +934,6 @@ void QRhiGles2::setStencilRef(QRhiCommandBuffer *cb, quint32 refValue) void QRhiGles2::draw(QRhiCommandBuffer *cb, quint32 vertexCount, quint32 instanceCount, quint32 firstVertex, quint32 firstInstance) { - Q_UNUSED(instanceCount); // no instancing Q_UNUSED(firstInstance); QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); Q_ASSERT(cbD->recordingPass == QGles2CommandBuffer::RenderPass); @@ -943,13 +943,13 @@ void QRhiGles2::draw(QRhiCommandBuffer *cb, quint32 vertexCount, cmd.args.draw.ps = cbD->currentPipeline; cmd.args.draw.vertexCount = vertexCount; cmd.args.draw.firstVertex = firstVertex; + cmd.args.draw.instanceCount = instanceCount; cbD->commands.append(cmd); } void QRhiGles2::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, quint32 instanceCount, quint32 firstIndex, qint32 vertexOffset, quint32 firstInstance) { - Q_UNUSED(instanceCount); // no instancing Q_UNUSED(firstInstance); Q_UNUSED(vertexOffset); // no glDrawElementsBaseVertex QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); @@ -960,6 +960,7 @@ void QRhiGles2::drawIndexed(QRhiCommandBuffer *cb, quint32 indexCount, cmd.args.drawIndexed.ps = cbD->currentPipeline; cmd.args.drawIndexed.indexCount = indexCount; cmd.args.drawIndexed.firstIndex = firstIndex; + cmd.args.drawIndexed.instanceCount = instanceCount; cbD->commands.append(cmd); } @@ -1613,13 +1614,14 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) const QVector<QRhiVertexInputBinding> bindings = psD->m_vertexInputLayout.bindings(); const QVector<QRhiVertexInputAttribute> attributes = psD->m_vertexInputLayout.attributes(); for (const QRhiVertexInputAttribute &a : attributes) { - if (a.binding() != cmd.args.bindVertexBuffer.binding) + const int bindingIdx = a.binding(); + if (bindingIdx != cmd.args.bindVertexBuffer.binding) continue; // we do not support more than one vertex buffer f->glBindBuffer(GL_ARRAY_BUFFER, cmd.args.bindVertexBuffer.buffer); - const int stride = bindings[a.binding()].stride(); + const int stride = bindings[bindingIdx].stride(); int size = 1; GLenum type = GL_FLOAT; bool normalize = false; @@ -1658,10 +1660,17 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) default: break; } + + const int locationIdx = a.location(); quint32 ofs = a.offset() + cmd.args.bindVertexBuffer.offset; - f->glVertexAttribPointer(a.location(), size, type, normalize, stride, + f->glVertexAttribPointer(locationIdx, size, type, normalize, stride, reinterpret_cast<const GLvoid *>(quintptr(ofs))); - f->glEnableVertexAttribArray(a.location()); + f->glEnableVertexAttribArray(locationIdx); + if (bindings[bindingIdx].classification() == QRhiVertexInputBinding::PerInstance + && caps.instancing) + { + f->glVertexAttribDivisor(locationIdx, bindings[bindingIdx].instanceStepRate()); + } } } else { qWarning("No graphics pipeline active for setVertexInput; ignored"); @@ -1677,21 +1686,36 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) case QGles2CommandBuffer::Command::Draw: { QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, cmd.args.draw.ps); - if (psD) - f->glDrawArrays(psD->drawMode, cmd.args.draw.firstVertex, cmd.args.draw.vertexCount); - else + if (psD) { + if (cmd.args.draw.instanceCount == 1 || !caps.instancing) { + f->glDrawArrays(psD->drawMode, cmd.args.draw.firstVertex, cmd.args.draw.vertexCount); + } else { + f->glDrawArraysInstanced(psD->drawMode, cmd.args.draw.firstVertex, cmd.args.draw.vertexCount, + cmd.args.draw.instanceCount); + } + } else { qWarning("No graphics pipeline active for draw; ignored"); + } } break; case QGles2CommandBuffer::Command::DrawIndexed: { QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, cmd.args.drawIndexed.ps); if (psD) { - quint32 ofs = cmd.args.drawIndexed.firstIndex * indexStride + indexOffset; - f->glDrawElements(psD->drawMode, - cmd.args.drawIndexed.indexCount, - indexType, - reinterpret_cast<const GLvoid *>(quintptr(ofs))); + const GLvoid *ofs = reinterpret_cast<const GLvoid *>( + quintptr(cmd.args.drawIndexed.firstIndex * indexStride + indexOffset)); + if (cmd.args.drawIndexed.instanceCount == 1 || !caps.instancing) { + f->glDrawElements(psD->drawMode, + cmd.args.drawIndexed.indexCount, + indexType, + ofs); + } else { + f->glDrawElementsInstanced(psD->drawMode, + cmd.args.drawIndexed.indexCount, + indexType, + ofs, + cmd.args.drawIndexed.instanceCount); + } } else { qWarning("No graphics pipeline active for drawIndexed; ignored"); } diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index dff12d626b..b758ec40b8 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -324,11 +324,13 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer QRhiGraphicsPipeline *ps; quint32 vertexCount; quint32 firstVertex; + quint32 instanceCount; } draw; struct { QRhiGraphicsPipeline *ps; quint32 indexCount; quint32 firstIndex; + quint32 instanceCount; } drawIndexed; struct { QRhiGraphicsPipeline *ps; @@ -644,7 +646,9 @@ public: coreProfile(false), uniformBuffers(false), elementIndexUint(false), - depth24(false) + depth24(false), + rgba8Format(false), + instancing(false) { } int ctxMajor; int ctxMinor; @@ -672,6 +676,7 @@ public: uint elementIndexUint : 1; uint depth24 : 1; uint rgba8Format : 1; + uint instancing : 1; } caps; QGles2SwapChain *currentSwapChain = nullptr; QVector<GLint> supportedCompressedFormats; |