我正在尝试使用Qt场景图来实现渲染图。在图形渲染中,更新总是发生在特定的像素列(单个垂直列中的像素)上,因此我已经创建了到根节点的n个子节点(QSGNode)(这里n是渲染区域的宽度) ,并为每个子节点创建了6个子节点(在绘图模式GL_LINES中为QSGGeometryNode),每个子节点对应一个屏幕上的图形。基本上,如果渲染区域宽度为100,则根节点将总共具有100 * 6个子节点。更新仅在少数子节点上进行,更新几何之后,我将节点标记为DirtyGeometry。
直到现在为止对我来说还不错,但是我看到它占用了很多CPU,所以我尝试使用QSG_RENDERER_DEBUG = render进行调试,我看到所有子节点都通过updatePaintNode调用再次呈现而不是我标记为肮脏的特定对象。
日志如下
Renderer::render() QSGAbstractRenderer(0xf9a5a0) "rebuild: none"
Rendering:
-> Opaque: 6145 nodes in 2 batches...
-> Alpha: 0 nodes in 0 batches...
- 0xf9a910 [ upload] [noclip] [opaque] [ merged] Nodes: 6144
Vertices: 12288 Indices: 12288 root: 0x0
- 0xf9a960 [retained] [noclip] [opaque] [ merged] Nodes: 1
Vertices: 4 Indices: 6 root: 0x0
-> times: build: 0, prepare(opaque/alpha): 0/0, sorting: 0,
upload(opaque/alpha): 0/0, render: 0
渲染区域为1024 * 624(即1024 * 6 = 6144个子QSGGeometry节点)。
QSGNode *QSGPlot::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *)
{
QSGGeometry *geometry = nullptr;
QSGNode* parentNode = nullptr;
if (!oldNode)
{
Q_ASSERT (_wfGenerator == nullptr);
float pixelWidth, pixelHeight;
DisplayInfo::getPixelSize(pixelWidth,pixelHeight);
const QRectF bounds = boundingRect();
float speed = 50.0f;
float gain = 10.0f;
_wfGenerator = new WFGenerator(pixelWidth,pixelHeight, speed,gain,bounds.width(),bounds.height());
parentNode = new QSGNode;
for (size_t columnI = 0; columnI < bounds.width(); columnI++)
{
QSGNode *columnNode = new QSGNode;
parentNode->appendChildNode(columnNode);
createGeometryChildNodes(columnNode, Qt::green, 6);
}
}
else
{
parentNode = static_cast<QSGGeometryNode*>(oldNode);
Q_ASSERT (parentNode->childCount() == boundingRect().width());
}
size_t dirtyColumnCount = 0;
_wfGenerator->generateWF(_columnBuffer, dirtyColumnCount);
for (size_t dirtyColI = 0; dirtyColI < dirtyColumnCount; dirtyColI++)
{
size_t updateCol = _columnBuffer[dirtyColI].columnI;
QSGNode *columnNode = static_cast<QSGNode*>(parentNode->childAtIndex(updateCol));
if (_columnBuffer[dirtyColI].validDirtyYCoordinates != 0)
{
Q_ASSERT (columnNode->childCount() >= _columnBuffer[dirtyColI].validDirtyYCoordinates);
for (auto rowI = 0; rowI < _columnBuffer[dirtyColI].validDirtyYCoordinates; rowI++)
{
QSGGeometryNode *rowNode = static_cast<QSGGeometryNode*>(columnNode->childAtIndex(rowI));
geometry = rowNode->geometry();
geometry->vertexDataAsPoint2D()[0].set(updateCol, _columnBuffer[dirtyColI].dirtyYCoordinates[rowI].y);
geometry->vertexDataAsPoint2D()[1].set(updateCol, _columnBuffer[dirtyColI].dirtyYCoordinates[rowI].y1);
rowNode->markDirty(QSGNode::DirtyGeometry);
}
}
else
{
for (auto rowI = 0; rowI < columnNode->childCount(); rowI++)
{
QSGGeometryNode *rowNode = static_cast<QSGGeometryNode*>(columnNode->childAtIndex(rowI));
geometry = rowNode->geometry();
geometry->vertexDataAsPoint2D()[0].set(updateCol, 0);
geometry->vertexDataAsPoint2D()[1].set(updateCol, 0);
rowNode->markDirty(QSGNode::DirtyGeometry);
}
}
}
return parentNode;
}
void QSGPlot::createGeometryChildNodes(QSGNode *parent, const QColor &color, const size_t &childCount)
{
for (size_t childI = 0; childI < childCount; childI++)
{
QSGGeometryNode *childNode = new QSGGeometryNode;
QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 2);
geometry->setLineWidth(1);
geometry->setDrawingMode(GL_LINES);
childNode->setGeometry(geometry);
childNode->setFlag(QSGNode::OwnsGeometry);
QSGFlatColorMaterial* material = new QSGFlatColorMaterial();
material->setColor(color);
childNode->setMaterial(material);
childNode->setFlag(QSGNode::OwnsMaterial);
parent->appendChildNode(childNode);
}
}
谁能指出我在此实现中做错了什么。 Find the screen recording of application here.