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_dotfield_render.h"
17 
18 #include <3d/implementation_uids.h>
19 #include <3d/namespace.h>
20 #include <3d/render/default_material_constants.h>
21 #include <3d/render/intf_render_data_store_default_scene.h>
22 #include <3d/render/intf_render_node_scene_util.h>
23 #include <base/containers/array_view.h>
24 #include <base/containers/string.h>
25 #include <base/containers/vector.h>
26 #include <base/math/matrix_util.h>
27 #include <base/math/vector.h>
28 #include <core/log.h>
29 #include <render/datastore/intf_render_data_store_manager.h>
30 #include <render/datastore/intf_render_data_store_pod.h>
31 #include <render/datastore/render_data_store_render_pods.h>
32 #include <render/device/intf_gpu_resource_manager.h>
33 #include <render/device/intf_shader_manager.h>
34 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
35 #include <render/nodecontext/intf_node_context_pso_manager.h>
36 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
37 #include <render/nodecontext/intf_render_command_list.h>
38 #include <render/nodecontext/intf_render_node_context_manager.h>
39 #include <render/nodecontext/intf_render_node_parser_util.h>
40 #include <render/nodecontext/intf_render_node_util.h>
41 #include "render_data_store_default_dotfield.h"
42 
43 namespace {
44 #include "app/shaders/common/dotfield_common.h"
45 #include "app/shaders/common/dotfield_struct_common.h"
46 } // namespace
47 
48 #include <algorithm>
49 using namespace BASE_NS;
50 using namespace CORE_NS;
51 using namespace RENDER_NS;
52 using namespace CORE3D_NS;
53 
54 namespace Dotfield {
55 namespace {
56 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
57 constexpr string_view DEFAULT_DOTFIELD_RENDER_DATA_STORE_NAME_POST_FIX = "RenderDataStoreDefaultDotfield";
58 } // namespace
59 
InitNode(IRenderNodeContextManager& renderNodeContextMgr)60 void RenderNodeDotfieldRender::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
61 {
62     renderNodeContextMgr_ = &renderNodeContextMgr;
63     ParseRenderNodeInputs();
64 
65     shaderToPsoData_.clear();
66 
67     const auto& renderNodeUtil = renderNodeContextMgr.GetRenderNodeUtil();
68     inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
69     renderPass_ = renderNodeUtil.CreateRenderPass(inputRenderPass_);
70     if (auto* renderNodeSceneUtil = CORE_NS::GetInstance<CORE3D_NS::IRenderNodeSceneUtil>(
71             *(renderNodeContextMgr_->GetRenderContext().GetInterface<IClassRegister>()),
72             CORE3D_NS::UID_RENDER_NODE_SCENE_UTIL);
73         renderNodeSceneUtil) {
74         const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData();
75         stores_ = renderNodeSceneUtil->GetSceneRenderDataStores(
76             renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName);
77     }
78     cameraUniformBufferHandle_ = renderNodeContextMgr.GetGpuResourceManager().GetBufferHandle(
79         stores_.dataStoreNameScene + DefaultMaterialCameraConstants::CAMERA_DATA_BUFFER_NAME);
80 
81     INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr.GetDescriptorSetManager();
82     {
83         const DescriptorCounts dc { {
84             { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u },
85         } };
86         descriptorSetMgr.ResetAndReserve(dc);
87     }
88     {
89         const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr.GetShaderManager();
90         shaderHandle_ = shaderMgr.GetShaderHandle("dotfieldshaders://shader/default_material_dotfield.shader");
91         const RenderHandle plHandle =
92             shaderMgr.GetPipelineLayoutHandle("dotfieldpipelinelayouts://default_material_dotfield.shaderpl");
93         const PipelineLayout pipelineLayout = shaderMgr.GetPipelineLayout(plHandle);
94 
95         CORE_ASSERT(pipelineLayout.pushConstant.byteSize == sizeof(DotfieldMaterialPushConstantStruct));
96         const uint32_t set = 0;
97         const RenderHandle descriptorSetHandle = descriptorSetMgr.CreateDescriptorSet(set, pipelineLayout);
98         binders_.set0 = descriptorSetMgr.CreateDescriptorSetBinder(
99             descriptorSetHandle, pipelineLayout.descriptorSetLayouts[set].bindings);
100     }
101 }
102 
ParseRenderNodeInputs()103 void RenderNodeDotfieldRender::ParseRenderNodeInputs()
104 {
105     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
106     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
107     jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
108 }
109 
PreExecuteFrame()110 void RenderNodeDotfieldRender::PreExecuteFrame(){}
111 
ExecuteFrame(IRenderCommandList& cmdList)112 void RenderNodeDotfieldRender::ExecuteFrame(IRenderCommandList& cmdList)
113 {
114     cmdList.BeginRenderPass(renderPass_.renderPassDesc, renderPass_.subpassStartIndex, renderPass_.subpassDesc);
115 
116     RenderData(*renderNodeContextMgr_, cmdList);
117 
118     cmdList.EndRenderPass();
119 }
120 
RenderData(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList)121 void RenderNodeDotfieldRender::RenderData(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList)
122 {
123     const RenderDataStoreDefaultDotfield* dataStore = static_cast<RenderDataStoreDefaultDotfield*>(
124         renderNodeContextMgr.GetRenderDataStoreManager().GetRenderDataStore(
125             stores_.dataStoreNamePrefix + DEFAULT_DOTFIELD_RENDER_DATA_STORE_NAME_POST_FIX.data()));
126     if (!dataStore) {
127         return;
128     }
129 
130     const auto& dotfieldPrimitives = dataStore->GetDotfieldPrimitives();
131     if (dotfieldPrimitives.empty()) {
132         return;
133     }
134 
135     const auto& bufferData = dataStore->GetBufferData();
136 
137     const ViewportDesc viewportDesc = renderNodeContextMgr.GetRenderNodeUtil().CreateDefaultViewport(renderPass_);
138     cmdList.SetDynamicStateViewport(viewportDesc);
139 
140     const ScissorDesc scissorDesc = renderNodeContextMgr.GetRenderNodeUtil().CreateDefaultScissor(renderPass_);
141     cmdList.SetDynamicStateScissor(scissorDesc);
142 
143     auto& binder0 = *binders_.set0;
144     binder0.BindBuffer(0, cameraUniformBufferHandle_, 0);
145     cmdList.UpdateDescriptorSet(binder0.GetDescriptorSetHandle(), binder0.GetDescriptorSetLayoutBindingResources());
146 
147     const uint32_t primitiveCount = static_cast<uint32_t>(dotfieldPrimitives.size());
148     const uint32_t currFrameIndex = bufferData.currFrameIndex;
149 
150     for (uint32_t idx = 0; idx < primitiveCount; ++idx) {
151         const auto& dotfieldPrimitive = dotfieldPrimitives[idx];
152         const auto& currEffect = bufferData.buffers[idx];
153 
154         const PsoData psoData = GetPsoData(renderNodeContextMgr, shaderHandle_);
155         cmdList.BindPipeline(psoData.psoHandle);
156 
157         if (idx == 0) {
158             cmdList.BindDescriptorSet(0, binder0.GetDescriptorSetHandle());
159         }
160 
161         float time = dataStore->GetTime();
162         const DotfieldMaterialPushConstantStruct pc = { { dotfieldPrimitive.size.x, dotfieldPrimitive.size.y, idx, 0 },
163             { time, dotfieldPrimitive.pointScale, 0, 0 }, dotfieldPrimitive.colors, dotfieldPrimitive.matrix };
164         cmdList.PushConstant(psoData.pushConstant, reinterpret_cast<const uint8_t*>(&pc));
165 
166         const VertexBuffer vb[] = {
167             { currEffect.dataBuffer[currFrameIndex].GetHandle(), 0 },
168         };
169         cmdList.BindVertexBuffers(array_view(vb));
170 
171         cmdList.Draw(1, dotfieldPrimitive.size.x * dotfieldPrimitive.size.y, 0, 0);
172     }
173 }
174 
GetPsoData( IRenderNodeContextManager& renderNodeContextMgr, const RenderHandle& shaderHandle)175 RenderNodeDotfieldRender::PsoData RenderNodeDotfieldRender::GetPsoData(
176     IRenderNodeContextManager& renderNodeContextMgr, const RenderHandle& shaderHandle)
177 {
178     if (const auto iter = shaderToPsoData_.find(shaderHandle.id); iter != shaderToPsoData_.cend()) {
179         return iter->second;
180     } else { // new
181         const auto& shaderMgr = renderNodeContextMgr.GetShaderManager();
182         const RenderHandle plHandle = shaderMgr.GetPipelineLayoutHandleByShaderHandle(shaderHandle);
183         const PipelineLayout pipelineLayout = shaderMgr.GetPipelineLayout(plHandle);
184         const RenderHandle vidHandle = shaderMgr.GetVertexInputDeclarationHandleByShaderHandle(shaderHandle);
185         const VertexInputDeclarationView vertexInputDeclaration = shaderMgr.GetVertexInputDeclarationView(vidHandle);
186         const PipelineLayout& reflPipelineLayout = shaderMgr.GetReflectionPipelineLayout(shaderHandle);
187         const RenderHandle graphicsStateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(shaderHandle);
188 
189         const RenderHandle psoHandle =
190             renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(shaderHandle, graphicsStateHandle, pipelineLayout,
191                 vertexInputDeclaration, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
192         const PsoData psoData = { psoHandle, reflPipelineLayout.pushConstant };
193         shaderToPsoData_[shaderHandle.id] = psoData;
194         return psoData;
195     }
196 }
197 
Create()198 IRenderNode* RenderNodeDotfieldRender::Create()
199 {
200     return new RenderNodeDotfieldRender();
201 }
202 
Destroy(IRenderNode* instance)203 void RenderNodeDotfieldRender::Destroy(IRenderNode* instance)
204 {
205     delete (RenderNodeDotfieldRender*)instance;
206 }
207 } // namespace Dotfield
208