8#include <private/qsgmaterialshader_p.h>
15#define QSGNODE_TRAVERSE(NODE) for (QSGNode *child = NODE->firstChild(); child; child = child->nextSibling())
16#define SHADOWNODE_TRAVERSE(NODE) for (Node *child = NODE->firstChild(); child; child = child->sibling())
17#define QSGNODE_DIRTY_PARENT (QSGNode::DirtyNodeAdded \
18 | QSGNode::DirtyOpacity \
19 | QSGNode::DirtyMatrix \
20 | QSGNode::DirtyNodeRemoved)
39 m_pipelines.releaseResources();
41 m_fade.releaseResources();
43 m_changeVis.releaseResources();
44 m_batchVis.releaseResources();
45 m_clipVis.releaseResources();
46 m_overdrawVis.releaseResources();
60 QLatin1String(
":/qt-project.org/scenegraph/shaders_ng/visualization.vert.qsb"));
62 QLatin1String(
":/qt-project.org/scenegraph/shaders_ng/visualization.frag.qsb"));
67 const bool forceUintIndex =
m_renderer->m_uint32IndexForRhi;
107 m_batchVis.render(
cb);
110 m_clipVis.render(
cb);
113 m_changeVis.render(
cb);
116 m_overdrawVis.render(
cb);
124void RhiVisualizer::recordDrawCalls(
const QVector<DrawCall> &drawCalls,
129 for (
const DrawCall &dc : drawCalls) {
131 dc.vertex.topology, dc.vertex.format, dc.vertex.stride,
135 cb->setGraphicsPipeline(ps);
137 cb->setShaderResources(srb, 1, &dynofs);
139 if (dc.index.count) {
140 cb->setVertexInput(0, 1, &vb, dc.buf.ibuf, dc.buf.ibufOffset, dc.index.format);
141 cb->drawIndexed(dc.index.count);
143 cb->setVertexInput(0, 1, &vb);
144 cb->draw(dc.vertex.count);
155 this->visualizer = visualizer;
158 float v[] = { -1, 1, 1, 1, -1, -1, 1, -1 };
169 float bgOpacity = 0.8f;
175 float color[4] = { 0.0f, 0.0f, 0.0f, bgOpacity };
199 inputLayout.
setBindings({ { 2 *
sizeof(float) } });
209void RhiVisualizer::Fade::releaseResources()
226 cb->setGraphicsPipeline(ps);
227 cb->setViewport(visualizer->m_renderer->m_pstate.viewport);
228 cb->setShaderResources();
230 cb->setVertexInput(0, 1, &vb);
238 dc->
vertex.count =
g->vertexCount();
239 dc->
vertex.stride =
g->sizeOfVertex();
241 dc->
vertex.data =
g->vertexData();
244 dc->
index.count =
g->indexCount();
245 dc->
index.stride = forceUintIndex ?
sizeof(
quint32) :
g->sizeOfIndex();
246 if (withData &&
g->indexCount())
247 dc->
index.data =
g->indexData();
252 return (
v + byteAlign - 1) & ~(byteAlign - 1);
259 if (!(*buf)->create())
261 }
else if ((*buf)->size() < newSize) {
263 if (!(*buf)->create())
280 if (
p.topology == topology &&
p.format == vertexFormat &&
p.stride == vertexStride)
308 p.topology = topology;
309 p.format = vertexFormat;
310 p.stride = vertexStride;
317void RhiVisualizer::PipelineCache::releaseResources()
325void RhiVisualizer::ChangeVis::gather(
Node *
n)
328 const uint dirty = visualizer->m_visualizeChangeSet.value(
n);
331 const float alpha = 0.5f;
334 if (
n->element()->batch->root)
341 if (
g->attributeCount() >= 1) {
343 memcpy(dc.uniforms.data,
matrix.constData(), 64);
345 memcpy(dc.uniforms.data + 64, rotation.
constData(), 64);
352 memcpy(dc.uniforms.data + 128,
c, 16);
353 float pattern = tinted ? 0.5f : 0.0f;
354 memcpy(dc.uniforms.data + 144, &
pattern, 4);
356 memcpy(dc.uniforms.data + 148, &projection, 4);
359 drawCalls.append(dc);
376 this->visualizer = visualizer;
381 if (drawCalls.isEmpty())
388 for (RhiVisualizer::DrawCall &dc : drawCalls) {
389 dc.buf.vbufOffset =
aligned(vbufOffset, 4);
390 vbufOffset = dc.buf.vbufOffset + dc.vertex.count * dc.vertex.stride;
392 dc.buf.ibufOffset =
aligned(ibufOffset, 4);
393 ibufOffset = dc.buf.ibufOffset + dc.index.count * dc.index.stride;
395 dc.buf.ubufOffset =
aligned(ubufOffset, ubufAlign);
402 const int ubufSize = ubufOffset;
405 for (RhiVisualizer::DrawCall &dc : drawCalls) {
406 u->
updateDynamicBuffer(vbuf, dc.buf.vbufOffset, dc.vertex.count * dc.vertex.stride, dc.vertex.data);
408 if (dc.index.count) {
409 u->
updateDynamicBuffer(ibuf, dc.buf.ibufOffset, dc.index.count * dc.index.stride, dc.index.data);
423void RhiVisualizer::ChangeVis::releaseResources()
440 visualizer->recordDrawCalls(drawCalls,
cb, srb);
443void RhiVisualizer::BatchVis::gather(Batch *
b)
445 if (
b->positionAttribute != 0)
455 memcpy(dc.uniforms.data + 64, rotation.
constData(), 64);
461 float(
color.greenF()),
462 float(
color.blueF()),
465 memcpy(dc.uniforms.data + 128,
c, 16);
467 float pattern =
b->merged ? 0.0f : 1.0f;
468 memcpy(dc.uniforms.data + 144, &
pattern, 4);
471 memcpy(dc.uniforms.data + 148, &projection, 4);
474 memcpy(dc.uniforms.data,
matrix.constData(), 64);
481 for (
int ds = 0; ds <
b->drawSets.size(); ++ds) {
482 const DrawSet &
set =
b->drawSets.at(ds);
483 dc.buf.vbuf =
b->vbo.buf;
484 dc.buf.vbufOffset =
set.vertices;
485 dc.buf.ibuf =
b->ibo.buf;
486 dc.buf.ibufOffset =
set.indices;
487 dc.index.count =
set.indexCount;
488 drawCalls.append(dc);
500 memcpy(dc.uniforms.data,
m.constData(), 64);
504 dc.buf.vbuf =
b->vbo.buf;
505 dc.buf.vbufOffset = vOffset;
506 if (
g->indexCount()) {
507 dc.buf.ibuf =
b->ibo.buf;
508 dc.buf.ibufOffset = iOffset;
511 drawCalls.append(dc);
513 vOffset += dc.vertex.count * dc.vertex.stride;
514 iOffset += dc.index.count * dc.index.stride;
521void RhiVisualizer::BatchVis::prepare(
const QDataBuffer<Batch *> &opaqueBatches,
const QDataBuffer<Batch *> &alphaBatches,
526 this->visualizer = visualizer;
527 this->forceUintIndex = forceUintIndex;
531 for (
int i = 0;
i < opaqueBatches.size(); ++
i)
532 gather(opaqueBatches.at(
i));
533 for (
int i = 0;
i < alphaBatches.size(); ++
i)
534 gather(alphaBatches.at(
i));
536 if (drawCalls.isEmpty())
541 for (RhiVisualizer::DrawCall &dc : drawCalls) {
542 dc.buf.ubufOffset =
aligned(ubufOffset, ubufAlign);
546 const int ubufSize = ubufOffset;
549 for (RhiVisualizer::DrawCall &dc : drawCalls)
550 u->updateDynamicBuffer(ubuf, dc.
buf.ubufOffset, DrawCall::
UBUF_SIZE, dc.uniforms.
data);
560void RhiVisualizer::BatchVis::releaseResources()
571 visualizer->recordDrawCalls(drawCalls,
cb, srb);
574void RhiVisualizer::ClipVis::gather(
QSGNode *node)
583 if (
g->attributeCount() >= 1) {
585 memcpy(dc.uniforms.data,
matrix.constData(), 64);
587 memcpy(dc.uniforms.data + 64, rotation.
constData(), 64);
588 float c[4] = { 0.2f, 0.0f, 0.0f, 0.2f };
589 memcpy(dc.uniforms.data + 128,
c, 16);
591 memcpy(dc.uniforms.data + 144, &
pattern, 4);
593 memcpy(dc.uniforms.data + 148, &projection, 4);
595 drawCalls.append(dc);
607 this->visualizer = visualizer;
612 if (drawCalls.isEmpty())
619 for (RhiVisualizer::DrawCall &dc : drawCalls) {
620 dc.buf.vbufOffset =
aligned(vbufOffset, 4);
621 vbufOffset = dc.buf.vbufOffset + dc.vertex.count * dc.vertex.stride;
623 dc.buf.ibufOffset =
aligned(ibufOffset, 4);
624 ibufOffset = dc.buf.ibufOffset + dc.index.count * dc.index.stride;
626 dc.buf.ubufOffset =
aligned(ubufOffset, ubufAlign);
633 const int ubufSize = ubufOffset;
636 for (RhiVisualizer::DrawCall &dc : drawCalls) {
637 u->
updateDynamicBuffer(vbuf, dc.buf.vbufOffset, dc.vertex.count * dc.vertex.stride, dc.vertex.data);
639 if (dc.index.count) {
640 u->
updateDynamicBuffer(ibuf, dc.buf.ibufOffset, dc.index.count * dc.index.stride, dc.index.data);
654void RhiVisualizer::ClipVis::releaseResources()
671 visualizer->recordDrawCalls(drawCalls,
cb, srb);
674void RhiVisualizer::OverdrawVis::gather(
Node *
n)
678 matrix(2, 2) = visualizer->m_renderer->m_zRange;
679 matrix(2, 3) = 1.0f -
n->element()->order * visualizer->m_renderer->m_zRange;
681 if (
n->element()->batch->root)
688 if (
g->attributeCount() >= 1) {
690 memcpy(dc.uniforms.data,
matrix.constData(), 64);
691 memcpy(dc.uniforms.data + 64, rotation.
constData(), 64);
694 const float ca = 0.33f;
695 if (
n->element()->batch->isOpaque) {
696 c[0] = ca * 0.3f;
c[1] = ca * 1.0f;
c[2] = ca * 0.3f;
c[3] = ca;
698 c[0] = ca * 1.0f;
c[1] = ca * 0.3f;
c[2] = ca * 0.3f;
c[3] = ca;
700 memcpy(dc.uniforms.data + 128,
c, 16);
702 memcpy(dc.uniforms.data + 144, &
pattern, 4);
704 memcpy(dc.uniforms.data + 148, &projection, 4);
707 drawCalls.append(dc);
719 this->visualizer = visualizer;
721 step += float(
M_PI * 2 / 1000.0);
722 if (step >
float(
M_PI * 2))
725 const float yfix = rhi->
isYUpInNDC() ? 1.0f : -1.0f;
727 rotation.
translate(0.0f, 0.5f * yfix, 4.0f);
728 rotation.
scale(2.0f, 2.0f, 1.0f);
729 rotation.
rotate(-30.0f * yfix, 1.0f, 0.0f, 0.0f);
730 rotation.
rotate(80.0f * std::sin(step), 0.0f, 1.0f, 0.0f);
751 -1, -1, 0, -1, -1, 1,
757 if (!
box.vbuf->create())
764 if (!
box.ubuf->create())
768 float color[4] = { 0.5f, 0.5f, 1.0f, 1.0f };
781 if (!
box.srb->create())
788 box.ps->setLineWidth(2);
795 box.ps->setTargetBlends({ blend });
799 inputLayout.
setBindings({ { 3 *
sizeof(float) } });
801 box.ps->setVertexInputLayout(inputLayout);
802 box.ps->setShaderResourceBindings(
box.srb);
803 box.ps->setRenderPassDescriptor(visualizer->m_renderer->renderTarget().rpDesc);
804 if (!
box.ps->create())
808 if (drawCalls.isEmpty())
815 for (RhiVisualizer::DrawCall &dc : drawCalls) {
816 dc.buf.vbufOffset =
aligned(vbufOffset, 4);
817 vbufOffset = dc.buf.vbufOffset + dc.vertex.count * dc.vertex.stride;
819 dc.buf.ibufOffset =
aligned(ibufOffset, 4);
820 ibufOffset = dc.buf.ibufOffset + dc.index.count * dc.index.stride;
822 dc.buf.ubufOffset =
aligned(ubufOffset, ubufAlign);
829 const int ubufSize = ubufOffset;
832 for (RhiVisualizer::DrawCall &dc : drawCalls) {
833 u->
updateDynamicBuffer(vbuf, dc.buf.vbufOffset, dc.vertex.count * dc.vertex.stride, dc.vertex.data);
835 if (dc.index.count) {
836 u->
updateDynamicBuffer(ibuf, dc.buf.ibufOffset, dc.index.count * dc.index.stride, dc.index.data);
850void RhiVisualizer::OverdrawVis::releaseResources()
879 cb->setGraphicsPipeline(
box.ps);
880 cb->setShaderResources();
882 cb->setVertexInput(0, 1, &vb);
885 visualizer->recordDrawCalls(drawCalls,
cb, srb,
true);
The QColor class provides colors based on RGB, HSV or CMYK values.
static QColor fromHsvF(float h, float s, float v, float a=1.0)
This is an overloaded member function, provided for convenience. It differs from the above function o...
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
void rotate(float angle, const QVector3D &vector)
Multiples this matrix by another that rotates coordinates through angle degrees about vector.
void scale(const QVector3D &vector)
Multiplies this matrix by another that scales coordinates by the components of vector.
void setToIdentity()
Sets this matrix to the identity.
const float * constData() const
Returns a constant pointer to the raw data of this matrix.
void translate(const QVector3D &vector)
Multiplies this matrix by another that translates coordinates by the components of vector.
void setSize(quint32 sz)
Sets the size of the buffer in bytes.
virtual bool create()=0
Creates the corresponding native graphics resources.
QPair< int, quint32 > DynamicOffset
Synonym for QPair<int, quint32>.
QPair< QRhiBuffer *, quint32 > VertexInput
Synonym for QPair<QRhiBuffer *, quint32>.
IndexFormat
Specifies the index data type.
void setTargetBlends(std::initializer_list< TargetBlend > list)
Sets the list of render target blend settings.
void setShaderResourceBindings(QRhiShaderResourceBindings *srb)
Associates with srb describing the resource binding layout and the resources (QRhiBuffer,...
void setVertexInputLayout(const QRhiVertexInputLayout &layout)
Specifies the vertex input layout.
void setShaderStages(std::initializer_list< QRhiShaderStage > list)
Sets the list of shader stages.
void setRenderPassDescriptor(QRhiRenderPassDescriptor *desc)
Associates with the specified QRhiRenderPassDescriptor desc.
void setTopology(Topology t)
Sets the primitive topology t.
Topology
Specifies the primitive topology.
virtual bool create()=0
Creates the corresponding native graphics resources.
void updateDynamicBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Enqueues updating a region of a QRhiBuffer buf created with the type QRhiBuffer::Dynamic.
void uploadStaticBuffer(QRhiBuffer *buf, quint32 offset, quint32 size, const void *data)
Enqueues updating a region of a QRhiBuffer buf created with the type QRhiBuffer::Immutable or QRhiBuf...
static QRhiShaderResourceBinding uniformBufferWithDynamicOffset(int binding, StageFlags stage, QRhiBuffer *buf, quint32 size)
static QRhiShaderResourceBinding uniformBuffer(int binding, StageFlags stage, QRhiBuffer *buf)
void setBindings(std::initializer_list< QRhiShaderResourceBinding > list)
Sets the list of bindings.
\inmodule QtGuiPrivate \inheaderfile rhi/qrhi.h
QRhiBuffer * newBuffer(QRhiBuffer::Type type, QRhiBuffer::UsageFlags usage, quint32 size)
QRhiShaderResourceBindings * newShaderResourceBindings()
QRhiGraphicsPipeline * newGraphicsPipeline()
int ubufAlignment() const
QSGRootNode * rootNode() const
Returns the root of the QSGNode scene.
const QSGGeometry * geometry() const
Returns this node's geometry.
const QMatrix4x4 * matrix() const
Will be set during rendering to contain transformation of the geometry for that rendering pass.
void releaseResources() override
void prepareVisualize() override
void visualize() override
RhiVisualizer(Renderer *renderer)
QHash< Node *, uint > m_visualizeChangeSet
VisualizeMode m_visualizeMode
The QSGClipNode class implements the clipping functionality in the scene graph.
The QSGGeometryNode class is used for all rendered content in the scene graph.
The QSGGeometry class provides low-level storage for graphics primitives in the \l{Qt Quick Scene Gra...
static QShader loadShader(const QString &filename)
\group qtquick-scenegraph-nodes \title Qt Quick Scene Graph Node classes
NodeType type() const
Returns the type of this node.
QRhiRenderPassDescriptor * rpDesc
const QSGRenderTarget & renderTarget() const
static bool ensureBuffer(QRhi *rhi, QRhiBuffer **buf, QRhiBuffer::UsageFlags usage, quint32 newSize)
QRhiVertexInputAttribute::Format qsg_vertexInputFormat(const QSGGeometry::Attribute &a)
QMatrix4x4 qsg_matrixForRoot(Node *node)
const QRhiShaderResourceBinding::StageFlags ubufVisibility
QRhiCommandBuffer::IndexFormat qsg_indexFormat(const QSGGeometry *geometry)
static void fillVertexIndex(RhiVisualizer::DrawCall *dc, QSGGeometry *g, bool withData, bool forceUintIndex)
QRhiGraphicsPipeline::Topology qsg_topology(int geomDrawMode)
Int aligned(Int v, Int byteAlign)
Combined button and popup list for selecting options.
static const int UBUF_SIZE
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLenum GLsizei const GLchar * buf
GLsizei const GLint * box
GLfloat GLfloat GLfloat alpha
GLsizeiptr const void GLenum usage
#define QSGNODE_DIRTY_PARENT
#define SHADOWNODE_TRAVERSE(NODE)
#define QSGNODE_TRAVERSE(NODE)
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
QLatin1StringView QLatin1String
QFuture< QSet< QChar > > set
[10]
QSvgRenderer * renderer
[0]
static const int UBUF_SIZE
struct QSGBatchRenderer::RhiVisualizer::DrawCall::@703 vertex
struct QSGBatchRenderer::RhiVisualizer::DrawCall::@704 index
The QSGGeometry::Attribute describes a single vertex attribute in a QSGGeometry.