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