1// Copyright (C) 2008-2012 NVIDIA Corporation.
2// Copyright (C) 2019 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4
5#ifndef QSSG_RENDER_BUFFER_MANAGER_H
6#define QSSG_RENDER_BUFFER_MANAGER_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtQuick3DRuntimeRender/private/qtquick3druntimerenderglobal_p.h>
20#include <QtQuick3DRuntimeRender/private/qssgrenderimagetexture_p.h>
21#include <QtQuick3DRuntimeRender/private/qssgrendermesh_p.h>
22#include <QtQuick3DRuntimeRender/private/qssgrendererutil_p.h>
23#include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h>
24#include <QtQuick3DUtils/private/qssgmesh_p.h>
25
26#include <QtQuick3DUtils/private/qquick3dprofiler_p.h>
27
28#include <QtCore/QMutex>
29#include <QtCore/qhash.h>
30#include <QtCore/qsize.h>
31
32QT_BEGIN_NAMESPACE
33
34struct QSSGRenderMesh;
35struct QSSGLoadedTexture;
36class QSSGRhiContext;
37class QSSGMeshBVH;
38class QSGTexture;
39class QSSGRenderGeometry;
40class QSSGRenderTextureData;
41struct QSSGRenderModel;
42struct QSSGRenderImage;
43struct QSSGRenderResourceLoader;
44struct QSSGRenderLayer;
45struct QSSGRenderSkin;
46
47// There is one QSSGBufferManager per QSSGRenderContextInterface, and so per
48// QQuickWindow, and by extension, per scenegraph render thread. This is
49// essential here because graphics resources (vertex/index buffers, textures)
50// are always specific to one render thread, they cannot be used and shared
51// between different threads (and so windows). This is ensured by design, by
52// having a dedicated BufferManager for each render thread (window).
53
54class QSSGRenderContextInterface;
55class QQuick3DRenderExtension;
56
57struct QSSGMeshProcessingOptions
58{
59 bool wantsLightmapUVs = false;
60 uint lightmapBaseResolution = 0;
61 QString meshFileOverride;
62
63 inline bool isCompatible(const QSSGMeshProcessingOptions &other) const
64 {
65 // a mesh postprocessing request with no-lightmap-UVs is compatible
66 // with a previously processed mesh regardless of having generated
67 // lightmap UVs or not
68 if (!wantsLightmapUVs)
69 return true;
70
71 // if lightmap UVs are wanted, the request can only use other's data
72 // if that generated lightmap UVs with the matching resolution
73 return other.wantsLightmapUVs && lightmapBaseResolution == other.lightmapBaseResolution;
74
75 // meshFileOverride plays no role here
76 }
77};
78
79class Q_QUICK3DRUNTIMERENDER_EXPORT QSSGBufferManager
80{
81 Q_DISABLE_COPY(QSSGBufferManager)
82public:
83 enum MipMode : quint8 {
84 MipModeFollowRenderImage,
85 MipModeEnable,
86 MipModeDisable,
87 MipModeBsdf
88 };
89
90 enum LoadRenderImageFlag {
91 LoadWithFlippedY = 0x01
92 };
93 Q_DECLARE_FLAGS(LoadRenderImageFlags, LoadRenderImageFlag)
94
95 struct ImageCacheKey {
96 QSSGRenderPath path;
97 int mipMode;
98 int type;
99 };
100
101 struct CustomImageCacheKey {
102 QSSGRenderTextureData *data;
103 QSize pixelSize;
104 MipMode mipMode;
105 };
106
107 struct ImageData {
108 QSSGRenderImageTexture renderImageTexture;
109 QHash<QSSGRenderLayer*, uint32_t> usageCounts;
110 uint32_t version = 0;
111 };
112
113 struct MeshData {
114 QSSGRenderMesh *mesh = nullptr;
115 QHash<QSSGRenderLayer*, uint32_t> usageCounts;
116 uint32_t generationId = 0;
117 QSSGMeshProcessingOptions options;
118 };
119
120 struct MemoryStats {
121 quint64 meshDataSize = 0;
122 quint64 imageDataSize = 0;
123 };
124
125 QSSGBufferManager();
126 ~QSSGBufferManager();
127
128 void setRenderContextInterface(QSSGRenderContextInterface *ctx);
129
130 void releaseCachedResources();
131 // called on the destuction of a layer to release its referenced resources
132 void releaseResourcesForLayer(QSSGRenderLayer *layer);
133
134 QSSGRenderImageTexture loadRenderImage(const QSSGRenderImage *image,
135 MipMode inMipMode = MipModeFollowRenderImage,
136 LoadRenderImageFlags flags = LoadWithFlippedY);
137 QSSGRenderImageTexture loadLightmap(const QSSGRenderModel &model);
138 QSSGRenderImageTexture loadSkinmap(QSSGRenderTextureData *skin);
139
140 QSSGRenderMesh *getMeshForPicking(const QSSGRenderModel &model) const;
141 QSSGBounds3 getModelBounds(const QSSGRenderModel *model) const;
142
143 QSSGRenderMesh *loadMesh(const QSSGRenderModel *model);
144
145 // Called at the end of the frame to release unreferenced geometry and textures
146 void cleanupUnreferencedBuffers(quint32 frameId, QSSGRenderLayer *layer);
147 void resetUsageCounters(quint32 frameId, QSSGRenderLayer *layer);
148
149 void releaseGeometry(QSSGRenderGeometry *geometry);
150 void releaseTextureData(const QSSGRenderTextureData *data);
151 void releaseTextureData(const CustomImageCacheKey &key);
152 void releaseExtensionResult(const QSSGRenderExtension &rext);
153
154 void commitBufferResourceUpdates();
155
156 void processResourceLoader(const QSSGRenderResourceLoader *loader);
157
158 static std::unique_ptr<QSSGMeshBVH> loadMeshBVH(const QSSGRenderPath &inSourcePath);
159 static std::unique_ptr<QSSGMeshBVH> loadMeshBVH(QSSGRenderGeometry *geometry);
160
161 static QSSGMesh::Mesh loadMeshData(const QSSGRenderPath &inSourcePath);
162 QSSGMesh::Mesh loadMeshData(const QSSGRenderGeometry *geometry);
163
164 void registerExtensionResult(const QSSGRenderExtension &extensions, QRhiTexture *texture);
165
166 static QRhiTexture::Format toRhiFormat(const QSSGRenderTextureFormat format);
167
168 static void registerMeshData(const QString &assetId, const QVector<QSSGMesh::Mesh> &meshData);
169 static void unregisterMeshData(const QString &assetId);
170 static QString runtimeMeshSourceName(const QString &assetId, qsizetype meshId);
171 static QString primitivePath(const QString &primitive);
172
173 QMutex *meshUpdateMutex();
174
175 void increaseMemoryStat(QRhiTexture *texture);
176 void decreaseMemoryStat(QRhiTexture *texture);
177 void increaseMemoryStat(QSSGRenderMesh *mesh);
178 void decreaseMemoryStat(QSSGRenderMesh *mesh);
179
180 // Views for testing
181 const QHash<ImageCacheKey, ImageData> &getImageMap() const { return imageMap; }
182 const QHash<CustomImageCacheKey, ImageData> &getCustomTextureMap() const { return customTextureMap; }
183 const QHash<QSGTexture *, ImageData> &getSGImageMap() const { return qsgImageMap; }
184 const QHash<QSSGRenderPath, MeshData> &getMeshMap() const { return meshMap; }
185 const QHash<QSSGRenderGeometry *, MeshData> &getCustomMeshMap() const { return customMeshMap; }
186
187private:
188 void clear();
189 QRhiResourceUpdateBatch *meshBufferUpdateBatch();
190
191 static QSSGMesh::Mesh loadPrimitive(const QString &inRelativePath);
192 enum CreateRhiTextureFlag {
193 ScanForTransparency = 0x01,
194 CubeMap = 0x02,
195 Texture3D = 0x04
196 };
197 Q_DECLARE_FLAGS(CreateRhiTextureFlags, CreateRhiTextureFlag)
198 bool setRhiTexture(QSSGRenderImageTexture &texture,
199 const QSSGLoadedTexture *inTexture,
200 MipMode inMipMode,
201 CreateRhiTextureFlags inFlags,
202 const QString &debugObjectName,
203 bool *wasTextureCreated = nullptr);
204
205 QSSGRenderMesh *loadRenderMesh(const QSSGRenderPath &inSourcePath, QSSGMeshProcessingOptions options);
206 QSSGRenderMesh *loadRenderMesh(QSSGRenderGeometry *geometry, QSSGMeshProcessingOptions options);
207
208 QSSGRenderMesh *createRenderMesh(const QSSGMesh::Mesh &mesh, const QString &debugObjectName = {});
209 QSSGRenderImageTexture loadTextureData(QSSGRenderTextureData *data, MipMode inMipMode);
210 bool createEnvironmentMap(const QSSGLoadedTexture *inImage, QSSGRenderImageTexture *outTexture, const QString &debugObjectName);
211
212 void releaseMesh(const QSSGRenderPath &inSourcePath);
213 void releaseImage(const ImageCacheKey &key);
214
215 QSSGRenderContextInterface *m_contextInterface = nullptr; // ContextInterfaces owns BufferManager
216
217 // These store the actual buffer handles
218 QHash<ImageCacheKey, ImageData> imageMap; // Textures (specificed by path)
219 QHash<CustomImageCacheKey, ImageData> customTextureMap; // Textures (QQuick3DTextureData)
220 QHash<QSGTexture *, ImageData> qsgImageMap; // Textures (from Qt Quick)
221 QHash<const QSSGRenderExtension *, ImageData> renderExtensionTexture; // Textures (from QQuick3DRenderExtension)
222 QHash<QSSGRenderPath, MeshData> meshMap; // Meshes (specififed by path)
223 QHash<QSSGRenderGeometry *, MeshData> customMeshMap; // Meshes (QQuick3DGeometry)
224
225 QRhiResourceUpdateBatch *meshBufferUpdates = nullptr;
226 QMutex meshBufferMutex;
227
228 quint32 frameCleanupIndex = 0;
229 quint32 frameResetIndex = 0;
230 QSSGRenderLayer *currentLayer = nullptr;
231 MemoryStats stats;
232};
233
234Q_DECLARE_OPERATORS_FOR_FLAGS(QSSGBufferManager::LoadRenderImageFlags)
235
236inline size_t qHash(const QSSGBufferManager::ImageCacheKey &k, size_t seed) Q_DECL_NOTHROW
237{
238 return qHash(path: k.path, seed) ^ k.mipMode ^ k.type;
239}
240
241inline bool operator==(const QSSGBufferManager::ImageCacheKey &a, const QSSGBufferManager::ImageCacheKey &b) Q_DECL_NOTHROW
242{
243 return a.path == b.path && a.mipMode == b.mipMode && a.type == b.type;
244}
245
246size_t qHash(const QSSGBufferManager::CustomImageCacheKey &k, size_t seed) noexcept;
247
248inline bool operator==(const QSSGBufferManager::CustomImageCacheKey &a, const QSSGBufferManager::CustomImageCacheKey &b) Q_DECL_NOTHROW
249{
250 return a.data == b.data && a.pixelSize == b.pixelSize && a.mipMode == b.mipMode;
251}
252
253QT_END_NAMESPACE
254
255#endif
256

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtquick3d/src/runtimerender/resourcemanager/qssgrenderbuffermanager_p.h