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

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