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 | |