summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2020-08-18 16:33:32 +0200
committerPaul Lemire <paul.lemire@kdab.com>2020-08-26 12:53:06 +0200
commit607235b72918a416268b45772c6bbc2f86c32e9b (patch)
treeca2902c6d9612d20d2ad35a41aa591a55d1af4e1
parent29281788884b69d7e7a86a17efbbe4c62c680e19 (diff)
Handle mat4 as vertex attributes
This will be required for instance drawing were providing a per instance matrix attribute is really convenient. Change-Id: I8329d22c346f254942288129e06d59b80c54ebe3 Reviewed-by: Mike Krus <mike.krus@kdab.com>
-rw-r--r--src/plugins/renderers/rhi/renderer/renderer.cpp40
1 files changed, 22 insertions, 18 deletions
diff --git a/src/plugins/renderers/rhi/renderer/renderer.cpp b/src/plugins/renderers/rhi/renderer/renderer.cpp
index 489e8aa02..fd8b5c1e9 100644
--- a/src/plugins/renderers/rhi/renderer/renderer.cpp
+++ b/src/plugins/renderers/rhi/renderer/renderer.cpp
@@ -834,7 +834,7 @@ std::optional<QRhiVertexInputAttribute::Format> rhiAttributeType(Attribute *attr
return QRhiVertexInputAttribute::Float2;
if (attr->vertexSize() == 3)
return QRhiVertexInputAttribute::Float3;
- if (attr->vertexSize() == 4)
+ if (attr->vertexSize() >= 4)
return QRhiVertexInputAttribute::Float4;
break;
}
@@ -1651,8 +1651,8 @@ bool Renderer::prepareGeometryInputBindings(const Geometry *geometry, const RHIS
QVarLengthArray<QRhiVertexInputAttribute, 8> &rhiAttributes,
QHash<int, int> &attributeNameToBinding)
{
+ // shader requires no attributes
if (shader->attributes().size() == 0)
- // shader requires no attributes
return true;
// QRhiVertexInputBinding -> specifies the stride of an attribute,
@@ -1676,6 +1676,12 @@ bool Renderer::prepareGeometryInputBindings(const Geometry *geometry, const RHIS
Attribute *attrib = m_nodesManager->attributeManager()->lookupResource(attribute_id);
if (attrib->attributeType() != QAttribute::VertexAttribute)
continue;
+ const int location = locationForAttribute(attrib, shader);
+ // In case the shader doesn't use the attribute, we would get no
+ // location. This is not a failure, just that we provide more attributes
+ // than required.
+ if (location == -1)
+ continue;
const bool isPerInstanceAttr = attrib->divisor() != 0;
const QRhiVertexInputBinding::Classification classification = isPerInstanceAttr
@@ -1702,21 +1708,16 @@ bool Renderer::prepareGeometryInputBindings(const Geometry *geometry, const RHIS
};
uint byteStride = attrib->byteStride();
+ const uint vertexTypeByteSize = getAttributeByteSize(attrib->vertexBaseType());
// in GL 0 means tighly packed, we therefore assume a tighly packed
// attribute and compute the stride if that happens
if (byteStride == 0)
- byteStride = attrib->vertexSize() * getAttributeByteSize(attrib->vertexBaseType());
+ byteStride = attrib->vertexSize() * vertexTypeByteSize;
const BufferBinding binding = { attrib->bufferId(), byteStride,
classification,
isPerInstanceAttr ? attrib->divisor() : 1U };
- const int location = locationForAttribute(attrib, shader);
- // In case the shader doesn't use the attribute, we would get no
- // location. This is not a failure, just that we provide more attributes
- // than required.
- if (location == -1)
- continue;
const auto it = std::find_if(uniqueBindings.begin(), uniqueBindings.end(),
[binding](const BufferBinding &a) {
@@ -1738,19 +1739,22 @@ bool Renderer::prepareGeometryInputBindings(const Geometry *geometry, const RHIS
return false;
}
- rhiAttributes.push_back({ bindingIndex,
- location,
- *attributeType,
- attrib->byteOffset() });
+ // Special Handling for Matrix as Vertex Attributes
+ // If an attribute has a size > 4 it can only be a matrix based type
+ // for which we will actually upload several attributes at contiguous
+ // locations
+ const uint elementsPerColumn = 4;
+ const int attributeSpan = std::ceil(float(attrib->vertexSize()) / elementsPerColumn);
+ for (int i = 0; i < attributeSpan; ++i) {
+ rhiAttributes.push_back({ bindingIndex,
+ location + i,
+ *attributeType,
+ attrib->byteOffset() + (i * elementsPerColumn * vertexTypeByteSize)});
+ }
attributeNameToBinding.insert(attrib->nameId(), bindingIndex);
}
- if (uniqueBindings.empty() || rhiAttributes.empty()) {
- qCWarning(Backend) << "No bindings or no attributes where found";
- return false;
- }
-
inputBindings.resize(uniqueBindings.size());
for (int i = 0, m = uniqueBindings.size(); i < m; ++i) {
const BufferBinding binding = uniqueBindings.at(i);