/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef CORE_ECS_RENDERSYSTEM_H #define CORE_ECS_RENDERSYSTEM_H #include <ComponentTools/component_query.h> #include <PropertyTools/property_api_impl.h> #include <limits> #include <3d/ecs/components/layer_defines.h> #include <3d/ecs/components/render_configuration_component.h> #include <3d/ecs/systems/intf_render_system.h> #include <3d/render/render_data_defines_3d.h> #include <base/math/vector.h> #include <core/namespace.h> #include <render/namespace.h> #include <render/resource_handle.h> #include "property/property_handle.h" BASE_BEGIN_NAMESPACE() namespace Math { class Mat4X4; } // namespace Math BASE_END_NAMESPACE() CORE_BEGIN_NAMESPACE() class IFrustumUtil; CORE_END_NAMESPACE() RENDER_BEGIN_NAMESPACE() class IShaderManager; class IRenderContext; RENDER_END_NAMESPACE() CORE3D_BEGIN_NAMESPACE() class IEnvironmentComponentManager; class IFogComponentManager; class IRenderHandleComponentManager; class INameComponentManager; class INodeComponentManager; class IRenderMeshBatchComponentManager; class IRenderMeshComponentManager; class IWorldMatrixComponentManager; class IPreviousWorldMatrixComponentManager; class IRenderConfigurationComponentManager; class ICameraComponentManager; class ILayerComponentManager; class ILightComponentManager; class IJointMatricesComponentManager; class IMaterialExtensionComponentManager; class IMaterialComponentManager; class IMeshComponentManager; class ISkinJointsComponentManager; class IPlanarReflectionComponentManager; class IPreviousJointMatricesComponentManager; class IPostProcessComponentManager; class IPostProcessConfigurationComponentManager; class IUriComponentManager; class IRenderDataStoreDefaultCamera; class IRenderDataStoreDefaultLight; class IRenderDataStoreDefaultMaterial; class IRenderDataStoreDefaultScene; class IRenderPreprocessorSystem; class IMesh; class IMaterial; class IPicking; class IRenderUtil; class IGraphicsContext; struct RenderMeshComponent; struct JointMatricesComponent; struct PreviousJointMatricesComponent; struct MaterialComponent; struct WorldMatrixComponent; struct LightComponent; struct MinAndMax; class RenderSystem final : public IRenderSystem { public: explicit RenderSystem(CORE_NS::IEcs& ecs); ~RenderSystem() override; BASE_NS::string_view GetName() const override; BASE_NS::Uid GetUid() const override; CORE_NS::IPropertyHandle* GetProperties() override; const CORE_NS::IPropertyHandle* GetProperties() const override; void SetProperties(const CORE_NS::IPropertyHandle&) override; bool IsActive() const override; void SetActive(bool state) override; void Initialize() override; bool Update(bool frameRenderingQueued, uint64_t totalTime, uint64_t deltaTime) override; void Uninitialize() override; const CORE_NS::IEcs& GetECS() const override; BASE_NS::array_view<const RENDER_NS::RenderHandleReference> GetRenderNodeGraphs() const override; struct BatchData { CORE_NS::Entity entity; // node, render mesh component CORE_NS::Entity mesh; // mesh component uint64_t layerMask { LayerConstants::DEFAULT_LAYER_MASK }; CORE_NS::IComponentManager::ComponentId jointId { CORE_NS::IComponentManager::INVALID_COMPONENT_ID }; CORE_NS::IComponentManager::ComponentId prevJointId { CORE_NS::IComponentManager::INVALID_COMPONENT_ID }; BASE_NS::Math::Mat4X4 mtx; // world matrix BASE_NS::Math::Mat4X4 prevWorld; // previous world matrix }; using BatchDataVector = BASE_NS::vector<BatchData>; struct DefaultMaterialShaderData { struct SingleShaderData { CORE_NS::EntityReference shader; CORE_NS::EntityReference gfxState; CORE_NS::EntityReference gfxStateDoubleSided; }; SingleShaderData opaque; SingleShaderData blend; SingleShaderData depth; }; struct CameraRenderNodeGraphs { // camera RENDER_NS::RenderHandleReference rngHandle; // camera post process RENDER_NS::RenderHandleReference ppRngHandle; }; struct CameraRngsOutput { CameraRenderNodeGraphs rngs; // multi-view post processes RENDER_NS::RenderHandleReference multiviewPpHandles[RenderSceneDataConstants::MAX_MULTI_VIEW_LAYER_CAMERA_COUNT] { {}, {}, {} }; }; private: struct MeshProcessData { const uint64_t layerMask { 0 }; const uint32_t batchInstanceCount { 0 }; const bool duplicateMaterialInstances { false }; const CORE_NS::Entity& renderMeshEntity; const CORE_NS::Entity& meshEntity; const MeshComponent& meshComponent; const RenderMeshComponent& renderMeshComponent; const BASE_NS::Math::Mat4X4& world; const BASE_NS::Math::Mat4X4& prevWorld; }; struct LightProcessData { const uint64_t layerMask { 0 }; const CORE_NS::Entity& entity; const LightComponent& lightComponent; const BASE_NS::Math::Mat4X4& world; RenderScene& renderScene; uint32_t& spotLightIndex; }; struct SkinProcessData { const JointMatricesComponent* const jointMatricesComponent { nullptr }; const PreviousJointMatricesComponent* const prevJointMatricesComponent { nullptr }; }; void SetDataStorePointers(RENDER_NS::IRenderDataStoreManager& manager); // returns the instance's valid scene component RenderConfigurationComponent GetRenderConfigurationComponent(); CORE_NS::Entity ProcessScene(const RenderConfigurationComponent& sc); uint32_t ProcessSubmesh(const MeshProcessData& mpd, const MeshComponent::Submesh& submesh, const uint32_t meshIndex, const uint32_t subMeshIdx, const uint32_t skinJointIndex, const MinAndMax& mam, const bool isNegative); void ProcessMesh(const MeshProcessData& mpd, const MinAndMax& batchMam, const SkinProcessData& spd, BASE_NS::vector<uint32_t>* submeshMaterials); void ProcessRenderMeshBatch(const CORE_NS::Entity renderMeshBatch, const CORE_NS::ComponentQuery::ResultRow* row); void ProcessRenderMeshBatch(BASE_NS::array_view<const CORE_NS::Entity> renderMeshComponents); void ProcessSingleRenderMesh(CORE_NS::Entity renderMeshComponent); void ProcessRenderables(); void ProcessBatchRenderables(); void ProcessEnvironments(const RenderConfigurationComponent& sceneComponent); void ProcessCameras(const RenderConfigurationComponent& sceneComponent, const CORE_NS::Entity& mainCameraEntity, RenderScene& renderScene); void ProcessLight(const LightProcessData& lightProcessData); void ProcessLights(RenderScene& renderScene); void ProcessShadowCamera(const LightProcessData lightProcessData, RenderLight& light); void ProcessReflection(const CORE_NS::ComponentQuery::ResultRow& row, const RenderCamera& camera); void ProcessReflections(const RenderScene& renderScene); void ProcessPostProcesses(); void FetchFullScene(); void EvaluateMaterialModifications(const MaterialComponent& matComp); // calculates min max from all submeshes and does min max for inout struct BatchIndices { uint32_t submeshIndex { ~0u }; uint32_t batchStartIndex { ~0u }; uint32_t batchEndCount { ~0u }; }; // with submeshIndex == ~0u processes all submeshes void CombineBatchWorldMinAndMax(const BatchDataVector& batchData, const BatchIndices& batchIndices, const MeshComponent& mesh, MinAndMax& mam) const; void ProcessRenderNodeGraphs(const RenderConfigurationComponent& renderConfig, const RenderScene& renderScene); void DestroyRenderDataStores(); CameraRngsOutput GetCameraRenderNodeGraphs(const RenderScene& renderScene, const RenderCamera& renderCamera); RENDER_NS::RenderHandleReference GetSceneRenderNodeGraph(const RenderScene& renderScene); struct CameraData; CameraData UpdateAndGetPreviousFrameCameraData( const CORE_NS::Entity& entity, const BASE_NS::Math::Mat4X4& view, const BASE_NS::Math::Mat4X4& proj); BASE_NS::vector<RenderCamera> GetMultiviewCameras(const RenderCamera& renderCamera); bool active_ = true; CORE_NS::IEcs& ecs_; IRenderSystem::Properties properties_; IRenderDataStoreDefaultCamera* dsCamera_ = nullptr; IRenderDataStoreDefaultLight* dsLight_ = nullptr; IRenderDataStoreDefaultMaterial* dsMaterial_ = nullptr; IRenderDataStoreDefaultScene* dsScene_ = nullptr; RENDER_NS::IShaderManager* shaderMgr_ = nullptr; RENDER_NS::IGpuResourceManager* gpuResourceMgr_ = nullptr; CORE_NS::IFrustumUtil* frustumUtil_ = nullptr; INodeComponentManager* nodeMgr_ = nullptr; IRenderMeshBatchComponentManager* renderMeshBatchMgr_ = nullptr; IRenderMeshComponentManager* renderMeshMgr_ = nullptr; IWorldMatrixComponentManager* worldMatrixMgr_ = nullptr; IPreviousWorldMatrixComponentManager* prevWorldMatrixMgr_ = nullptr; IRenderConfigurationComponentManager* renderConfigMgr_ = nullptr; ICameraComponentManager* cameraMgr_ = nullptr; ILightComponentManager* lightMgr_ = nullptr; IPlanarReflectionComponentManager* planarReflectionMgr_ = nullptr; IMaterialExtensionComponentManager* materialExtensionMgr_ = nullptr; IMaterialComponentManager* materialMgr_ = nullptr; IMeshComponentManager* meshMgr_ = nullptr; IUriComponentManager* uriMgr_ = nullptr; INameComponentManager* nameMgr_ = nullptr; IEnvironmentComponentManager* environmentMgr_ = nullptr; IFogComponentManager* fogMgr_ = nullptr; IRenderHandleComponentManager* gpuHandleMgr_ = nullptr; ILayerComponentManager* layerMgr_ = nullptr; IJointMatricesComponentManager* jointMatricesMgr_ = nullptr; IPreviousJointMatricesComponentManager* prevJointMatricesMgr_ = nullptr; IPostProcessComponentManager* postProcessMgr_ = nullptr; IPostProcessConfigurationComponentManager* postProcessConfigMgr_ = nullptr; uint32_t renderConfigurationGeneration_ = 0; uint32_t cameraGeneration_ = 0; uint32_t lightGeneration_ = 0; uint32_t planarReflectionGeneration_ = 0; uint32_t materialExtensionGeneration_ = 0; uint32_t environmentGeneration_ = 0; uint32_t fogGeneration_ = 0; uint32_t postprocessGeneration_ = 0; uint32_t postprocessConfigurationGeneration_ = 0; IPicking* picking_ = nullptr; IGraphicsContext* graphicsContext_ = nullptr; IRenderUtil* renderUtil_ = nullptr; RENDER_NS::IRenderContext* renderContext_ = nullptr; IRenderPreprocessorSystem* renderPreprocessorSystem_ = nullptr; CORE_NS::ComponentQuery lightQuery_; CORE_NS::ComponentQuery renderableQuery_; CORE_NS::ComponentQuery reflectionsQuery_; BASE_NS::Math::Vec3 sceneBoundingSpherePosition_ { 0.0f, 0.0f, 0.0f }; float sceneBoundingSphereRadius_ { 0.0f }; CORE_NS::PropertyApiImpl<IRenderSystem::Properties> RENDER_SYSTEM_PROPERTIES; uint64_t totalTime_ { 0u }; uint64_t deltaTime_ { 0u }; uint64_t frameIndex_ { 0u }; // additionally these could be stored to somewhere else // though this is ECS render system and the render node graphs are owned by ECS (RS) // these do not add overhead if the property bits are not set (only clear per frame) struct RenderProcessing { struct AdditionalCameraContainer { CameraRenderNodeGraphs rngs; RenderCamera::Flags flags { 0 }; RenderCamera::RenderPipelineType renderPipelineType { RenderCamera::RenderPipelineType::FORWARD }; uint64_t lastFrameIndex { 0 }; // frame when used bool enableAutoDestroy { true }; // always true with all cameras BASE_NS::fixed_string<RENDER_NS::RenderDataConstants::MAX_DEFAULT_NAME_LENGTH> postProcessName; BASE_NS::string customRngFile; BASE_NS::string customPostProcessRngFile; uint32_t multiViewCameraCount { 0U }; }; struct SceneRngContainer { BASE_NS::string customRngFile; BASE_NS::string customPostSceneRngFile; RENDER_NS::RenderHandleReference rng; RENDER_NS::RenderHandleReference customRng; RENDER_NS::RenderHandleReference customPostRng; }; // all render node graphs (scene rng is always the first and this needs to be in order) BASE_NS::vector<RENDER_NS::RenderHandleReference> orderedRenderNodeGraphs; // camera component id with generation hash BASE_NS::unordered_map<uint64_t, AdditionalCameraContainer> camIdToRng; SceneRngContainer sceneRngs; uint64_t sceneMainCamId { 0 }; // reset every frame (flags for rendering hints) uint32_t frameFlags { 0u }; // store created pods BASE_NS::vector<BASE_NS::string> postProcessPods; // store created post process data stores BASE_NS::vector<BASE_NS::string> postProcessConfigs; bool frameProcessed { false }; }; RenderProcessing renderProcessing_; struct CameraData { BASE_NS::Math::Mat4X4 view; BASE_NS::Math::Mat4X4 proj; uint64_t lastFrameIndex { 0 }; // frame when used }; // store previous frame matrices BASE_NS::unordered_map<CORE_NS::Entity, CameraData> cameraData_; BASE_NS::unordered_map<CORE_NS::Entity, BatchDataVector> batches_; BASE_NS::vector<uint32_t> materialIndices_; // store default shader data for default materials in this ECS DefaultMaterialShaderData dmShaderData_; }; CORE3D_END_NAMESPACE() #endif // CORE_ECS_RENDERSYSTEM_H