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 #include "render_node_default_lights.h"
17 
18 #include <algorithm>
19 
20 #include <3d/render/default_material_constants.h>
21 #include <3d/render/intf_render_data_store_default_camera.h>
22 #include <3d/render/intf_render_data_store_default_light.h>
23 #include <3d/render/intf_render_data_store_default_scene.h>
24 #include <base/math/matrix_util.h>
25 #include <core/log.h>
26 #include <core/namespace.h>
27 #include <render/datastore/intf_render_data_store.h>
28 #include <render/datastore/intf_render_data_store_manager.h>
29 #include <render/device/intf_gpu_resource_manager.h>
30 #include <render/nodecontext/intf_render_node_context_manager.h>
31 #include <render/nodecontext/intf_render_node_graph_share_manager.h>
32 
33 // NOTE: do not include in header
34 #include "render_light_helper.h"
35 
36 namespace {
37 #include <3d/shaders/common/3d_dm_structures_common.h>
38 } // namespace
39 
40 CORE3D_BEGIN_NAMESPACE()
41 using namespace BASE_NS;
42 using namespace RENDER_NS;
43 
44 namespace {
45 template<typename DataType>
MapBuffer(IRenderNodeGpuResourceManager & gpuResourceManager,const RenderHandle handle)46 DataType* MapBuffer(IRenderNodeGpuResourceManager& gpuResourceManager, const RenderHandle handle)
47 {
48     return reinterpret_cast<DataType*>(gpuResourceManager.MapBuffer(handle));
49 }
50 } // namespace
51 
InitNode(IRenderNodeContextManager & renderNodeContextMgr)52 void RenderNodeDefaultLights::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
53 {
54     renderNodeContextMgr_ = &renderNodeContextMgr;
55 
56     const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
57     stores_ = RenderNodeSceneUtil::GetSceneRenderDataStores(
58         renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName);
59 
60     const string bufferName =
61         stores_.dataStoreNameScene.c_str() + DefaultMaterialLightingConstants::LIGHT_DATA_BUFFER_NAME;
62     const string clusterBufferName =
63         stores_.dataStoreNameScene.c_str() + DefaultMaterialLightingConstants::LIGHT_CLUSTER_DATA_BUFFER_NAME;
64 
65     auto& gpuResourceMgr = renderNodeContextMgr.GetGpuResourceManager();
66     lightBufferHandle_ = gpuResourceMgr.Create(
67         bufferName, {
68                         CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
69                         (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
70                         CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
71                         sizeof(DefaultMaterialLightStruct),
72                     });
73     lightClusterBufferHandle_ = gpuResourceMgr.Create(
74         clusterBufferName, {
75                                CORE_BUFFER_USAGE_STORAGE_BUFFER_BIT,
76                                (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
77                                CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
78                                sizeof(uint32_t) * RenderLightHelper::DEFAULT_CLUSTER_INDEX_COUNT,
79                            });
80     if (lightBufferHandle_ && lightClusterBufferHandle_) {
81         IRenderNodeGraphShareManager& rngShareMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
82         const RenderHandle handles[] = { lightBufferHandle_.GetHandle(), lightClusterBufferHandle_.GetHandle() };
83         rngShareMgr.RegisterRenderNodeOutputs(handles);
84     }
85 }
86 
PreExecuteFrame()87 void RenderNodeDefaultLights::PreExecuteFrame()
88 {
89     if (lightBufferHandle_) {
90         IRenderNodeGraphShareManager& rngShareMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
91         const RenderHandle handle = lightBufferHandle_.GetHandle();
92         rngShareMgr.RegisterRenderNodeOutputs({ &handle, 1u });
93     }
94 }
95 
ExecuteFrame(IRenderCommandList & cmdList)96 void RenderNodeDefaultLights::ExecuteFrame(IRenderCommandList& cmdList)
97 {
98     const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
99     const auto* dataStoreScene =
100         static_cast<IRenderDataStoreDefaultScene*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameScene));
101     const auto* dataStoreCamera =
102         static_cast<IRenderDataStoreDefaultCamera*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameCamera));
103     const auto* dataStoreLight =
104         static_cast<IRenderDataStoreDefaultLight*>(renderDataStoreMgr.GetRenderDataStore(stores_.dataStoreNameLight));
105 
106     if (dataStoreScene && dataStoreLight && dataStoreCamera) {
107         auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
108         const auto scene = dataStoreScene->GetScene();
109         const uint32_t sceneCameraIdx = scene.cameraIndex;
110         const auto& lights = dataStoreLight->GetLights();
111         const auto& cameras = dataStoreCamera->GetCameras();
112         const bool validCamera = (sceneCameraIdx < static_cast<uint32_t>(cameras.size()));
113         const Math::Vec4 shadowAtlasSizeInvSize = RenderLightHelper::GetShadowAtlasSizeInvSize(*dataStoreLight);
114         const uint32_t shadowCount = dataStoreLight->GetLightCounts().shadowCount;
115         // light buffer update (needs to be updated every frame)
116         if (auto data = MapBuffer<uint8_t>(gpuResourceMgr, lightBufferHandle_.GetHandle()); data) {
117             // NOTE: do not read data from mapped buffer (i.e. do not use mapped buffer as input to anything)
118             RenderLightHelper::LightCounts lightCounts;
119             const uint32_t lightCount = std::min(CORE_DEFAULT_MATERIAL_MAX_LIGHT_COUNT, (uint32_t)lights.size());
120             vector<RenderLightHelper::SortData> sortedFlags = RenderLightHelper::SortLights(lights, lightCount);
121 
122             const RenderCamera camera = validCamera ? cameras[sceneCameraIdx] : RenderCamera {};
123 
124             auto* singleLightStruct =
125                 reinterpret_cast<DefaultMaterialSingleLightStruct*>(data + RenderLightHelper::LIGHT_LIST_OFFSET);
126             for (const auto& sortData : sortedFlags) {
127                 using UsageFlagBits = RenderLight::LightUsageFlagBits;
128                 if (sortData.lightUsageFlags & UsageFlagBits::LIGHT_USAGE_DIRECTIONAL_LIGHT_BIT) {
129                     lightCounts.directionalLightCount++;
130                 } else if (sortData.lightUsageFlags & UsageFlagBits::LIGHT_USAGE_POINT_LIGHT_BIT) {
131                     lightCounts.pointLightCount++;
132                 } else if (sortData.lightUsageFlags & UsageFlagBits::LIGHT_USAGE_SPOT_LIGHT_BIT) {
133                     lightCounts.spotLightCount++;
134                 }
135 
136                 RenderLightHelper::CopySingleLight(lights[sortData.index], shadowCount, singleLightStruct++);
137             }
138 
139             DefaultMaterialLightStruct* lightStruct = reinterpret_cast<DefaultMaterialLightStruct*>(data);
140             lightStruct->directionalLightBeginIndex = 0;
141             lightStruct->directionalLightCount = lightCounts.directionalLightCount;
142             lightStruct->pointLightBeginIndex = lightCounts.directionalLightCount;
143             lightStruct->pointLightCount = lightCounts.pointLightCount;
144             lightStruct->spotLightBeginIndex = lightCounts.directionalLightCount + lightCounts.pointLightCount;
145             lightStruct->spotLightCount = lightCounts.spotLightCount;
146             lightStruct->pad0 = 0;
147             lightStruct->pad1 = 0;
148             lightStruct->clusterSizes = Math::UVec4(0, 0, 0, 0);
149             lightStruct->clusterFactors = Math::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
150             lightStruct->atlasSizeInvSize = shadowAtlasSizeInvSize;
151             lightStruct->additionalFactors = { 0.0f, 0.0f, 0.0f, 0.0f };
152 
153             gpuResourceMgr.UnmapBuffer(lightBufferHandle_.GetHandle());
154         }
155     }
156 }
157 
158 // for plugin / factory interface
Create()159 RENDER_NS::IRenderNode* RenderNodeDefaultLights::Create()
160 {
161     return new RenderNodeDefaultLights();
162 }
163 
Destroy(IRenderNode * instance)164 void RenderNodeDefaultLights::Destroy(IRenderNode* instance)
165 {
166     delete static_cast<RenderNodeDefaultLights*>(instance);
167 }
168 CORE3D_END_NAMESPACE()
169