rhi: Improve layout compatibility test performance

Also bump the non-heap buffer size in the binding list to 16,
in order to accommodate complex Quick3D materials with many
associated texture maps.

Change-Id: Id190e5f8304f5941cffc41a2605fce45dfeb72f0
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
bb10
Laszlo Agocs 2020-09-28 13:05:38 +02:00
parent 331c8cd5b4
commit 868866cecd
8 changed files with 36 additions and 9 deletions

View File

@ -2806,16 +2806,25 @@ bool QRhiShaderResourceBindings::isLayoutCompatible(const QRhiShaderResourceBind
if (!other)
return false;
const int count = m_bindings.count();
if (count != other->m_bindings.count())
return false;
// This can become a hot code path. Therefore we do not iterate and call
// isLayoutCompatible() on m_bindings, but rather check a pre-calculated
// hash code and then, if the hash matched, do a uint array comparison
// (that's still more cache friendly).
for (int i = 0; i < count; ++i) {
if (!m_bindings[i].isLayoutCompatible(other->m_bindings.at(i)))
return false;
return m_layoutDescHash == other->m_layoutDescHash
&& m_layoutDesc == other->m_layoutDesc;
}
void QRhiImplementation::updateLayoutDesc(QRhiShaderResourceBindings *srb)
{
srb->m_layoutDescHash = 0;
srb->m_layoutDesc.clear();
for (const QRhiShaderResourceBinding &b : qAsConst(srb->m_bindings)) {
const QRhiShaderResourceBinding::Data *d = b.data();
// must match QRhiShaderResourceBinding::isLayoutCompatible()
srb->m_layoutDescHash ^= uint(d->binding) ^ uint(d->stage) ^ uint(d->type);
srb->m_layoutDesc << uint(d->binding) << uint(d->stage) << uint(d->type);
}
return true;
}
/*!

View File

@ -1012,7 +1012,10 @@ public:
protected:
QRhiShaderResourceBindings(QRhiImplementation *rhi);
QVarLengthArray<QRhiShaderResourceBinding, 8> m_bindings;
QVarLengthArray<QRhiShaderResourceBinding, 16> m_bindings;
uint m_layoutDescHash = 0;
QVarLengthArray<uint, 16 * 3> m_layoutDesc;
friend class QRhiImplementation;
#ifndef QT_NO_DEBUG_STREAM
friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QRhiShaderResourceBindings &);
#endif

View File

@ -211,6 +211,7 @@ public:
bool sanityCheckGraphicsPipeline(QRhiGraphicsPipeline *ps);
bool sanityCheckShaderResourceBindings(QRhiShaderResourceBindings *srb);
void updateLayoutDesc(QRhiShaderResourceBindings *srb);
QRhi *q;

View File

@ -3456,6 +3456,8 @@ bool QD3D11ShaderResourceBindings::create()
if (!rhiD->sanityCheckShaderResourceBindings(this))
return false;
rhiD->updateLayoutDesc(this);
std::copy(m_bindings.cbegin(), m_bindings.cend(), std::back_inserter(sortedBindings));
std::sort(sortedBindings.begin(), sortedBindings.end(),
[](const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)

View File

@ -4307,6 +4307,8 @@ bool QGles2ShaderResourceBindings::create()
if (!rhiD->sanityCheckShaderResourceBindings(this))
return false;
rhiD->updateLayoutDesc(this);
generation += 1;
return true;
}

View File

@ -3013,6 +3013,8 @@ bool QMetalShaderResourceBindings::create()
if (!rhiD->sanityCheckShaderResourceBindings(this))
return false;
rhiD->updateLayoutDesc(this);
std::copy(m_bindings.cbegin(), m_bindings.cend(), std::back_inserter(sortedBindings));
std::sort(sortedBindings.begin(), sortedBindings.end(),
[](const QRhiShaderResourceBinding &a, const QRhiShaderResourceBinding &b)

View File

@ -800,6 +800,12 @@ void QNullShaderResourceBindings::destroy()
bool QNullShaderResourceBindings::create()
{
QRHI_RES_RHI(QRhiNull);
if (!rhiD->sanityCheckShaderResourceBindings(this))
return false;
rhiD->updateLayoutDesc(this);
return true;
}

View File

@ -6186,6 +6186,8 @@ bool QVkShaderResourceBindings::create()
if (!rhiD->sanityCheckShaderResourceBindings(this))
return false;
rhiD->updateLayoutDesc(this);
for (int i = 0; i < QVK_FRAMES_IN_FLIGHT; ++i)
descSets[i] = VK_NULL_HANDLE;