5#include <QtQuick3DRuntimeRender/private/qssgrendermesh_p.h>
6#include <QtQuick/qquickwindow.h>
7#include <QtQuick/qquickitem.h>
48 return m_results.frameTime;
61 return m_results.renderTime;
74 return m_results.renderPrepareTime;
87 return m_results.syncTime;
99 return m_maxFrameTime;
102float QQuick3DRenderStats::timestamp()
const
109 m_syncStartTime = timestamp();
114 m_results.syncTime = timestamp() - m_syncStartTime;
117 qDebug(
"Sync took: %f ms", m_results.syncTime);
122 m_renderStartTime = timestamp();
127 m_renderPrepareStartTime = timestamp();
132 m_results.renderPrepareTime = timestamp() - m_renderPrepareStartTime;
144 m_renderingThisFrame =
true;
145 const float endTime = timestamp();
146 m_results.renderTime = endTime - m_renderStartTime;
149 qDebug(
"Render took: %f ms (of which prep: %f ms)", m_results.renderTime, m_results.renderPrepareTime);
152void QQuick3DRenderStats::onFrameSwapped()
157 if (m_renderingThisFrame) {
159 m_results.frameTime = timestamp();
160 m_internalMaxFrameTime =
qMax(m_results.frameTime, m_internalMaxFrameTime);
162 m_secTimer += m_results.frameTime;
163 m_notifyTimer += m_results.frameTime;
165 m_results.renderTime = m_results.frameTime - m_renderStartTime;
167 processRhiContextStats();
174 const float msecs = float(
cb->lastCompletedGpuTime() * 1000.0);
176 m_results.lastCompletedGpuTime = msecs;
181 const float notifyInterval = 200.0f;
182 if (m_notifyTimer >= notifyInterval) {
183 m_notifyTimer -= notifyInterval;
185 if (m_results.frameTime != m_notifiedResults.frameTime) {
186 m_notifiedResults.frameTime = m_results.frameTime;
190 if (m_results.syncTime != m_notifiedResults.syncTime) {
191 m_notifiedResults.syncTime = m_results.syncTime;
195 if (m_results.renderTime != m_notifiedResults.renderTime) {
196 m_notifiedResults.renderTime = m_results.renderTime;
197 m_notifiedResults.renderPrepareTime = m_results.renderPrepareTime;
201 if (m_results.lastCompletedGpuTime != m_notifiedResults.lastCompletedGpuTime) {
202 m_notifiedResults.lastCompletedGpuTime = m_results.lastCompletedGpuTime;
206 notifyRhiContextStats();
209 const float fpsInterval = 1000.0f;
210 if (m_secTimer >= fpsInterval) {
211 m_secTimer -= fpsInterval;
213 m_fps = m_frameCount;
217 m_maxFrameTime = m_internalMaxFrameTime;
218 m_internalMaxFrameTime = 0;
222 m_renderingThisFrame =
false;
239 if (m_extendedDataCollectionEnabled)
242 if (m_contextStats && m_contextStats->
rhiCtx->
rhi()) {
262 m_frameSwappedConnection =
connect(m_window, &QQuickWindow::afterFrameEnd,
263 this, &QQuick3DRenderStats::onFrameSwapped,
288 return m_extendedDataCollectionEnabled;
293 if (
enable != m_extendedDataCollectionEnabled) {
294 m_extendedDataCollectionEnabled =
enable;
297 if (m_contextStats) {
302 if (m_extendedDataCollectionEnabled)
361 return "ETC2_RGB8A1";
410 if (!mesh->
subsets.isEmpty()) {
413 return buf->buffer()->name();
418void QQuick3DRenderStats::processRhiContextStats()
420 if (!m_contextStats || !m_extendedDataCollectionEnabled)
431 const auto textures = rhiCtxD->m_textures;
432 const auto meshes = rhiCtxD->m_meshes;
433 const auto pipelines = rhiCtxD->m_pipelines;
435 m_results.drawCallCount = 0;
436 m_results.drawVertexCount = 0;
437 for (
const auto &pass :
data.renderPasses) {
444 m_results.imageDataSize = globalData.imageDataSize;
445 m_results.meshDataSize = globalData.meshDataSize;
447 m_results.renderPassCount =
data.renderPasses.size()
448 + (
data.externalRenderPass.pixelSize.isEmpty() ? 0 : 1);
451| Name | Size | Vertices | Draw calls |
452| ---- | ---- | -------- | ---------- |
455 if (!
data.externalRenderPass.pixelSize.isEmpty())
457 for (
const auto &pass :
data.renderPasses) {
458 if (!pass.pixelSize.isEmpty())
464 if (m_results.activeTextures !=
textures) {
465 m_results.activeTextures =
textures;
467| Name | Size | Format | Mip | Flags |
468| ---- | ---- | ------ | --- | ----- |
470 QList<QRhiTexture *> textureList = textures.values();
472 return a->name() < b->name();
476 const QRhiTexture::Flags
flags = tex->flags();
483 tex->name().constData(),
484 tex->pixelSize().width(),
485 tex->pixelSize().height(),
488 flagMsg.constData());
491 m_results.textureDetails = texDetails;
494 if (m_results.activeMeshes != meshes) {
495 m_results.activeMeshes = meshes;
497| Name | Submeshes | Vertices | V.buf size | I.buf size |
498| ---- | --------- | -------- | ---------- | ---------- |
500 QList<QSSGRenderMesh *> meshList = meshes.values();
502 return nameForRenderMesh(a) < nameForRenderMesh(b);
506 const int subsetCount = int(mesh->subsets.size());
510 if (subsetCount > 0) {
512 vertexCount += subset.
count;
514 const QSSGRhiBuffer *vbuf = mesh->subsets[0].rhi.vertexBuffer.get();
517 const QSSGRhiBuffer *ibuf = mesh->subsets[0].rhi.indexBuffer.get();
533 m_results.pipelineCount =
pipelines.count();
541void QQuick3DRenderStats::notifyRhiContextStats()
543 if (!m_contextStats || !m_extendedDataCollectionEnabled)
546 if (m_results.drawCallCount != m_notifiedResults.drawCallCount) {
547 m_notifiedResults.drawCallCount = m_results.drawCallCount;
551 if (m_results.drawVertexCount != m_notifiedResults.drawVertexCount) {
552 m_notifiedResults.drawVertexCount = m_results.drawVertexCount;
556 if (m_results.imageDataSize != m_notifiedResults.imageDataSize) {
557 m_notifiedResults.imageDataSize = m_results.imageDataSize;
561 if (m_results.meshDataSize != m_notifiedResults.meshDataSize) {
562 m_notifiedResults.meshDataSize = m_results.meshDataSize;
566 if (m_results.renderPassCount != m_notifiedResults.renderPassCount) {
567 m_notifiedResults.renderPassCount = m_results.renderPassCount;
571 if (m_results.renderPassDetails != m_notifiedResults.renderPassDetails) {
572 m_notifiedResults.renderPassDetails = m_results.renderPassDetails;
576 if (m_results.textureDetails != m_notifiedResults.textureDetails) {
577 m_notifiedResults.textureDetails = m_results.textureDetails;
581 if (m_results.meshDetails != m_notifiedResults.meshDetails) {
582 m_notifiedResults.meshDetails = m_results.meshDetails;
586 if (m_results.pipelineCount != m_notifiedResults.pipelineCount) {
587 m_notifiedResults.pipelineCount = m_results.pipelineCount;
591 if (m_results.materialGenerationTime != m_notifiedResults.materialGenerationTime) {
592 m_notifiedResults.materialGenerationTime = m_results.materialGenerationTime;
596 if (m_results.effectGenerationTime != m_notifiedResults.effectGenerationTime) {
597 m_notifiedResults.effectGenerationTime = m_results.effectGenerationTime;
631 return m_results.drawCallCount;
652 return m_results.drawVertexCount;
674 return m_results.imageDataSize;
696 return m_results.meshDataSize;
718 return m_results.renderPassCount;
729 return m_results.renderPassDetails;
740 return m_results.textureDetails;
751 return m_results.meshDetails;
771 return m_results.pipelineCount;
792 return m_results.materialGenerationTime;
813 return m_results.effectGenerationTime;
916 return m_graphicsApiName;
943 return m_results.lastCompletedGpuTime;
954 qWarning(
"QQuick3DRenderStats: No window, cannot request releasing cached resources");
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
qint64 restart() noexcept
Restarts the timer and returns the number of milliseconds elapsed since the previous start.
void start() noexcept
\typealias QElapsedTimer::Duration Synonym for std::chrono::nanoseconds.
qint64 nsecsElapsed() const noexcept
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
void setWindow(QQuickWindow *window)
void graphicsApiNameChanged()
QQuick3DRenderStats(QObject *parent=nullptr)
\qmltype RenderStats \inqmlmodule QtQuick3D
void meshDataSizeChanged()
void lastCompletedGpuTimeChanged()
void setExtendedDataCollectionEnabled(bool enable)
void pipelineCreationTimeChanged()
qint64 materialGenerationTime
void maxFrameTimeChanged()
void endSync(bool dump=false)
void setRhiContext(QSSGRhiContext *ctx, QSSGRenderLayer *layer)
void pipelineCountChanged()
void drawCallCountChanged()
void meshDetailsChanged()
bool extendedDataCollectionEnabled
void materialGenerationTimeChanged()
void startRenderPrepare()
void vmemUsedBytesChanged()
void textureDetailsChanged()
void vmemAllocCountChanged()
void drawVertexCountChanged()
Q_INVOKABLE void releaseCachedResources()
float lastCompletedGpuTime
QString renderPassDetails
void imageDataSizeChanged()
qint64 pipelineCreationTime
void effectGenerationTimeChanged()
void extendedDataCollectionEnabledChanged()
qint64 effectGenerationTime
void endRender(bool dump=false)
void renderPassDetailsChanged()
void renderPassCountChanged()
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
void releaseResources()
This function tries to release redundant resources currently held by the QML scene.
virtual QRhiCommandBuffer * currentFrameCommandBuffer()=0
Format
Specifies the texture format.
QRhiStats statistics() const
Gathers and returns statistics about the timings and allocations of graphics resources.
static int mipLevelsForSize(const QSize &size)
const char * backendName() const
QRhiBuffer * buffer() const
static QSSGRhiContextPrivate * get(QSSGRhiContext *q)
static quint64 totalVertexCountForPass(const QSSGRhiContextStats::RenderPassInfo &pass)
static QSSGRhiContextStats & get(QSSGRhiContext &rhiCtx)
QHash< QSSGRenderLayer *, PerLayerInfo > perLayerInfo
static quint64 totalDrawCallCountForPass(const QSSGRhiContextStats::RenderPassInfo &pass)
QSet< QSSGRenderLayer * > dynamicDataSources
bool remove(const T &value)
iterator insert(const T &value)
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
Combined button and popup list for selecting options.
#define QByteArrayLiteral(str)
bool qFuzzyIsNull(qfloat16 f) noexcept
constexpr const T & qMax(const T &a, const T &b)
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint const GLuint GLuint const GLuint * textures
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLsizei GLsizei GLenum format
static QByteArray nameForRenderMesh(const QSSGRenderMesh *mesh)
static void printRenderPassDetails(QString *dst, const QSSGRhiContextStats::RenderPassInfo &rp)
static const char * textureFormatStr(QRhiTexture::Format format)
static QString dump(const QByteArray &)
SSL_CTX int(* cb)(SSL *ssl, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
QLatin1StringView QLatin1String
unsigned long long quint64
myObject disconnect()
[26]
qint64 totalPipelineCreationTime
QVector< QSSGRenderSubset > subsets
qint64 materialGenerationTime
qint64 effectGenerationTime