| 1 | // Copyright (C) 2008-2012 NVIDIA Corporation. |
| 2 | // Copyright (C) 2022 The Qt Company Ltd. |
| 3 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
| 4 | |
| 5 | #ifndef QSSG_LAYER_RENDER_DATA_H |
| 6 | #define QSSG_LAYER_RENDER_DATA_H |
| 7 | |
| 8 | |
| 9 | // |
| 10 | // W A R N I N G |
| 11 | // ------------- |
| 12 | // |
| 13 | // This file is not part of the Qt API. It exists purely as an |
| 14 | // implementation detail. This header file may change from version to |
| 15 | // version without notice, or even be removed. |
| 16 | // |
| 17 | // We mean it. |
| 18 | // |
| 19 | |
| 20 | #include <QtQuick3DRuntimeRender/private/qssgrenderitem2d_p.h> |
| 21 | #include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h> |
| 22 | #include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h> |
| 23 | #include <QtQuick3DRuntimeRender/private/qssgrenderableobjects_p.h> |
| 24 | #include <QtQuick3DRuntimeRender/private/qssgrendershadowmap_p.h> |
| 25 | #include <QtQuick3DRuntimeRender/private/qssgrendereffect_p.h> |
| 26 | #include <QtQuick3DRuntimeRender/private/qssgrenderresourceloader_p.h> |
| 27 | #include <QtQuick3DRuntimeRender/private/qssgrenderreflectionmap_p.h> |
| 28 | #include <QtQuick3DRuntimeRender/private/qssgrendercamera_p.h> |
| 29 | #include <QtQuick3DRuntimeRender/private/qssgrhicontext_p.h> |
| 30 | #include <QtQuick3DRuntimeRender/private/qssgperframeallocator_p.h> |
| 31 | #include <QtQuick3DRuntimeRender/private/qssgshadermapkey_p.h> |
| 32 | #include <QtQuick3DRuntimeRender/private/qssglightmapper_p.h> |
| 33 | #include <ssg/qssgrenderextensions.h> |
| 34 | |
| 35 | #include <QtQuick3DUtils/private/qssgrenderbasetypes_p.h> |
| 36 | |
| 37 | #include <optional> |
| 38 | #include <unordered_map> |
| 39 | |
| 40 | #include "qssgrenderpass_p.h" |
| 41 | |
| 42 | #define QSSG_RENDER_MINIMUM_RENDER_OPACITY .01f |
| 43 | |
| 44 | QT_BEGIN_NAMESPACE |
| 45 | |
| 46 | struct QSSGRenderableObject; |
| 47 | |
| 48 | enum class QSSGLayerRenderPreparationResultFlag |
| 49 | { |
| 50 | // Was the data in this layer dirty (meaning re-render to texture, possibly) |
| 51 | WasLayerDataDirty = 1 << 0, |
| 52 | |
| 53 | // Was the data in this layer dirty *or* this layer *or* any effect dirty. |
| 54 | WasDirty = 1 << 1, |
| 55 | |
| 56 | RequiresDepthTexture = 1 << 2, |
| 57 | |
| 58 | // SSAO should be done in a separate pass |
| 59 | // Note that having an AO pass necessitates a DepthTexture so this flag should |
| 60 | // never be set without the RequiresDepthTexture flag as well. |
| 61 | RequiresSsaoPass = 1 << 3, |
| 62 | |
| 63 | // if some light cause shadow |
| 64 | // we need a separate per light shadow map pass |
| 65 | RequiresShadowMapPass = 1 << 4, |
| 66 | |
| 67 | RequiresScreenTexture = 1 << 5, |
| 68 | |
| 69 | // set together with RequiresScreenTexture when SCREEN_MIP_TEXTURE is used |
| 70 | RequiresMipmapsForScreenTexture = 1 << 6 |
| 71 | }; |
| 72 | |
| 73 | struct QSSGLayerRenderPreparationResultFlags : public QFlags<QSSGLayerRenderPreparationResultFlag> |
| 74 | { |
| 75 | bool wasLayerDataDirty() const |
| 76 | { |
| 77 | return this->operator&(other: QSSGLayerRenderPreparationResultFlag::WasLayerDataDirty); |
| 78 | } |
| 79 | void setLayerDataDirty(bool inValue) |
| 80 | { |
| 81 | setFlag(flag: QSSGLayerRenderPreparationResultFlag::WasLayerDataDirty, on: inValue); |
| 82 | } |
| 83 | |
| 84 | bool wasDirty() const { return this->operator&(other: QSSGLayerRenderPreparationResultFlag::WasDirty); } |
| 85 | void setWasDirty(bool inValue) { setFlag(flag: QSSGLayerRenderPreparationResultFlag::WasDirty, on: inValue); } |
| 86 | |
| 87 | bool requiresDepthTexture() const |
| 88 | { |
| 89 | return this->operator&(other: QSSGLayerRenderPreparationResultFlag::RequiresDepthTexture); |
| 90 | } |
| 91 | void setRequiresDepthTexture(bool inValue) |
| 92 | { |
| 93 | setFlag(flag: QSSGLayerRenderPreparationResultFlag::RequiresDepthTexture, on: inValue); |
| 94 | } |
| 95 | |
| 96 | bool requiresSsaoPass() const { return this->operator&(other: QSSGLayerRenderPreparationResultFlag::RequiresSsaoPass); } |
| 97 | void setRequiresSsaoPass(bool inValue) |
| 98 | { |
| 99 | setFlag(flag: QSSGLayerRenderPreparationResultFlag::RequiresSsaoPass, on: inValue); |
| 100 | } |
| 101 | |
| 102 | bool requiresShadowMapPass() const |
| 103 | { |
| 104 | return this->operator&(other: QSSGLayerRenderPreparationResultFlag::RequiresShadowMapPass); |
| 105 | } |
| 106 | void setRequiresShadowMapPass(bool inValue) |
| 107 | { |
| 108 | setFlag(flag: QSSGLayerRenderPreparationResultFlag::RequiresShadowMapPass, on: inValue); |
| 109 | } |
| 110 | |
| 111 | bool requiresScreenTexture() const |
| 112 | { |
| 113 | return this->operator&(other: QSSGLayerRenderPreparationResultFlag::RequiresScreenTexture); |
| 114 | } |
| 115 | void setRequiresScreenTexture(bool inValue) |
| 116 | { |
| 117 | setFlag(flag: QSSGLayerRenderPreparationResultFlag::RequiresScreenTexture, on: inValue); |
| 118 | } |
| 119 | |
| 120 | bool requiresMipmapsForScreenTexture() const |
| 121 | { |
| 122 | return this->operator&(other: QSSGLayerRenderPreparationResultFlag::RequiresMipmapsForScreenTexture); |
| 123 | } |
| 124 | void setRequiresMipmapsForScreenTexture(bool inValue) |
| 125 | { |
| 126 | setFlag(flag: QSSGLayerRenderPreparationResultFlag::RequiresMipmapsForScreenTexture, on: inValue); |
| 127 | } |
| 128 | }; |
| 129 | |
| 130 | struct QSSGLayerRenderPreparationResult |
| 131 | { |
| 132 | QSSGLayerRenderPreparationResultFlags flags; |
| 133 | QRectF viewport; |
| 134 | QSSGRenderLayer *layer = nullptr; |
| 135 | |
| 136 | QSSGLayerRenderPreparationResult() = default; |
| 137 | QSSGLayerRenderPreparationResult(const QRectF &inViewport, QSSGRenderLayer &inLayer); |
| 138 | |
| 139 | bool isNull() const { return !layer; } |
| 140 | bool isLayerVisible() const; |
| 141 | QSize textureDimensions() const; |
| 142 | QSSGCameraGlobalCalculationResult setupCameraForRender(QSSGRenderCamera &inCamera, float dpr = 1.0f); |
| 143 | }; |
| 144 | |
| 145 | struct QSSGDefaultMaterialPreparationResult |
| 146 | { |
| 147 | QSSGRenderableImage *firstImage; |
| 148 | float opacity; |
| 149 | QSSGRenderableObjectFlags renderableFlags; |
| 150 | QSSGShaderDefaultMaterialKey materialKey; |
| 151 | bool dirty; |
| 152 | |
| 153 | explicit QSSGDefaultMaterialPreparationResult(QSSGShaderDefaultMaterialKey inMaterialKey); |
| 154 | }; |
| 155 | |
| 156 | struct QSSGBakedLightingModel |
| 157 | { |
| 158 | QSSGBakedLightingModel(const QSSGRenderModel *model, const QVector<QSSGRenderableObjectHandle> &renderables) |
| 159 | : model(model), |
| 160 | renderables(renderables) |
| 161 | { } |
| 162 | |
| 163 | const QSSGRenderModel *model; |
| 164 | QVector<QSSGRenderableObjectHandle> renderables; |
| 165 | }; |
| 166 | |
| 167 | class Q_QUICK3DRUNTIMERENDER_EXPORT QSSGLayerRenderData |
| 168 | { |
| 169 | public: |
| 170 | enum Enum { |
| 171 | MAX_AA_LEVELS = 8, |
| 172 | MAX_TEMPORAL_AA_LEVELS = 2, |
| 173 | }; |
| 174 | |
| 175 | using RenderableFilter = std::function<bool(QSSGModelContext *)>; |
| 176 | |
| 177 | QSSGLayerRenderData(QSSGRenderLayer &inLayer, QSSGRenderer &inRenderer); |
| 178 | ~QSSGLayerRenderData(); |
| 179 | |
| 180 | typedef QVector<QSSGModelContext *> TModelContextPtrList; |
| 181 | using RenderableNodeEntries = QVector<QSSGRenderableNodeEntry>; |
| 182 | using RenderableItem2DEntries = QVector<QSSGRenderItem2D *>; |
| 183 | |
| 184 | QSSGShaderDefaultMaterialKey generateLightingKey(QSSGRenderDefaultMaterial::MaterialLighting inLightingType, |
| 185 | const QSSGShaderLightListView &lights, bool receivesShadows = true); |
| 186 | |
| 187 | void prepareImageForRender(QSSGRenderImage &inImage, |
| 188 | QSSGRenderableImage::Type inMapType, |
| 189 | QSSGRenderableImage *&ioFirstImage, |
| 190 | QSSGRenderableImage *&ioNextImage, |
| 191 | QSSGRenderableObjectFlags &ioFlags, |
| 192 | QSSGShaderDefaultMaterialKey &ioGeneratedShaderKey, |
| 193 | quint32 inImageIndex, QSSGRenderDefaultMaterial *inMaterial = nullptr); |
| 194 | |
| 195 | void setVertexInputPresence(const QSSGRenderableObjectFlags &renderableFlags, |
| 196 | QSSGShaderDefaultMaterialKey &key); |
| 197 | |
| 198 | static void prepareModelBoneTextures(const QSSGRenderContextInterface &contextInterface, |
| 199 | const RenderableNodeEntries &renderableModels); |
| 200 | |
| 201 | // Helper functions used during PrepareForRender and PrepareAndRender |
| 202 | // Updates lights with model receivesShadows. Do not pass globalLights. |
| 203 | bool prepareModelsForRender(QSSGRenderContextInterface &ctx, |
| 204 | const RenderableNodeEntries &renderableModels, |
| 205 | QSSGLayerRenderPreparationResultFlags &ioFlags, |
| 206 | const QSSGRenderCameraList &allCameras, |
| 207 | const QSSGRenderCameraDataList &allCameraData, |
| 208 | TModelContextPtrList &modelContexts, |
| 209 | QSSGRenderableObjectList &opaqueObjects, |
| 210 | QSSGRenderableObjectList &transparentObjects, |
| 211 | QSSGRenderableObjectList &screenTextureObjects, |
| 212 | float lodThreshold = 0.0f); |
| 213 | bool prepareParticlesForRender(const RenderableNodeEntries &renderableParticles, const QSSGRenderCameraData &cameraData); |
| 214 | bool prepareItem2DsForRender(const QSSGRenderContextInterface &ctxIfc, |
| 215 | const RenderableItem2DEntries &renderableItem2Ds); |
| 216 | |
| 217 | void prepareResourceLoaders(); |
| 218 | |
| 219 | void prepareForRender(); |
| 220 | // Helper function used during prepareForRender |
| 221 | void prepareReflectionProbesForRender(); |
| 222 | |
| 223 | static qsizetype frustumCulling(const QSSGClippingFrustum &clipFrustum, const QSSGRenderableObjectList &renderables, QSSGRenderableObjectList &visibleRenderables); |
| 224 | [[nodiscard]] static qsizetype frustumCullingInline(const QSSGClippingFrustum &clipFrustum, QSSGRenderableObjectList &renderables); |
| 225 | |
| 226 | |
| 227 | // Per-frame cache of renderable objects post-sort (for the MAIN rendering camera, i.e., don't use these lists for rendering from a different camera). |
| 228 | const QSSGRenderableObjectList &getSortedOpaqueRenderableObjects(const QSSGRenderCamera &camera, size_t index = 0); |
| 229 | // If layer depth test is false, this may also contain opaque objects. |
| 230 | const QSSGRenderableObjectList &getSortedTransparentRenderableObjects(const QSSGRenderCamera &camera, size_t index = 0); |
| 231 | const QSSGRenderableObjectList &getSortedScreenTextureRenderableObjects(const QSSGRenderCamera &camera, size_t index = 0); |
| 232 | const QVector<QSSGBakedLightingModel> &getSortedBakedLightingModels(); |
| 233 | const RenderableItem2DEntries &getRenderableItem2Ds(); |
| 234 | const QSSGRenderableObjectList &getSortedRenderedDepthWriteObjects(const QSSGRenderCamera &camera, size_t index = 0); |
| 235 | const QSSGRenderableObjectList &getSortedrenderedOpaqueDepthPrepassObjects(const QSSGRenderCamera &camera, size_t index = 0); |
| 236 | |
| 237 | void resetForFrame(); |
| 238 | |
| 239 | void maybeBakeLightmap(); |
| 240 | |
| 241 | QSSGFrameData &getFrameData(); |
| 242 | |
| 243 | ShadowMapPass shadowMapPass; |
| 244 | ReflectionMapPass reflectionMapPass; |
| 245 | ZPrePassPass zPrePassPass; |
| 246 | SSAOMapPass ssaoMapPass; |
| 247 | DepthMapPass depthMapPass; |
| 248 | ScreenMapPass screenMapPass; |
| 249 | ScreenReflectionPass reflectionPass; |
| 250 | Item2DPass item2DPass; |
| 251 | SkyboxPass skyboxPass; |
| 252 | SkyboxCubeMapPass skyboxCubeMapPass; |
| 253 | static constexpr size_t USERPASSES = 2; // See QSSGRenderLayer::RenderExtensionMode::Count |
| 254 | UserPass userPasses[USERPASSES]; |
| 255 | OpaquePass opaquePass; |
| 256 | TransparentPass transparentPass; |
| 257 | InfiniteGridPass infiniteGridPass; |
| 258 | DebugDrawPass debugDrawPass; |
| 259 | |
| 260 | // Built-in passes |
| 261 | QVarLengthArray<QSSGRenderPass *, 16> activePasses; |
| 262 | |
| 263 | QSSGRenderLayer &layer; |
| 264 | QSSGRenderer *renderer = nullptr; |
| 265 | // List of nodes we can render, not all may be active. Found by doing a depth-first |
| 266 | // search through m_FirstChild if length is zero. |
| 267 | |
| 268 | // renderableNodes have all lights, but properties configured for specific node |
| 269 | RenderableNodeEntries renderableModels; |
| 270 | RenderableNodeEntries renderableParticles; |
| 271 | QVector<QSSGRenderItem2D *> renderableItem2Ds; |
| 272 | QVector<QSSGRenderCamera *> cameras; |
| 273 | QVector<QSSGRenderLight *> lights; |
| 274 | QVector<QSSGRenderReflectionProbe *> reflectionProbes; |
| 275 | |
| 276 | // Results of prepare for render. |
| 277 | QSSGRenderCameraList renderedCameras; // multiple items with multiview, one otherwise (or zero if no cameras at all) |
| 278 | QSSGShaderLightList globalLights; // All non-scoped lights |
| 279 | |
| 280 | QVector<QSSGBakedLightingModel> bakedLightingModels; |
| 281 | // Sorted lists of the rendered objects. There may be other transforms applied so |
| 282 | // it is simplest to duplicate the lists. |
| 283 | QVector<QSSGBakedLightingModel> renderedBakedLightingModels; |
| 284 | RenderableItem2DEntries renderedItem2Ds; |
| 285 | |
| 286 | QSSGLayerRenderPreparationResult layerPrepResult; |
| 287 | std::optional<QSSGRenderCameraDataList> renderedCameraData; |
| 288 | |
| 289 | TModelContextPtrList modelContexts; |
| 290 | |
| 291 | |
| 292 | bool tooManyLightsWarningShown = false; |
| 293 | bool tooManyShadowLightsWarningShown = false; |
| 294 | |
| 295 | QSSGLightmapper *m_lightmapper = nullptr; |
| 296 | |
| 297 | QSSGShaderFeatures getShaderFeatures() const { return features; } |
| 298 | QSSGRhiGraphicsPipelineState getPipelineState() const { return ps; } |
| 299 | |
| 300 | bool interactiveLightmapBakingRequested = false; |
| 301 | QSSGLightmapper::Callback lightmapBakingOutputCallback; |
| 302 | |
| 303 | [[nodiscard]] QSSGRenderGraphObject *getCamera(QSSGCameraId id) const; |
| 304 | [[nodiscard]] QSSGRenderCamera *activeCamera() const { return !renderedCameras.isEmpty() ? renderedCameras[0] : nullptr; } |
| 305 | |
| 306 | [[nodiscard]] QSSGRenderCameraData getCameraRenderData(const QSSGRenderCamera *camera); |
| 307 | [[nodiscard]] QSSGRenderCameraData getCameraRenderData(const QSSGRenderCamera *camera) const; |
| 308 | |
| 309 | void setLightmapTexture(const QSSGModelContext &modelContext, QRhiTexture *lightmapTexture); |
| 310 | [[nodiscard]] QRhiTexture *getLightmapTexture(const QSSGModelContext &modelContext) const; |
| 311 | |
| 312 | void setBonemapTexture(const QSSGModelContext &modelContext, QRhiTexture *bonemapTexture); |
| 313 | [[nodiscard]] QRhiTexture *getBonemapTexture(const QSSGModelContext &modelContext) const; |
| 314 | |
| 315 | [[nodiscard]] QSSGRenderContextInterface *contextInterface() const; |
| 316 | // Note: temp. API to report the state of the z-prepass step |
| 317 | [[nodiscard]] bool isZPrePassActive() const { return zPrePassActive; } |
| 318 | void setZPrePassPrepResult(bool res) { zPrePassActive = res; } |
| 319 | |
| 320 | // Exposed as const, as we often need to use this to look-up values from a specific key. |
| 321 | [[nodiscard]] const QSSGShaderDefaultMaterialKeyProperties &getDefaultMaterialPropertyTable() const |
| 322 | { |
| 323 | return defaultMaterialShaderKeyProperties; |
| 324 | } |
| 325 | |
| 326 | struct GlobalRenderProperties |
| 327 | { |
| 328 | bool isYUpInFramebuffer = true; |
| 329 | bool isYUpInNDC = true; |
| 330 | bool isClipDepthZeroToOne = true; |
| 331 | }; |
| 332 | |
| 333 | [[nodiscard]] static GlobalRenderProperties globalRenderProperties(const QSSGRenderContextInterface &ctx); |
| 334 | |
| 335 | // Temp. API. Ideally there shouldn't be a reason for anyone to hold onto these, |
| 336 | // but we follow the existing pattern for now. |
| 337 | const QSSGRenderShadowMapPtr &requestShadowMapManager(); |
| 338 | const QSSGRenderReflectionMapPtr &requestReflectionMapManager(); |
| 339 | const QSSGRenderShadowMapPtr &getShadowMapManager() const { return shadowMapManager; } |
| 340 | const QSSGRenderReflectionMapPtr &getReflectionMapManager() const { return reflectionMapManager; } |
| 341 | |
| 342 | static bool prepareInstancing(QSSGRhiContext *rhiCtx, |
| 343 | QSSGSubsetRenderable *renderable, |
| 344 | const QVector3D &cameraDirection, |
| 345 | const QVector3D &cameraPosition, |
| 346 | float minThreshold, |
| 347 | float maxThreshold); |
| 348 | |
| 349 | [[nodiscard]] QSSGRhiRenderableTexture *getRenderResult(QSSGFrameData::RenderResult id) { return &renderResults[size_t(id)]; } |
| 350 | [[nodiscard]] const QSSGRhiRenderableTexture *getRenderResult(QSSGFrameData::RenderResult id) const { return &renderResults[size_t(id)]; } |
| 351 | [[nodiscard]] static inline const std::unique_ptr<QSSGPerFrameAllocator> &perFrameAllocator(QSSGRenderContextInterface &ctx); |
| 352 | [[nodiscard]] static inline QSSGLayerRenderData *getCurrent(const QSSGRenderer &renderer) { return renderer.m_currentLayer; } |
| 353 | void saveRenderState(const QSSGRenderer &renderer); |
| 354 | void restoreRenderState(QSSGRenderer &renderer); |
| 355 | |
| 356 | static void setTonemapFeatures(QSSGShaderFeatures &features, QSSGRenderLayer::TonemapMode tonemapMode) |
| 357 | { |
| 358 | features.set(feature: QSSGShaderFeatures::Feature::LinearTonemapping, |
| 359 | val: tonemapMode == QSSGRenderLayer::TonemapMode::Linear); |
| 360 | features.set(feature: QSSGShaderFeatures::Feature::AcesTonemapping, |
| 361 | val: tonemapMode == QSSGRenderLayer::TonemapMode::Aces); |
| 362 | features.set(feature: QSSGShaderFeatures::Feature::HejlDawsonTonemapping, |
| 363 | val: tonemapMode == QSSGRenderLayer::TonemapMode::HejlDawson); |
| 364 | features.set(feature: QSSGShaderFeatures::Feature::FilmicTonemapping, |
| 365 | val: tonemapMode == QSSGRenderLayer::TonemapMode::Filmic); |
| 366 | features.set(feature: QSSGShaderFeatures::Feature::ForceIblExposure, |
| 367 | val: tonemapMode == QSSGRenderLayer::TonemapMode::Custom); |
| 368 | } |
| 369 | |
| 370 | QSSGPrepContextId getOrCreateExtensionContext(const QSSGRenderExtension &ext, |
| 371 | QSSGRenderCamera *camera = nullptr, |
| 372 | quint32 slot = 0); |
| 373 | |
| 374 | // Model API |
| 375 | QSSGRenderablesId createRenderables(QSSGPrepContextId prepId, const QList<QSSGNodeId> &nodes, QSSGRenderHelpers::CreateFlags createFlags); |
| 376 | void setGlobalTransform(QSSGRenderablesId renderablesId, const QSSGRenderModel &model, const QMatrix4x4 &mvp); |
| 377 | QMatrix4x4 getGlobalTransform(QSSGPrepContextId prepId, const QSSGRenderModel &model); |
| 378 | void setGlobalOpacity(QSSGRenderablesId renderablesId, const QSSGRenderModel &model, float opacity); |
| 379 | float getGlobalOpacity(QSSGPrepContextId prepId, const QSSGRenderModel &model); |
| 380 | [[nodiscard]] QMatrix4x4 getModelMvp(QSSGPrepContextId prepId, const QSSGRenderModel &model) const; |
| 381 | void setModelMaterials(QSSGRenderablesId renderablesId, const QSSGRenderModel &model, const QList<QSSGResourceId> &materials); |
| 382 | void setModelMaterials(const QSSGRenderablesId renderablesId, const QList<QSSGResourceId> &materials); |
| 383 | [[nodiscard]] QSSGPrepResultId prepareModelsForRender(QSSGRenderContextInterface &contextInterface, |
| 384 | QSSGPrepContextId prepId, |
| 385 | QSSGRenderablesId renderablesId, |
| 386 | float lodThreshold); |
| 387 | |
| 388 | |
| 389 | // |
| 390 | void prepareRenderables(QSSGRenderContextInterface &ctx, |
| 391 | QSSGPrepResultId prepId, |
| 392 | QRhiRenderPassDescriptor *renderPassDescriptor, |
| 393 | const QSSGRhiGraphicsPipelineState &ps, |
| 394 | QSSGRenderablesFilters filter); |
| 395 | void renderRenderables(QSSGRenderContextInterface &ctx, |
| 396 | QSSGPrepResultId prepId); |
| 397 | |
| 398 | private: |
| 399 | friend class QSSGRenderer; |
| 400 | friend class QSSGRendererPrivate; |
| 401 | friend class QSSGFrameData; |
| 402 | friend class QSSGModelHelpers; |
| 403 | friend class QSSGRenderHelpers; |
| 404 | |
| 405 | class ExtensionContext |
| 406 | { |
| 407 | public: |
| 408 | explicit ExtensionContext() = default; |
| 409 | explicit ExtensionContext(const QSSGRenderExtension &ownerExt, QSSGRenderCamera *cam, size_t idx, quint32 slot) |
| 410 | : owner(&ownerExt), camera(cam), ps{}, filter{0}, index(idx), slot(slot) |
| 411 | { } |
| 412 | const QSSGRenderExtension *owner = nullptr; |
| 413 | QSSGRenderCamera *camera = nullptr; |
| 414 | QSSGRhiGraphicsPipelineState ps[3] {}; |
| 415 | QSSGRenderablesFilters filter { 0 }; |
| 416 | size_t index = 0; // index into the model store |
| 417 | quint32 slot = 0; |
| 418 | }; |
| 419 | |
| 420 | std::vector<ExtensionContext> extContexts { ExtensionContext{ /* 0 - Always available */ } }; |
| 421 | std::vector<RenderableNodeEntries> renderableModelStore { RenderableNodeEntries{ /* 0 - Always available */ } }; |
| 422 | std::vector<TModelContextPtrList> modelContextStore { TModelContextPtrList{ /* 0 - Always available */ }}; |
| 423 | std::vector<QSSGRenderableObjectList> renderableObjectStore { QSSGRenderableObjectList{ /* 0 - Always available */ }}; |
| 424 | std::vector<QSSGRenderableObjectList> opaqueObjectStore { QSSGRenderableObjectList{ /* 0 - Always available */ }}; |
| 425 | std::vector<QSSGRenderableObjectList> transparentObjectStore { QSSGRenderableObjectList{ /* 0 - Always available */ }}; |
| 426 | std::vector<QSSGRenderableObjectList> screenTextureObjectStore { QSSGRenderableObjectList{ /* 0 - Always available */ }}; |
| 427 | |
| 428 | // Soreted cache (per camera and extension) |
| 429 | using PerCameraCache = std::unordered_map<const QSSGRenderCamera *, QSSGRenderableObjectList>; |
| 430 | std::vector<PerCameraCache> sortedOpaqueObjectCache { PerCameraCache{ /* 0 - Always available */ } }; |
| 431 | std::vector<PerCameraCache> sortedTransparentObjectCache { PerCameraCache{ /* 0 - Always available */ } }; |
| 432 | std::vector<PerCameraCache> sortedScreenTextureObjectCache { PerCameraCache{ /* 0 - Always available */ } }; |
| 433 | std::vector<PerCameraCache> sortedOpaqueDepthPrepassCache { PerCameraCache{ /* 0 - Always available */ } }; |
| 434 | std::vector<PerCameraCache> sortedDepthWriteCache { PerCameraCache{ /* 0 - Always available */ } }; |
| 435 | |
| 436 | [[nodiscard]] const QSSGRenderCameraDataList &getCachedCameraDatas(); |
| 437 | void ensureCachedCameraDatas(); |
| 438 | void updateSortedDepthObjectsListImp(const QSSGRenderCamera &camera, size_t index); |
| 439 | |
| 440 | |
| 441 | QSSGDefaultMaterialPreparationResult prepareDefaultMaterialForRender(QSSGRenderDefaultMaterial &inMaterial, |
| 442 | QSSGRenderableObjectFlags &inExistingFlags, |
| 443 | float inOpacity, |
| 444 | const QSSGShaderLightListView &lights, |
| 445 | QSSGLayerRenderPreparationResultFlags &ioFlags); |
| 446 | |
| 447 | QSSGDefaultMaterialPreparationResult prepareCustomMaterialForRender(QSSGRenderCustomMaterial &inMaterial, |
| 448 | QSSGRenderableObjectFlags &inExistingFlags, |
| 449 | float inOpacity, bool alreadyDirty, |
| 450 | const QSSGShaderLightListView &lights, |
| 451 | QSSGLayerRenderPreparationResultFlags &ioFlags); |
| 452 | |
| 453 | static void prepareModelMaterials(RenderableNodeEntries &renderableModels, bool cullUnrenderables); |
| 454 | static void prepareModelMaterials(const RenderableNodeEntries::ConstIterator &begin, |
| 455 | const RenderableNodeEntries::ConstIterator &end); |
| 456 | // Load meshes as needed |
| 457 | static void prepareModelMeshes(const QSSGRenderContextInterface &contextInterface, |
| 458 | RenderableNodeEntries &renderableModels, |
| 459 | bool globalPickingEnabled); |
| 460 | static void prepareModelMeshes(const QSSGRenderContextInterface &contextInterface, |
| 461 | const RenderableNodeEntries::ConstIterator begin, |
| 462 | const RenderableNodeEntries::ConstIterator end, |
| 463 | bool globalPickingEnabled); |
| 464 | |
| 465 | // Persistent data |
| 466 | QHash<QSSGShaderMapKey, QSSGRhiShaderPipelinePtr> shaderMap; |
| 467 | |
| 468 | // Cached buffer. |
| 469 | QByteArray generatedShaderString; |
| 470 | |
| 471 | // Saved render state (for sublayers) |
| 472 | struct SavedRenderState |
| 473 | { |
| 474 | QRect viewport; |
| 475 | QRect scissorRect; |
| 476 | float dpr = 1.0; |
| 477 | }; |
| 478 | |
| 479 | std::optional<SavedRenderState> savedRenderState; |
| 480 | |
| 481 | // Note: Re-used to avoid expensive initialization. |
| 482 | // - Should be revisit, as we can do better. |
| 483 | QSSGShaderDefaultMaterialKeyProperties defaultMaterialShaderKeyProperties; |
| 484 | QSSGFrameData frameData; |
| 485 | QSSGRhiGraphicsPipelineState ps; // Base pipleline state |
| 486 | QSSGShaderFeatures features; // Base feature set |
| 487 | bool particlesEnabled = true; |
| 488 | bool hasDepthWriteObjects = false; |
| 489 | bool zPrePassActive = false; |
| 490 | enum class DepthPrepassObject : quint8 |
| 491 | { |
| 492 | None = 0x0, |
| 493 | ScreenTexture = 0x1, |
| 494 | Transparent = 0x2, |
| 495 | Opaque = 0x4 |
| 496 | }; |
| 497 | using DepthPrepassObjectStateT = std::underlying_type_t<DepthPrepassObject>; |
| 498 | DepthPrepassObjectStateT depthPrepassObjectsState { DepthPrepassObjectStateT(DepthPrepassObject::None) }; |
| 499 | QSSGRenderShadowMapPtr shadowMapManager; |
| 500 | QSSGRenderReflectionMapPtr reflectionMapManager; |
| 501 | QHash<const QSSGModelContext *, QRhiTexture *> lightmapTextures; |
| 502 | QHash<const QSSGModelContext *, QRhiTexture *> bonemapTextures; |
| 503 | QSSGRhiRenderableTexture renderResults[3] {}; |
| 504 | }; |
| 505 | |
| 506 | QT_END_NAMESPACE |
| 507 | |
| 508 | #endif // QSSG_LAYER_RENDER_DATA_H |
| 509 | |
| 510 | |