| 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 | #include "qssgrendererimplshaders_p.h" |
| 6 | |
| 7 | #include <QtQuick3DRuntimeRender/private/qssgrenderer_p.h> |
| 8 | #include <QtQuick3DRuntimeRender/private/qssgrenderlight_p.h> |
| 9 | #include "../qssgrendercontextcore.h" |
| 10 | #include <QtQuick3DRuntimeRender/private/qssgrendershadercache_p.h> |
| 11 | #include <QtQuick3DRuntimeRender/private/qssgrendershaderlibrarymanager_p.h> |
| 12 | #include <QtQuick3DRuntimeRender/private/qssgrendershadercodegenerator_p.h> |
| 13 | #include <QtQuick3DRuntimeRender/private/qssgrenderdefaultmaterialshadergenerator_p.h> |
| 14 | #include <QtQuick3DRuntimeRender/private/qssgvertexpipelineimpl_p.h> |
| 15 | |
| 16 | // this file contains the getXxxxShader implementations suitable for the QRhi-based rendering path |
| 17 | |
| 18 | QT_BEGIN_NAMESPACE |
| 19 | |
| 20 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getBuiltinRhiShader(const QByteArray &name, |
| 21 | BuiltinShader &storage, |
| 22 | int viewCount) |
| 23 | { |
| 24 | if (storage.shaderPipeline && storage.viewCount != viewCount) |
| 25 | storage = {}; |
| 26 | |
| 27 | if (!storage.shaderPipeline) { |
| 28 | // loadBuiltin must always return a valid QSSGRhiShaderPipeline. |
| 29 | // There will just be no stages if loading fails. |
| 30 | storage.shaderPipeline = m_shaderCache.loadBuiltinUncached(inKey: name, viewCount); |
| 31 | storage.viewCount = viewCount; |
| 32 | } |
| 33 | |
| 34 | return storage.shaderPipeline; |
| 35 | } |
| 36 | |
| 37 | void QSSGBuiltInRhiShaderCache::releaseCachedResources() |
| 38 | { |
| 39 | m_cache = {}; |
| 40 | } |
| 41 | |
| 42 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiCubemapShadowBlurXShader() |
| 43 | { |
| 44 | return getBuiltinRhiShader(QByteArrayLiteral("cubeshadowblurx" ), storage&: m_cache.cubemapShadowBlurXRhiShader); |
| 45 | } |
| 46 | |
| 47 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiCubemapShadowBlurYShader() |
| 48 | { |
| 49 | return getBuiltinRhiShader(QByteArrayLiteral("cubeshadowblury" ), storage&: m_cache.cubemapShadowBlurYRhiShader); |
| 50 | } |
| 51 | |
| 52 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiGridShader(int viewCount) |
| 53 | { |
| 54 | return getBuiltinRhiShader(QByteArrayLiteral("grid" ), storage&: m_cache.gridShader, viewCount); |
| 55 | } |
| 56 | |
| 57 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiOrthographicShadowBlurXShader() |
| 58 | { |
| 59 | return getBuiltinRhiShader(QByteArrayLiteral("orthoshadowblurx" ), storage&: m_cache.orthographicShadowBlurXRhiShader); |
| 60 | } |
| 61 | |
| 62 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiOrthographicShadowBlurYShader() |
| 63 | { |
| 64 | return getBuiltinRhiShader(QByteArrayLiteral("orthoshadowblury" ), storage&: m_cache.orthographicShadowBlurYRhiShader); |
| 65 | } |
| 66 | |
| 67 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiSsaoShader(int viewCount) |
| 68 | { |
| 69 | return getBuiltinRhiShader(QByteArrayLiteral("ssao" ), storage&: m_cache.ssaoRhiShader, viewCount); |
| 70 | } |
| 71 | |
| 72 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiSkyBoxCubeShader(int viewCount) |
| 73 | { |
| 74 | return getBuiltinRhiShader(QByteArrayLiteral("skyboxcube" ), storage&: m_cache.skyBoxCubeRhiShader, viewCount); |
| 75 | } |
| 76 | |
| 77 | static inline constexpr size_t getSkyboxIndex(QSSGRenderLayer::TonemapMode tonemapMode, bool isRGBE) |
| 78 | { |
| 79 | switch (tonemapMode) { |
| 80 | case QSSGRenderLayer::TonemapMode::None: |
| 81 | return 0 + (size_t(isRGBE) * QSSGRenderLayer::TonemapModeCount); |
| 82 | case QSSGRenderLayer::TonemapMode::Linear: |
| 83 | return 1 + (size_t(isRGBE) * QSSGRenderLayer::TonemapModeCount); |
| 84 | case QSSGRenderLayer::TonemapMode::Aces: |
| 85 | return 2 + (size_t(isRGBE) * QSSGRenderLayer::TonemapModeCount); |
| 86 | case QSSGRenderLayer::TonemapMode::HejlDawson: |
| 87 | return 3 + (size_t(isRGBE) * QSSGRenderLayer::TonemapModeCount); |
| 88 | case QSSGRenderLayer::TonemapMode::Filmic: |
| 89 | return 4 + (size_t(isRGBE) * QSSGRenderLayer::TonemapModeCount); |
| 90 | case QSSGRenderLayer::TonemapMode::Custom: |
| 91 | return 5 + (size_t(isRGBE) * QSSGRenderLayer::TonemapModeCount); |
| 92 | } |
| 93 | |
| 94 | // GCC 8.x does not treat __builtin_unreachable() as constexpr |
| 95 | # if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900) |
| 96 | // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8 |
| 97 | Q_UNREACHABLE(); |
| 98 | # endif |
| 99 | return 0; |
| 100 | } |
| 101 | |
| 102 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiSkyBoxShader(QSSGRenderLayer::TonemapMode tonemapMode, bool isRGBE, int viewCount) |
| 103 | { |
| 104 | // Skybox shader is special and has multiple possible shaders so we have to do |
| 105 | // a bit of manual work here (mapping resolved in getSkyboxIndex()). |
| 106 | static constexpr char variant[][23] { "skybox_hdr_none" , |
| 107 | "skybox_hdr_linear" , |
| 108 | "skybox_hdr_aces" , |
| 109 | "skybox_hdr_hejldawson" , |
| 110 | "skybox_hdr_filmic" , |
| 111 | "skybox_hdr_custom" , |
| 112 | "skybox_rgbe_none" , |
| 113 | "skybox_rgbe_linear" , |
| 114 | "skybox_rgbe_aces" , |
| 115 | "skybox_rgbe_hejldawson" , |
| 116 | "skybox_rgbe_filmic" , |
| 117 | "skybox_rgbe_custom" , |
| 118 | }; |
| 119 | |
| 120 | const size_t skyboxIndex = getSkyboxIndex(tonemapMode, isRGBE); |
| 121 | return getBuiltinRhiShader(name: QByteArray::fromRawData(data: variant[skyboxIndex], size: std::char_traits<char>::length(s: variant[skyboxIndex])), storage&: m_cache.skyBoxRhiShader[skyboxIndex], viewCount); |
| 122 | } |
| 123 | |
| 124 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiSupersampleResolveShader(int viewCount) |
| 125 | { |
| 126 | return getBuiltinRhiShader(QByteArrayLiteral("ssaaresolve" ), storage&: m_cache.supersampleResolveRhiShader, viewCount); |
| 127 | } |
| 128 | |
| 129 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiProgressiveAAShader() |
| 130 | { |
| 131 | return getBuiltinRhiShader(QByteArrayLiteral("progressiveaa" ), storage&: m_cache.progressiveAARhiShader); |
| 132 | } |
| 133 | |
| 134 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiParticleShader(QSSGRenderParticles::FeatureLevel featureLevel, int viewCount) |
| 135 | { |
| 136 | switch (featureLevel) { |
| 137 | case QSSGRenderParticles::FeatureLevel::Simple: |
| 138 | return getBuiltinRhiShader(QByteArrayLiteral("particlesnolightsimple" ), storage&: m_cache.particlesNoLightingSimpleRhiShader, viewCount); |
| 139 | break; |
| 140 | case QSSGRenderParticles::FeatureLevel::Mapped: |
| 141 | return getBuiltinRhiShader(QByteArrayLiteral("particlesnolightmapped" ), storage&: m_cache.particlesNoLightingMappedRhiShader, viewCount); |
| 142 | break; |
| 143 | case QSSGRenderParticles::FeatureLevel::Animated: |
| 144 | return getBuiltinRhiShader(QByteArrayLiteral("particlesnolightanimated" ), storage&: m_cache.particlesNoLightingAnimatedRhiShader, viewCount); |
| 145 | break; |
| 146 | case QSSGRenderParticles::FeatureLevel::SimpleVLight: |
| 147 | return getBuiltinRhiShader(QByteArrayLiteral("particlesvlightsimple" ), storage&: m_cache.particlesVLightingSimpleRhiShader, viewCount); |
| 148 | break; |
| 149 | case QSSGRenderParticles::FeatureLevel::MappedVLight: |
| 150 | return getBuiltinRhiShader(QByteArrayLiteral("particlesvlightmapped" ), storage&: m_cache.particlesVLightingMappedRhiShader, viewCount); |
| 151 | break; |
| 152 | case QSSGRenderParticles::FeatureLevel::AnimatedVLight: |
| 153 | return getBuiltinRhiShader(QByteArrayLiteral("particlesvlightanimated" ), storage&: m_cache.particlesVLightingAnimatedRhiShader, viewCount); |
| 154 | break; |
| 155 | case QSSGRenderParticles::FeatureLevel::Line: |
| 156 | return getBuiltinRhiShader(QByteArrayLiteral("lineparticles" ), storage&: m_cache.lineParticlesRhiShader, viewCount); |
| 157 | break; |
| 158 | case QSSGRenderParticles::FeatureLevel::LineMapped: |
| 159 | return getBuiltinRhiShader(QByteArrayLiteral("lineparticlesmapped" ), storage&: m_cache.lineParticlesMappedRhiShader, viewCount); |
| 160 | break; |
| 161 | case QSSGRenderParticles::FeatureLevel::LineAnimated: |
| 162 | return getBuiltinRhiShader(QByteArrayLiteral("lineparticlesanimated" ), storage&: m_cache.lineParticlesAnimatedRhiShader, viewCount); |
| 163 | break; |
| 164 | case QSSGRenderParticles::FeatureLevel::LineVLight: |
| 165 | return getBuiltinRhiShader(QByteArrayLiteral("lineparticlesvlightsimple" ), storage&: m_cache.lineParticlesVLightRhiShader, viewCount); |
| 166 | break; |
| 167 | case QSSGRenderParticles::FeatureLevel::LineMappedVLight: |
| 168 | return getBuiltinRhiShader(QByteArrayLiteral("lineparticlesvlightmapped" ), storage&: m_cache.lineParticlesMappedVLightRhiShader, viewCount); |
| 169 | break; |
| 170 | case QSSGRenderParticles::FeatureLevel::LineAnimatedVLight: |
| 171 | return getBuiltinRhiShader(QByteArrayLiteral("lineparticlesvlightanimated" ), storage&: m_cache.lineParticlesAnimatedVLightRhiShader, viewCount); |
| 172 | break; |
| 173 | } |
| 174 | return getBuiltinRhiShader(QByteArrayLiteral("particlesnolightanimated" ), storage&: m_cache.particlesNoLightingAnimatedRhiShader, viewCount); |
| 175 | } |
| 176 | |
| 177 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiSimpleQuadShader(int viewCount) |
| 178 | { |
| 179 | return getBuiltinRhiShader(QByteArrayLiteral("simplequad" ), storage&: m_cache.simpleQuadRhiShader, viewCount); |
| 180 | } |
| 181 | |
| 182 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiLightmapUVRasterizationShader(LightmapUVRasterizationShaderMode mode) |
| 183 | { |
| 184 | switch (mode) { |
| 185 | case LightmapUVRasterizationShaderMode::Uv: |
| 186 | return getBuiltinRhiShader(QByteArrayLiteral("lightmapuvraster_uv" ), storage&: m_cache.lightmapUVRasterShader_uv); |
| 187 | case LightmapUVRasterizationShaderMode::UvTangent: |
| 188 | return getBuiltinRhiShader(QByteArrayLiteral("lightmapuvraster_uv_tangent" ), storage&: m_cache.lightmapUVRasterShader_uv_tangent); |
| 189 | case LightmapUVRasterizationShaderMode::Default: |
| 190 | return getBuiltinRhiShader(QByteArrayLiteral("lightmapuvraster" ), storage&: m_cache.lightmapUVRasterShader); |
| 191 | } |
| 192 | |
| 193 | Q_UNREACHABLE_RETURN(getBuiltinRhiShader(QByteArrayLiteral("lightmapuvraster" ), m_cache.lightmapUVRasterShader)); |
| 194 | } |
| 195 | |
| 196 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiLightmapDilateShader() |
| 197 | { |
| 198 | return getBuiltinRhiShader(QByteArrayLiteral("lightmapdilate" ), storage&: m_cache.lightmapDilateShader); |
| 199 | } |
| 200 | |
| 201 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiDebugObjectShader(int viewCount) |
| 202 | { |
| 203 | return getBuiltinRhiShader(QByteArrayLiteral("debugobject" ), storage&: m_cache.debugObjectShader, viewCount); |
| 204 | } |
| 205 | |
| 206 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiReflectionprobePreFilterShader() |
| 207 | { |
| 208 | return getBuiltinRhiShader(QByteArrayLiteral("reflectionprobeprefilter" ), storage&: m_cache.reflectionprobePreFilterShader); |
| 209 | } |
| 210 | |
| 211 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhienvironmentmapPreFilterShader(bool isRGBE) |
| 212 | { |
| 213 | static constexpr char variant[][29] { "environmentmapprefilter" , "environmentmapprefilter_rgbe" }; |
| 214 | const quint8 idx = quint8(isRGBE); |
| 215 | return getBuiltinRhiShader(name: QByteArray::fromRawData(data: variant[idx], size: std::char_traits<char>::length(s: variant[idx])), storage&: m_cache.environmentmapPreFilterShader[idx]); |
| 216 | } |
| 217 | |
| 218 | QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiEnvironmentmapShader() |
| 219 | { |
| 220 | return getBuiltinRhiShader(QByteArrayLiteral("environmentmap" ), storage&: m_cache.environmentmapShader); |
| 221 | } |
| 222 | |
| 223 | QT_END_NAMESPACE |
| 224 | |