From 92c508653891395c7ca12b95fd1e6f184b43ba7a Mon Sep 17 00:00:00 2001 From: Juan Jose Casafranca Date: Tue, 19 Nov 2019 11:41:32 +0100 Subject: [PATCH] Add texture memory usage in gltfEditor Change-Id: Ie24db0274dcdc1bd34bcf7b79ff4658b713945e0 Reviewed-on: https://kuesa-codereview.kdab.com/c/kuesa/kuesa/+/337 Reviewed-by: Paul Lemire --- src/core/gltf2importer/textureparser.cpp | 28 +- src/core/gltf2importer/textureparser_p.h | 14 +- tools/gltfEditor/memoryusagewidget.cpp | 42 ++ tools/gltfEditor/memoryusagewidget.h | 2 + tools/gltfEditor/textureinspector.cpp | 29 + tools/gltfEditor/textureinspector.h | 3 + tools/gltfEditor/texturewidget.cpp | 18 + tools/gltfEditor/texturewidget.ui | 658 +++++++++++------------ 8 files changed, 427 insertions(+), 367 deletions(-) diff --git a/src/core/gltf2importer/textureparser.cpp b/src/core/gltf2importer/textureparser.cpp index bcf46fe87..5c88c9195 100644 --- a/src/core/gltf2importer/textureparser.cpp +++ b/src/core/gltf2importer/textureparser.cpp @@ -73,24 +73,22 @@ class EmbeddedTextureImageFunctor : public Qt3DRender::QTextureImageDataGenerato QImage m_image; }; -class EmbeddedTextureImage : public Qt3DRender::QAbstractTextureImage -{ -public: - EmbeddedTextureImage(const QImage &image, QNode *parent = nullptr) - : Qt3DRender::QAbstractTextureImage(parent), m_image(image) - { - } +} // namespace - Qt3DRender::QTextureImageDataGeneratorPtr dataGenerator() const - { - return Qt3DRender::QTextureImageDataGeneratorPtr(new EmbeddedTextureImageFunctor(m_image)); - } +TextureParser::EmbeddedTextureImage::EmbeddedTextureImage(const QImage &image, Qt3DCore::QNode *parent) + : Qt3DRender::QAbstractTextureImage(parent), m_image(image) +{ +} -private: - QImage m_image; -}; +Qt3DRender::QTextureImageDataGeneratorPtr TextureParser::EmbeddedTextureImage::dataGenerator() const +{ + return Qt3DRender::QTextureImageDataGeneratorPtr(new EmbeddedTextureImageFunctor(m_image)); +} -} // namespace +QImage TextureParser::EmbeddedTextureImage::image() +{ + return m_image; +} bool TextureParser::parse(const QJsonArray &texturesArray, GLTF2Context *context) const { diff --git a/src/core/gltf2importer/textureparser_p.h b/src/core/gltf2importer/textureparser_p.h index 0d3ed841b..e972458bd 100644 --- a/src/core/gltf2importer/textureparser_p.h +++ b/src/core/gltf2importer/textureparser_p.h @@ -38,12 +38,12 @@ // #include +#include QT_BEGIN_NAMESPACE namespace Qt3DRender { class QAbstractTexture; -class QAbstractTextureImage; } // namespace Qt3DRender namespace Kuesa { @@ -64,6 +64,18 @@ class Q_AUTOTEST_EXPORT TextureParser bool parse(const QJsonArray &texturesArray, GLTF2Context *context) const; static bool ensureImageIsCompatibleWithTexture(Qt3DRender::QAbstractTextureImage *image, Qt3DRender::QAbstractTexture *texture); + + class EmbeddedTextureImage : public Qt3DRender::QAbstractTextureImage + { + public: + EmbeddedTextureImage(const QImage &image, QNode *parent = nullptr); + Qt3DRender::QTextureImageDataGeneratorPtr dataGenerator() const; + + QImage image(); + + private: + QImage m_image; + }; }; } // namespace GLTF2Import diff --git a/tools/gltfEditor/memoryusagewidget.cpp b/tools/gltfEditor/memoryusagewidget.cpp index e110ac6be..a7dd8feee 100644 --- a/tools/gltfEditor/memoryusagewidget.cpp +++ b/tools/gltfEditor/memoryusagewidget.cpp @@ -43,6 +43,9 @@ #include #include +#include +#include "textureinspector.h" + namespace { const QLatin1String LASTPATHSETTING("mainwindow/lastPath"); @@ -77,6 +80,26 @@ void MemoryUsageWidget::setSceneEntity(Kuesa::SceneEntity *sceneEntity) } void MemoryUsageWidget::updateWidgetValues() +{ + updateGeometryMemoryUsage(); + + Kuesa::TextureCollection *texturesCollection = m_sceneEntity->textures(); + const auto &names = texturesCollection->names(); + + // Textures are loaded by the backend, so we dont have yet the data for the + // texture Instead of calling directly updateTextureMemoryUsage, we wait + // until we receive a statusChanged notification + for (const auto &name : qAsConst(names)) { + Qt3DRender::QAbstractTexture *texture = texturesCollection->find(name); + QObject::connect(texture, &Qt3DRender::QAbstractTexture::statusChanged, + [this] (Qt3DRender::QAbstractTexture::Status status) { + if (status == Qt3DRender::QAbstractTexture::Status::Ready) + updateTextureMemoryUsage(); + }); + } +} + +void MemoryUsageWidget::updateGeometryMemoryUsage() const { Kuesa::MeshCollection *meshesCollection = m_sceneEntity->meshes(); const auto &names = meshesCollection->names(); @@ -97,3 +120,22 @@ void MemoryUsageWidget::updateWidgetValues() m_ui->geometryUsage->setText(totalSizeString(geometrySize)); } + +void MemoryUsageWidget::updateTextureMemoryUsage() const +{ + Kuesa::TextureCollection *texturesCollection = m_sceneEntity->textures(); + const auto &names = texturesCollection->names(); + + int texturesSize = 0; + QVector visitedImages; + for (const auto &name : qAsConst(names)) { + Qt3DRender::QAbstractTexture *texture = texturesCollection->find(name); + Qt3DRender::QAbstractTextureImage *image = texture->textureImages()[0]; + if (!visitedImages.contains(image)) { + visitedImages.push_back(image); + texturesSize += ::textureSizeInBytes(texture); + } + } + + m_ui->textureUsage->setText(totalSizeString(texturesSize)); +} diff --git a/tools/gltfEditor/memoryusagewidget.h b/tools/gltfEditor/memoryusagewidget.h index 3d8b2497d..c4e8bf9af 100644 --- a/tools/gltfEditor/memoryusagewidget.h +++ b/tools/gltfEditor/memoryusagewidget.h @@ -54,6 +54,8 @@ class MemoryUsageWidget : public QWidget private: void updateWidgetValues(); + void updateGeometryMemoryUsage() const; + void updateTextureMemoryUsage() const; QScopedPointer m_ui; Kuesa::SceneEntity *m_sceneEntity; diff --git a/tools/gltfEditor/textureinspector.cpp b/tools/gltfEditor/textureinspector.cpp index 3409a469f..d9837e164 100644 --- a/tools/gltfEditor/textureinspector.cpp +++ b/tools/gltfEditor/textureinspector.cpp @@ -28,6 +28,9 @@ #include "textureinspector.h" #include +#include + +#include namespace { @@ -156,6 +159,11 @@ QString TextureInspector::magnificationFilter() const return (m_texture != nullptr) ? filtersToName.value(m_texture->magnificationFilter(), QStringLiteral("Undefined")) : QStringLiteral("Undefined"); } +int TextureInspector::textureSize() const +{ + return ::textureSizeInBytes(m_texture); +} + TextureImagesModel::TextureImagesModel(QObject *parent) : QAbstractTableModel(parent) , m_texture(nullptr) @@ -226,3 +234,24 @@ QVariant TextureImagesModel::headerData(int section, Qt::Orientation orientation return columnsToName.value(section); return QVariant(); } + +int textureSizeInBytes(Qt3DRender::QAbstractTexture *texture) +{ + auto mipmapMultiplier = 1.0; + if (texture->generateMipMaps()) + // A mipmap chain uses 1/3 more space than the normal image + mipmapMultiplier = 4.0/3.0; + // texture can be of two types. QTextureLoader or QTexture2D + // We use QTextureLoader for dds files and QTexture2D for png/jpg files + auto textureLoader = qobject_cast(texture); + if (textureLoader) { + QFileInfo fInfo; + fInfo.setFile(textureLoader->source().toString()); + if (fInfo.exists()) + return static_cast(mipmapMultiplier*fInfo.size()); + } else { + // FIXME Check that all textures we upload coming from a glTF file have 4 channels + return static_cast(mipmapMultiplier * texture->width() * texture->height() * 4); + } + return std::numeric_limits::quiet_NaN(); +} diff --git a/tools/gltfEditor/textureinspector.h b/tools/gltfEditor/textureinspector.h index deea10d9e..11650f088 100644 --- a/tools/gltfEditor/textureinspector.h +++ b/tools/gltfEditor/textureinspector.h @@ -40,6 +40,8 @@ class AbstractAssetCollection; class TextureImagesModel; +int textureSizeInBytes(Qt3DRender::QAbstractTexture *texture); + class TextureInspector : public QObject { Q_OBJECT @@ -65,6 +67,7 @@ class TextureInspector : public QObject QString wrapZMode() const; QString minificationFilter() const; QString magnificationFilter() const; + int textureSize() const; Q_SIGNALS: void textureParamsChanged(); diff --git a/tools/gltfEditor/texturewidget.cpp b/tools/gltfEditor/texturewidget.cpp index e698273f6..3b949d975 100644 --- a/tools/gltfEditor/texturewidget.cpp +++ b/tools/gltfEditor/texturewidget.cpp @@ -40,6 +40,19 @@ #include #include +namespace { +QString totalSizeString(int sizeInBytes) +{ + auto size = sizeInBytes / 1024.0; + QString suffix(QStringLiteral(" KB")); + if (size > 1024.) { + size = size / 1024.; + suffix = QStringLiteral(" MB"); + } + return QString::number(size, 'f', 2) + suffix; +} +} + TextureWidget::TextureWidget(QWidget *parent) : QWidget(parent) , m_inspector(nullptr) @@ -48,6 +61,10 @@ TextureWidget::TextureWidget(QWidget *parent) { ui->setupUi(this); + auto scrollArea = new FixedWidthScrollArea(this); + layout()->addWidget(scrollArea); + scrollArea->setWidget(ui->rootWidget); + m_previewWidget->setAlignment(Qt::AlignHCenter); auto hBoxLayout = new QHBoxLayout(ui->texturePreviewGroupBox); hBoxLayout->addWidget(m_previewWidget); @@ -81,6 +98,7 @@ void TextureWidget::updateData() { ui->nameValue->setText(m_inspector->assetName()); ui->formatValue->setText(m_inspector->format()); + ui->textureSize->setText(::totalSizeString(m_inspector->textureSize())); ui->targetValue->setText(m_inspector->target()); ui->widthValue->setText(QString::number(m_inspector->width())); ui->heightValue->setText(QString::number(m_inspector->height())); diff --git a/tools/gltfEditor/texturewidget.ui b/tools/gltfEditor/texturewidget.ui index 9b9c05752..4f16f2b9b 100644 --- a/tools/gltfEditor/texturewidget.ui +++ b/tools/gltfEditor/texturewidget.ui @@ -6,8 +6,8 @@ 0 0 - 408 - 567 + 250 + 677 @@ -25,368 +25,324 @@ Form - + - 5 + 0 - 5 + 0 - 5 + 0 - 5 + 0 - - - - 0 - 0 - - - - - 200 - 200 - - - - QFrame::NoFrame - - - - - 0 - 0 - 391 - 529 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Preview - - - - - - - - 0 - 0 - - - - Texture Details - - - - - - Name: - - - - - - - Target - - - - - - - Texture2D - - - - - - - - 0 - 0 - - - - Qt::LeftToRight - - - Format: - - - 2 - - - - - - - RGBA - - - - - - - true - - - - - - - - - - - 0 - 0 - - - - - 210 - 110 - - - - Dimensions - - - - - - Width: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - 0 - - - - - - - Samples: - - - - - - - 0 - - - - - - - Height: - - - - - - - 0 - - - - - - - Layers: - - - - - - - 0 - - - - - - - Depth: - - - - - - - 0 - - - - - - - - - - - 0 - 0 - - - - Filtering - - - - - - Minification: - - - - - - - Linear - - - - - - - Magnification: - - - - - - - Nearest - - - - - - - - - - - 0 - 0 - - - - Wrapping - - - - - - x: - - - - - - - ClampToEdge - - - - - - - y: - - - - - - - ClampToEdge - - - - - - - z: - - - - - - - ClampToEdge - - - - - - - - - - - 0 - 0 - - - - Images - - - - - - - Qt::Vertical - - - - 20 - 5 - - - - - - + + + + + + Preview + + + + + + + + 0 + 0 + + + + Texture Details + + + + + + Texture2D + + + + + + + + 0 + 0 + + + + Qt::LeftToRight + + + Format: + + + 2 + + + + + + + Target + + + + + + + RGBA + + + + + + + true + + + + + + + Name: + + + + + + + TextLabel + + + + + + + Size: + + + + + + + + + + + 0 + 0 + + + + + 210 + 110 + + + + Dimensions + + + + + + Width: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + 0 + + + + + + + Samples: + + + + + + + 0 + + + + + + + Height: + + + + + + + 0 + + + + + + + Layers: + + + + + + + 0 + + + + + + + Depth: + + + + + + + 0 + + + + + + + + + + + 0 + 0 + + + + Filtering + + + + + + Minification: + + + + + + + Linear + + + + + + + Magnification: + + + + + + + Nearest + + + + + + + + + + + 0 + 0 + + + + Wrapping + + + + + + x: + + + + + + + ClampToEdge + + + + + + + y: + + + + + + + ClampToEdge + + + + + + + z: + + + + + + + ClampToEdge + + + + + + + + + + + 0 + 0 + + + + Images + + + + - - - FixedWidthScrollArea - QScrollArea -
- 1 -
-