1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifndef CORE_ECS_RENDERSYSTEM_H
17 #define CORE_ECS_RENDERSYSTEM_H
18
19 #include <ComponentTools/component_query.h>
20 #include <limits>
21
22 #include <3d/ecs/components/layer_defines.h>
23 #include <3d/ecs/components/render_configuration_component.h>
24 #include <3d/ecs/systems/intf_render_system.h>
25 #include <3d/render/render_data_defines_3d.h>
26 #include <base/containers/unordered_map.h>
27 #include <base/math/vector.h>
28 #include <core/namespace.h>
29 #include <core/property_tools/property_api_impl.h>
30 #include <render/namespace.h>
31 #include <render/resource_handle.h>
32
33 #include "property/property_handle.h"
34
BASE_BEGIN_NAMESPACE()35 BASE_BEGIN_NAMESPACE()
36 namespace Math {
37 class Mat4X4;
38 } // namespace Math
39 BASE_END_NAMESPACE()
40
41 CORE_BEGIN_NAMESPACE()
42 class IFrustumUtil;
43 CORE_END_NAMESPACE()
44
45 RENDER_BEGIN_NAMESPACE()
46 class IShaderManager;
47 class IRenderContext;
48 struct PostProcessConfiguration;
49 RENDER_END_NAMESPACE()
50
51 CORE3D_BEGIN_NAMESPACE()
52 class IDynamicEnvironmentBlenderComponentManager;
53 class IEnvironmentComponentManager;
54 class IFogComponentManager;
55 class IRenderHandleComponentManager;
56 class INameComponentManager;
57 class INodeComponentManager;
58 class IRenderMeshComponentManager;
59 class IWorldMatrixComponentManager;
60 class IRenderConfigurationComponentManager;
61 class ICameraComponentManager;
62 class ILayerComponentManager;
63 class ILightComponentManager;
64 class IJointMatricesComponentManager;
65 class IMaterialComponentManager;
66 class IMeshComponentManager;
67 class ISkinJointsComponentManager;
68 class IPlanarReflectionComponentManager;
69 class IPreviousJointMatricesComponentManager;
70 class IPostProcessComponentManager;
71 class IPostProcessConfigurationComponentManager;
72 class IUriComponentManager;
73 class IRenderDataStoreDefaultCamera;
74 class IRenderDataStoreDefaultLight;
75 class IRenderDataStoreDefaultMaterial;
76 class IRenderDataStoreDefaultScene;
77
78 class IRenderPreprocessorSystem;
79
80 class IMesh;
81 class IMaterial;
82 class IPicking;
83 class IRenderUtil;
84 class IGraphicsContext;
85
86 struct RenderMeshComponent;
87 struct JointMatricesComponent;
88 struct PreviousJointMatricesComponent;
89 struct MaterialComponent;
90 struct WorldMatrixComponent;
91 struct LightComponent;
92 struct MinAndMax;
93
94 class RenderSystem final : public IRenderSystem {
95 public:
96 explicit RenderSystem(CORE_NS::IEcs& ecs);
97 ~RenderSystem() override;
98 BASE_NS::string_view GetName() const override;
99 BASE_NS::Uid GetUid() const override;
100 CORE_NS::IPropertyHandle* GetProperties() override;
101 const CORE_NS::IPropertyHandle* GetProperties() const override;
102 void SetProperties(const CORE_NS::IPropertyHandle&) override;
103 bool IsActive() const override;
104 void SetActive(bool state) override;
105
106 void Initialize() override;
107 bool Update(bool frameRenderingQueued, uint64_t totalTime, uint64_t deltaTime) override;
108 void Uninitialize() override;
109
110 const CORE_NS::IEcs& GetECS() const override;
111
112 BASE_NS::array_view<const RENDER_NS::RenderHandleReference> GetRenderNodeGraphs() const override;
113
114 struct BatchData {
115 CORE_NS::Entity entity; // node, render mesh component
116 CORE_NS::Entity mesh; // mesh component
117 uint64_t layerMask { LayerConstants::DEFAULT_LAYER_MASK };
118 CORE_NS::IComponentManager::ComponentId jointId { CORE_NS::IComponentManager::INVALID_COMPONENT_ID };
119 CORE_NS::IComponentManager::ComponentId prevJointId { CORE_NS::IComponentManager::INVALID_COMPONENT_ID };
120
121 BASE_NS::Math::Mat4X4 mtx; // world matrix
122 BASE_NS::Math::Mat4X4 prevWorld; // previous world matrix
123 };
124 using BatchDataVector = BASE_NS::vector<BatchData>;
125
126 struct DefaultMaterialShaderData {
127 struct SingleShaderData {
128 CORE_NS::EntityReference shader;
129 CORE_NS::EntityReference gfxState;
130 CORE_NS::EntityReference gfxStateDoubleSided;
131 };
132 SingleShaderData opaque;
133 SingleShaderData blend;
134 SingleShaderData depth;
135 };
136 struct CameraRenderNodeGraphs {
137 // camera
138 RENDER_NS::RenderHandleReference rngHandle;
139 // camera post process
140 RENDER_NS::RenderHandleReference ppRngHandle;
141 };
142 struct CameraRngsOutput {
143 CameraRenderNodeGraphs rngs;
144 // multi-view post processes
145 RENDER_NS::RenderHandleReference
146 multiviewPpHandles[RenderSceneDataConstants::MAX_MULTI_VIEW_LAYER_CAMERA_COUNT] { {}, {}, {} };
147 };
148
149 private:
150 struct MeshProcessData {
151 const uint64_t layerMask { 0 };
152 const uint32_t batchInstanceCount { 0 };
153 const CORE_NS::Entity& renderMeshEntity;
154 const CORE_NS::Entity& meshEntity;
155 const MeshComponent& meshComponent;
156 const RenderMeshComponent& renderMeshComponent;
157 const BASE_NS::Math::Mat4X4& world;
158 const BASE_NS::Math::Mat4X4& prevWorld;
159 bool materialGpuInstancing { false };
160 };
161 struct LightProcessData {
162 const uint64_t layerMask { 0 };
163 const CORE_NS::Entity& entity;
164 const LightComponent& lightComponent;
165 const BASE_NS::Math::Mat4X4& world;
166 RenderScene& renderScene;
167 uint32_t& spotLightIndex;
168 };
169 struct SkinProcessData {
170 const JointMatricesComponent* const jointMatricesComponent { nullptr };
171 const PreviousJointMatricesComponent* const prevJointMatricesComponent { nullptr };
172 };
173
174 void SetDataStorePointers(RENDER_NS::IRenderDataStoreManager& manager);
175 // returns the instance's valid scene component
176 RenderConfigurationComponent GetRenderConfigurationComponent();
177 CORE_NS::Entity ProcessScene(const RenderConfigurationComponent& sc);
178 // return material frame offset
179 uint32_t ProcessSubmesh(const MeshProcessData& mpd, const MeshComponent::Submesh& submesh, const uint32_t meshIndex,
180 const uint32_t subMeshIdx, const uint32_t skinJointIndex, const MinAndMax& mam, const bool isNegative);
181 void ProcessMesh(const MeshProcessData& mpd, const MinAndMax& batchMam, const SkinProcessData& spd,
182 BASE_NS::vector<uint32_t>* submeshMaterials);
183 void ProcessRenderMeshComponentBatch(
184 const CORE_NS::Entity renderMeshBatch, const CORE_NS::ComponentQuery::ResultRow* row);
185 void ProcessRenderMeshAutomaticBatch(BASE_NS::array_view<const CORE_NS::Entity> renderMeshComponents);
186 void ProcessSingleRenderMesh(CORE_NS::Entity renderMeshComponent);
187 void ProcessRenderables();
188 void ProcessRenderMeshBatchComponentRenderables();
189 void ProcessEnvironments(const RenderConfigurationComponent& sceneComponent);
190 void ProcessCameras(const RenderConfigurationComponent& sceneComponent, const CORE_NS::Entity& mainCameraEntity,
191 RenderScene& renderScene);
192 void ProcessLight(const LightProcessData& lightProcessData);
193 void ProcessLights(RenderScene& renderScene);
194 void ProcessShadowCamera(const LightProcessData lightProcessData, RenderLight& light);
195 void ProcessReflection(
196 const CORE_NS::ComponentQuery::ResultRow& row, const RenderCamera& camera, BASE_NS::Math::UVec2 targetRes);
197 void ProcessReflections(const RenderScene& renderScene);
198 void ProcessPostProcesses();
199 void RecalculatePostProcesses(BASE_NS::string_view name, RENDER_NS::PostProcessConfiguration& ppConfig);
200 void FetchFullScene();
201 void EvaluateMaterialModifications(const MaterialComponent& matComp);
202 // calculates min max from all submeshes and does min max for inout
203 struct BatchIndices {
204 uint32_t submeshIndex { ~0u };
205 uint32_t batchStartIndex { ~0u };
206 uint32_t batchEndIndex { ~0u };
207 };
208 // with submeshIndex == ~0u processes all submeshes
209 void CombineBatchWorldMinAndMax(const BatchDataVector& batchData, const BatchIndices& batchIndices,
210 const MeshComponent& mesh, MinAndMax& mam) const;
211
212 void ProcessRenderNodeGraphs(const RenderConfigurationComponent& renderConfig, const RenderScene& renderScene);
213 void DestroyRenderDataStores();
214 CameraRngsOutput GetCameraRenderNodeGraphs(const RenderScene& renderScene, const RenderCamera& renderCamera);
215 RENDER_NS::RenderHandleReference GetSceneRenderNodeGraph(const RenderScene& renderScene);
216
217 struct CameraData;
218 CameraData UpdateAndGetPreviousFrameCameraData(
219 const CORE_NS::Entity& entity, const BASE_NS::Math::Mat4X4& view, const BASE_NS::Math::Mat4X4& proj);
220 BASE_NS::vector<RenderCamera> GetMultiviewCameras(const RenderCamera& renderCamera);
221
222 bool active_ = true;
223 CORE_NS::IEcs& ecs_;
224
225 IRenderSystem::Properties properties_;
226
227 BASE_NS::refcnt_ptr<IRenderDataStoreDefaultCamera> dsCamera_;
228 BASE_NS::refcnt_ptr<IRenderDataStoreDefaultLight> dsLight_;
229 BASE_NS::refcnt_ptr<IRenderDataStoreDefaultMaterial> dsMaterial_;
230 BASE_NS::refcnt_ptr<IRenderDataStoreDefaultScene> dsScene_;
231 RENDER_NS::IShaderManager* shaderMgr_ = nullptr;
232 RENDER_NS::IGpuResourceManager* gpuResourceMgr_ = nullptr;
233 CORE_NS::IFrustumUtil* frustumUtil_ = nullptr;
234
235 INodeComponentManager* nodeMgr_ = nullptr;
236 IRenderMeshComponentManager* renderMeshMgr_ = nullptr;
237 IWorldMatrixComponentManager* worldMatrixMgr_ = nullptr;
238 IRenderConfigurationComponentManager* renderConfigMgr_ = nullptr;
239 ICameraComponentManager* cameraMgr_ = nullptr;
240 ILightComponentManager* lightMgr_ = nullptr;
241 IPlanarReflectionComponentManager* planarReflectionMgr_ = nullptr;
242
243 IMaterialComponentManager* materialMgr_ = nullptr;
244 IMeshComponentManager* meshMgr_ = nullptr;
245 IUriComponentManager* uriMgr_ = nullptr;
246 INameComponentManager* nameMgr_ = nullptr;
247 IEnvironmentComponentManager* environmentMgr_ = nullptr;
248 IFogComponentManager* fogMgr_ = nullptr;
249 IRenderHandleComponentManager* gpuHandleMgr_ = nullptr;
250 ILayerComponentManager* layerMgr_ = nullptr;
251 IDynamicEnvironmentBlenderComponentManager* dynamicEnvBlendMgr_ = nullptr;
252
253 IJointMatricesComponentManager* jointMatricesMgr_ = nullptr;
254 IPreviousJointMatricesComponentManager* prevJointMatricesMgr_ = nullptr;
255
256 IPostProcessComponentManager* postProcessMgr_ = nullptr;
257 IPostProcessConfigurationComponentManager* postProcessConfigMgr_ = nullptr;
258
259 uint32_t renderConfigurationGeneration_ = 0;
260 uint32_t cameraGeneration_ = 0;
261 uint32_t lightGeneration_ = 0;
262 uint32_t planarReflectionGeneration_ = 0;
263 uint32_t environmentGeneration_ = 0;
264 uint32_t fogGeneration_ = 0;
265 uint32_t postprocessGeneration_ = 0;
266 uint32_t postprocessConfigurationGeneration_ = 0;
267
268 IPicking* picking_ = nullptr;
269
270 IGraphicsContext* graphicsContext_ = nullptr;
271 IRenderUtil* renderUtil_ = nullptr;
272 RENDER_NS::IRenderContext* renderContext_ = nullptr;
273
274 IRenderPreprocessorSystem* renderPreprocessorSystem_ = nullptr;
275
276 CORE_NS::ComponentQuery lightQuery_;
277 CORE_NS::ComponentQuery renderableQuery_;
278 CORE_NS::ComponentQuery reflectionsQuery_;
279 uint32_t reflectionMaxMipBlur_ { 0U };
280
281 BASE_NS::Math::Vec3 sceneBoundingSpherePosition_ { 0.0f, 0.0f, 0.0f };
282 float sceneBoundingSphereRadius_ { 0.0f };
283
284 CORE_NS::PropertyApiImpl<IRenderSystem::Properties> RENDER_SYSTEM_PROPERTIES;
285
286 uint64_t totalTime_ { 0u };
287 uint64_t deltaTime_ { 0u };
288 uint64_t frameIndex_ { 0u };
289
290 // additionally these could be stored to somewhere else
291 // though this is ECS render system and the render node graphs are owned by ECS (RS)
292 // these do not add overhead if the property bits are not set (only clear per frame)
293 struct RenderProcessing {
294 struct AdditionalCameraContainer {
295 CameraRenderNodeGraphs rngs;
296 RenderCamera::Flags flags { 0 };
297 RenderCamera::RenderPipelineType renderPipelineType { RenderCamera::RenderPipelineType::FORWARD };
298 uint64_t lastFrameIndex { 0 }; // frame when used
299 BASE_NS::fixed_string<RENDER_NS::RenderDataConstants::MAX_DEFAULT_NAME_LENGTH> postProcessName;
300 BASE_NS::string customRngFile;
301 BASE_NS::string customPostProcessRngFile;
302 uint32_t multiViewCameraCount { 0U };
303 uint64_t multiViewCameraHash { 0U };
304 };
305 struct SceneRngContainer {
306 BASE_NS::string customRngFile;
307 BASE_NS::string customPostSceneRngFile;
308
309 RENDER_NS::RenderHandleReference rng;
310 RENDER_NS::RenderHandleReference customRng;
311 RENDER_NS::RenderHandleReference customPostRng;
312 };
313
314 // all render node graphs (scene rng is always the first and this needs to be in order)
315 BASE_NS::vector<RENDER_NS::RenderHandleReference> orderedRenderNodeGraphs;
316 // camera component id with generation hash
317 BASE_NS::unordered_map<uint64_t, AdditionalCameraContainer> camIdToRng;
318
319 SceneRngContainer sceneRngs;
320 uint64_t sceneMainCamId { 0 };
321
322 // reset every frame (flags for rendering hints)
323 uint32_t frameFlags { 0u };
324
325 // store created pods
326 BASE_NS::vector<BASE_NS::string> postProcessPods;
327 // store created post process data stores
328 BASE_NS::vector<BASE_NS::string> postProcessConfigs;
329
330 bool frameProcessed { false };
331 };
332 RenderProcessing renderProcessing_;
333
334 struct CameraData {
335 BASE_NS::Math::Mat4X4 view;
336 BASE_NS::Math::Mat4X4 proj;
337 uint64_t lastFrameIndex { 0 }; // frame when used
338 };
339 // store previous frame matrices
340 BASE_NS::unordered_map<CORE_NS::Entity, CameraData> cameraData_;
341
342 BASE_NS::unordered_map<CORE_NS::Entity, BatchDataVector> batches_;
343 // used to fetch submesh material frame offsets
344 BASE_NS::vector<uint32_t> materialFrameOffsets_;
345
346 // store default shader data for default materials in this ECS
347 DefaultMaterialShaderData dmShaderData_;
348 };
349 CORE3D_END_NAMESPACE()
350
351 #endif // CORE_ECS_RENDERSYSTEM_H
352