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