From 63790184c79d2765ea726488726cd9f2b43b91d1 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 13 Oct 2020 15:47:27 +0200 Subject: [PATCH] rhi: Fix up vertex inputs with matrices In order to prevent too much voodoo in backends like D3D11, the input layout is expected to specify the slice index for vecX that are part of an unrolled matrix. Also deoptimize the instancing manual test to exercise a matrix too instead of just vectors. Change-Id: If2dcbcbc483645ce2420b2f87dda765b95da6e80 Reviewed-by: Andy Nichols --- src/gui/rhi/qrhi.cpp | 11 +++++++-- src/gui/rhi/qrhi_p.h | 6 ++++- src/gui/rhi/qrhid3d11.cpp | 20 ++++++++++++--- tests/manual/rhi/instancing/inst.frag.qsb | Bin 735 -> 724 bytes tests/manual/rhi/instancing/inst.vert | 12 +++------ tests/manual/rhi/instancing/inst.vert.qsb | Bin 1456 -> 1225 bytes tests/manual/rhi/instancing/instancing.cpp | 27 ++++++++++++--------- 7 files changed, 51 insertions(+), 25 deletions(-) diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp index 06781686fa..5db0791322 100644 --- a/src/gui/rhi/qrhi.cpp +++ b/src/gui/rhi/qrhi.cpp @@ -1202,12 +1202,19 @@ QDebug operator<<(QDebug dbg, const QRhiVertexInputBinding &b) /*! Constructs a vertex input attribute description with the specified \a binding number, \a location, \a format, and \a offset. + + \a matrixSlice should be -1 except when this attribute corresponds to a row + or column of a matrix (for example, a 4x4 matrix becomes 4 vec4s, consuming + 4 consecutive vertex input locations), in which case it is the index of the + row or column. \c{location - matrixSlice} must always be equal to the \c + location for the first row or column of the unrolled matrix. */ -QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset) +QRhiVertexInputAttribute::QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice) : m_binding(binding), m_location(location), m_format(format), - m_offset(offset) + m_offset(offset), + m_matrixSlice(matrixSlice) { } diff --git a/src/gui/rhi/qrhi_p.h b/src/gui/rhi/qrhi_p.h index 977b68cd8e..6a141d13e1 100644 --- a/src/gui/rhi/qrhi_p.h +++ b/src/gui/rhi/qrhi_p.h @@ -212,7 +212,7 @@ public: }; QRhiVertexInputAttribute() = default; - QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset); + QRhiVertexInputAttribute(int binding, int location, Format format, quint32 offset, int matrixSlice = -1); int binding() const { return m_binding; } void setBinding(int b) { m_binding = b; } @@ -226,11 +226,15 @@ public: quint32 offset() const { return m_offset; } void setOffset(quint32 ofs) { m_offset = ofs; } + int matrixSlice() const { return m_matrixSlice; } + void setMatrixSlice(int slice) { m_matrixSlice = slice; } + private: int m_binding = 0; int m_location = 0; Format m_format = Float4; quint32 m_offset = 0; + int m_matrixSlice = -1; }; Q_DECLARE_TYPEINFO(QRhiVertexInputAttribute, Q_MOVABLE_TYPE); diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp index 48e626106c..ce954c9fe0 100644 --- a/src/gui/rhi/qrhid3d11.cpp +++ b/src/gui/rhi/qrhid3d11.cpp @@ -4019,15 +4019,29 @@ bool QD3D11GraphicsPipeline::create() d3dTopology = toD3DTopology(m_topology); if (!vsByteCode.isEmpty()) { + QByteArrayList matrixSliceSemantics; QVarLengthArray inputDescs; for (auto it = m_vertexInputLayout.cbeginAttributes(), itEnd = m_vertexInputLayout.cendAttributes(); it != itEnd; ++it) { D3D11_INPUT_ELEMENT_DESC desc; memset(&desc, 0, sizeof(desc)); - // the output from SPIRV-Cross uses TEXCOORD as the semantic - desc.SemanticName = "TEXCOORD"; - desc.SemanticIndex = UINT(it->location()); + // The output from SPIRV-Cross uses TEXCOORD as the + // semantic, except for matrices that are unrolled into consecutive + // vec2/3/4s attributes and need TEXCOORD_ as + // SemanticName and row/column index as SemanticIndex. + const int matrixSlice = it->matrixSlice(); + if (matrixSlice < 0) { + desc.SemanticName = "TEXCOORD"; + desc.SemanticIndex = UINT(it->location()); + } else { + QByteArray sem; + sem.resize(16); + qsnprintf(sem.data(), sem.size(), "TEXCOORD%d_", it->location() - matrixSlice); + matrixSliceSemantics.append(sem); + desc.SemanticName = matrixSliceSemantics.last().constData(); + desc.SemanticIndex = UINT(matrixSlice); + } desc.Format = toD3DAttributeFormat(it->format()); desc.InputSlot = UINT(it->binding()); desc.AlignedByteOffset = it->offset(); diff --git a/tests/manual/rhi/instancing/inst.frag.qsb b/tests/manual/rhi/instancing/inst.frag.qsb index cd6b9482279fa6a4b116d9467f436a635ebda96c..c2a738734f18ea41534eb1bb5249e8b2b4054f27 100644 GIT binary patch literal 724 zcmV;_0xSIh00${}oW)dMPZL29UnmqGw9 z-sD%D<9X18&b8tsU~g0DFv|N_5RD?_!tpJXLxibTE|Z zCc$ow9hqzEpGgUmUR=yXE-*8F<63&GvARN6Hx&J9+1Dih3?o){wO zP-@4iUDXOI0soy&ngs(1Qny=VY@&~|B`$#tagaPWn>P5G(q1{GsGGaOJ)q9DV0*zg1>87x1|+!rum=Yfu8%T9#SW zeD@Ac4m@~R-u82>4|dl!C9`*rEtp4%v+%J*k8~CE5MMwJSRww9e4xDI$Q$4j3-1xw zRHz8=!>S5j0rLUqBTtol3HV)Pwml-=BzcK2)aRsMA^l~FnUnr9#fjKskgMiwIKI4o z0c~)Wd@{n?Y$}7ry+zbGzD|0y?+cmoQ6fWSfD1La7}=U{PQgk8`2SjZk!7c?n{lHJG4>l5 GJdUGWEMbZO literal 735 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 K8S@X-sq1tn*xgM4 diff --git a/tests/manual/rhi/instancing/instancing.cpp b/tests/manual/rhi/instancing/instancing.cpp index 87a99b4581..5eb6293b6e 100644 --- a/tests/manual/rhi/instancing/instancing.cpp +++ b/tests/manual/rhi/instancing/instancing.cpp @@ -83,8 +83,8 @@ void Window::customInit() d.initialUpdates->uploadStaticBuffer(d.vbuf, cube); - // translation + color (vec3 + vec3), interleaved, for each instance - d.instBuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, INSTANCE_COUNT * 6 * sizeof(float)); + // transform + color (mat4 + vec3), interleaved, for each instance + d.instBuf = m_r->newBuffer(QRhiBuffer::Immutable, QRhiBuffer::VertexBuffer, INSTANCE_COUNT * 19 * sizeof(float)); d.instBuf->create(); d.releasePool << d.instBuf; @@ -108,12 +108,15 @@ void Window::customInit() QRhiVertexInputLayout inputLayout; inputLayout.setBindings({ { 3 * sizeof(float) }, // cube vertices - { 6 * sizeof(float), QRhiVertexInputBinding::PerInstance } // per-instance translation and color + { 19 * sizeof(float), QRhiVertexInputBinding::PerInstance }, // per-instance transform and color }); inputLayout.setAttributes({ - { 0, 0, QRhiVertexInputAttribute::Float3, 0 }, // position - { 1, 1, QRhiVertexInputAttribute::Float3, 0 }, // instTranslate - { 1, 2, QRhiVertexInputAttribute::Float3, 3 * sizeof(float) } // instColor + { 0, 0, QRhiVertexInputAttribute::Float3, 0 }, // position + { 1, 1, QRhiVertexInputAttribute::Float4, 0, 0 }, // instMat + { 1, 2, QRhiVertexInputAttribute::Float4, 4 * sizeof(float), 1 }, + { 1, 3, QRhiVertexInputAttribute::Float4, 8 * sizeof(float), 2 }, + { 1, 4, QRhiVertexInputAttribute::Float4, 12 * sizeof(float), 3 }, + { 1, 5, QRhiVertexInputAttribute::Float3, 16 * sizeof(float) }, // instColor }); d.ps->setVertexInputLayout(inputLayout); d.ps->setShaderResourceBindings(d.srb); @@ -121,14 +124,16 @@ void Window::customInit() d.ps->create(); QByteArray instData; - instData.resize(INSTANCE_COUNT * 6 * sizeof(float)); + instData.resize(INSTANCE_COUNT * 19 * sizeof(float)); float *p = reinterpret_cast(instData.data()); QRandomGenerator *rgen = QRandomGenerator::global(); for (int i = 0; i < INSTANCE_COUNT; ++i) { - // translation - *p++ = rgen->bounded(8000) / 100.0f - 40.0f; - *p++ = rgen->bounded(8000) / 100.0f - 40.0f; - *p++ = 0.0f; + QMatrix4x4 m; + m.translate(rgen->bounded(8000) / 100.0f - 40.0f, + rgen->bounded(8000) / 100.0f - 40.0f, + 0.0f); + memcpy(p, m.constData(), 16 * sizeof(float)); + p += 16; // color *p++ = i / float(INSTANCE_COUNT); *p++ = 0.0f;