• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_weather_simulation.h"
17 
18 #include <3d/render/intf_render_data_store_default_scene.h>
19 #include <3d/render/intf_render_node_scene_util.h>
20 #include <base/math/mathf.h>
21 #include <base/math/vector.h>
22 #include <core/log.h>
23 #include <render/datastore/intf_render_data_store.h>
24 #include <render/datastore/intf_render_data_store_manager.h>
25 #include <render/datastore/intf_render_data_store_pod.h>
26 #include <render/datastore/render_data_store_render_pods.h>
27 #include <render/device/intf_gpu_resource_manager.h>
28 #include <render/device/intf_shader_manager.h>
29 #include <render/namespace.h>
30 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
31 #include <render/nodecontext/intf_node_context_pso_manager.h>
32 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
33 #include <render/nodecontext/intf_render_command_list.h>
34 #include <render/nodecontext/intf_render_node_context_manager.h>
35 #include <render/nodecontext/intf_render_node_parser_util.h>
36 #include <render/nodecontext/intf_render_node_util.h>
37 
38 #include "3d/shaders/common/water_ripple_common.h"
39 
40 CORE3D_BEGIN_NAMESPACE()
41 using namespace BASE_NS;
42 using namespace RENDER_NS;
43 
InitNode(IRenderNodeContextManager & renderNodeContextMgr)44 void RenderNodeWeatherSimulation ::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
45 {
46     renderNodeContextMgr_ = &renderNodeContextMgr;
47     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
48     ParseRenderNodeInputs();
49 
50     auto& shaderMgr = renderNodeContextMgr.GetShaderManager();
51     const auto& renderNodeUtil = renderNodeContextMgr.GetRenderNodeUtil();
52     if (!shaderMgr.IsValid(shader_) || !shaderMgr.IsValid(initShader_)) {
53         CORE_LOG_E("RenderNodeRippleSimulation needs a valid shader handle");
54     }
55 
56     // simulate shader
57     {
58         pipelineLayout_ = renderNodeContextMgr.GetRenderNodeUtil().CreatePipelineLayout(shader_);
59         psoHandle_ = renderNodeContextMgr.GetPsoManager().GetComputePsoHandle(shader_, pipelineLayout_, {});
60 
61         {
62             const DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(pipelineLayout_);
63             renderNodeContextMgr.GetDescriptorSetManager().ResetAndReserve(dc);
64         }
65 
66         // create pipeline descriptor set
67         pipelineDescriptorSetBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineLayout_);
68     }
69 
70     // initialization shader
71     {
72         initPipelineLayout_ = renderNodeContextMgr.GetRenderNodeUtil().CreatePipelineLayout(initShader_);
73         initPsoHandle_ = renderNodeContextMgr.GetPsoManager().GetComputePsoHandle(initShader_, initPipelineLayout_, {});
74 
75         {
76             const DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(initPipelineLayout_);
77             renderNodeContextMgr.GetDescriptorSetManager().ResetAndReserve(dc);
78         }
79 
80         // create pipeline descriptor set
81         initPipelineDescriptorSetBinder_ = renderNodeUtil.CreatePipelineDescriptorSetBinder(initPipelineLayout_);
82     }
83 
84     defaultMaterialSam_ = gpuResourceMgr.GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
85     rippleTextureHandle_ = gpuResourceMgr.GetImageHandle("RIPPLE_RENDER_NODE_TEXTURE_0");
86     rippleTextureHandle1_ = gpuResourceMgr.GetImageHandle("RIPPLE_RENDER_NODE_TEXTURE_1");
87     rippleInputArgsBuffer_ = gpuResourceMgr.GetBufferHandle("RIPPLE_RENDER_NODE_INPUTBUFFER");
88 }
89 
PreExecuteFrame()90 void RenderNodeWeatherSimulation ::PreExecuteFrame()
91 {
92     // re-create needed gpu resources
93 }
94 
ExecuteFrame(IRenderCommandList & cmdList)95 void RenderNodeWeatherSimulation::ExecuteFrame(IRenderCommandList& cmdList)
96 {
97     const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
98     dataStoreWeather_ =
99         static_cast<RenderDataStoreWeather*>(renderDataStoreMgr.GetRenderDataStore("RenderDataStoreWeather"));
100     const IRenderDataStoreDefaultScene* dataStoreScene = static_cast<CORE3D_NS::IRenderDataStoreDefaultScene*>(
101         renderDataStoreMgr.GetRenderDataStore("RenderDataStoreDefaultScene"));
102     if ((!dataStoreWeather_) || (!dataStoreScene)) {
103         return;
104     }
105 
106     if (!RenderHandleUtil::IsValid(shader_)) {
107         return; // invalid shader
108     }
109 
110     if (!areTextureInit) {
111         InitializeRippleBuffers(cmdList);
112         areTextureInit = true;
113         return;
114     }
115 
116     const auto& effectData = dataStoreWeather_->GetWaterEffectData();
117     if (effectData.empty()) {
118         return;
119     }
120 
121     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
122     const auto TextureImageDesc = gpuResourceMgr.GetImageDescriptor(rippleTextureHandle_);
123 
124     const auto scene = dataStoreScene->GetScene();
125     {
126         auto& pipelineDescriptorSetBinder = *pipelineDescriptorSetBinder_;
127         pipelineDescriptorSetBinder.ClearBindings();
128 
129         // bind the input args buffer
130         {
131             BindableBuffer bindable;
132             bindable.handle = rippleInputArgsBuffer_;
133             bindable.byteOffset = 0;
134             bindable.byteSize = sizeof(DefaultWaterRippleDataStruct);
135             pipelineDescriptorSetBinder.BindBuffer(0, 0, bindable);
136         }
137 
138         // bind the ripple storage src texture
139         {
140             BindableImage bindable;
141             if (pingPongIdx == 0) {
142                 bindable.handle = rippleTextureHandle_;
143             } else {
144                 bindable.handle = rippleTextureHandle1_;
145             }
146             pipelineDescriptorSetBinder.BindImage(0, 1, bindable);
147         }
148 
149         // bind the ripple storage dst texture
150         {
151             BindableImage bindable;
152             if (pingPongIdx == 1) {
153                 bindable.handle = rippleTextureHandle_;
154             } else {
155                 bindable.handle = rippleTextureHandle1_;
156             }
157             pipelineDescriptorSetBinder.BindImage(0, 2, bindable);
158         }
159 
160         const auto descHandle = pipelineDescriptorSetBinder_->GetDescriptorSetHandle(0);
161         const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(0);
162         cmdList.UpdateDescriptorSet(descHandle, bindings);
163     }
164 
165     cmdList.BindPipeline(psoHandle_);
166 
167     // bind all sets
168     {
169         const auto descHandles = pipelineDescriptorSetBinder_->GetDescriptorSetHandles();
170         cmdList.BindDescriptorSets(0, descHandles);
171     }
172 
173     BASE_NS::Math::Vec4 pc { scene.deltaTime / 1000.0f, 0, 0, 0 };
174 
175     // NOTE: fix the hard-coded
176     // Add plane offcet to pc
177     pc.z = effectData[0U].planeOffset.x;
178     pc.w = effectData[0U].planeOffset.y;
179 
180     cmdList.PushConstant(pipelineLayout_.pushConstant, arrayviewU8(pc).data());
181 
182     // dispatch compute shader
183     if (TextureImageDesc.width > 1u && TextureImageDesc.height > 1u) {
184         const Math::UVec3 targetSize = { TextureImageDesc.width, TextureImageDesc.height, 1 };
185 
186         const uint32_t tgcX = (targetSize.x + WATER_RIPPLE_TGS - 1u) / WATER_RIPPLE_TGS;
187         const uint32_t tgcY = (targetSize.y + WATER_RIPPLE_TGS - 1u) / WATER_RIPPLE_TGS;
188 
189         cmdList.Dispatch(tgcX, tgcY, 1);
190     } else {
191         CORE_LOG_W("RenderNodeRippleSimulation: dispatchResources needed");
192     }
193 
194     {
195         // add barrier for memory
196         constexpr GeneralBarrier src { AccessFlagBits::CORE_ACCESS_SHADER_WRITE_BIT,
197             PipelineStageFlagBits::CORE_PIPELINE_STAGE_COMPUTE_SHADER_BIT };
198         constexpr GeneralBarrier dst { AccessFlagBits::CORE_ACCESS_INDIRECT_COMMAND_READ_BIT |
199                                            AccessFlagBits::CORE_ACCESS_SHADER_WRITE_BIT,
200             PipelineStageFlagBits::CORE_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
201                 PipelineStageFlagBits::CORE_PIPELINE_STAGE_COMPUTE_SHADER_BIT };
202 
203         cmdList.CustomMemoryBarrier(src, dst);
204         cmdList.AddCustomBarrierPoint();
205     }
206 
207     // copy from 1 to 0
208     if (pingPongIdx == 0U) {
209         ImageCopy imageCopy;
210         imageCopy.srcSubresource = { RENDER_NS::ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1u };
211         imageCopy.srcOffset = { 0, 0, 0 };
212         imageCopy.dstSubresource = { RENDER_NS::ImageAspectFlagBits::CORE_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1u };
213         imageCopy.dstOffset = { 0, 0, 0 };
214         imageCopy.extent = { TextureImageDesc.width, TextureImageDesc.height, 1u };
215 
216         cmdList.CopyImageToImage(rippleTextureHandle1_, rippleTextureHandle_, imageCopy);
217     }
218 
219     pingPongIdx = (pingPongIdx == 0U) ? 1U : 0U;
220 }
221 
InitializeRippleBuffers(RENDER_NS::IRenderCommandList & cmdList)222 void RenderNodeWeatherSimulation::InitializeRippleBuffers(RENDER_NS::IRenderCommandList& cmdList)
223 {
224     const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
225     const auto TextureImageDesc = gpuResourceMgr.GetImageDescriptor(rippleTextureHandle_);
226 
227     {
228         auto& pipelineDescriptorSetBinder = *initPipelineDescriptorSetBinder_;
229         pipelineDescriptorSetBinder.ClearBindings();
230 
231         // bind the input args buffer
232         {
233             BindableBuffer bindable;
234             bindable.handle = rippleInputArgsBuffer_;
235             bindable.byteOffset = 0;
236             bindable.byteSize = sizeof(DefaultWaterRippleDataStruct);
237             pipelineDescriptorSetBinder.BindBuffer(0, 0, bindable);
238         }
239 
240         // bind the ripple storage src texture
241         {
242             BindableImage bindable;
243             bindable.handle = rippleTextureHandle_;
244             bindable.samplerHandle = rippleTextureHandle_;
245             pipelineDescriptorSetBinder.BindImage(0, 1, bindable);
246         }
247 
248         // bind the ripple storage dst texture
249         {
250             BindableImage bindable;
251             bindable.handle = rippleTextureHandle1_;
252             bindable.samplerHandle = rippleTextureHandle1_;
253             pipelineDescriptorSetBinder.BindImage(0, 2, bindable);
254         }
255 
256         const auto descHandle = initPipelineDescriptorSetBinder_->GetDescriptorSetHandle(0);
257         const auto bindings = initPipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(0);
258         cmdList.UpdateDescriptorSet(descHandle, bindings);
259     }
260 
261     cmdList.BindPipeline(initPsoHandle_);
262 
263     // bind all sets
264     {
265         const auto descHandles = initPipelineDescriptorSetBinder_->GetDescriptorSetHandles();
266         cmdList.BindDescriptorSets(0, descHandles);
267     }
268 
269     // dispatch compute shader
270     if (TextureImageDesc.width > 1u && TextureImageDesc.height > 1u) {
271         const Math::UVec3 targetSize = { TextureImageDesc.width, TextureImageDesc.height, 1 };
272 
273         const uint32_t tgcX = (targetSize.x + WATER_RIPPLE_TGS - 1u) / WATER_RIPPLE_TGS;
274         const uint32_t tgcY = (targetSize.y + WATER_RIPPLE_TGS - 1u) / WATER_RIPPLE_TGS;
275 
276         cmdList.Dispatch(tgcX, tgcY, 1);
277     } else {
278         CORE_LOG_W("RenderNodeRippleSimulation: dispatchResources needed");
279     }
280 
281     {
282         // add barrier for memory
283         constexpr GeneralBarrier src { AccessFlagBits::CORE_ACCESS_SHADER_WRITE_BIT,
284             PipelineStageFlagBits::CORE_PIPELINE_STAGE_COMPUTE_SHADER_BIT };
285         constexpr GeneralBarrier dst { AccessFlagBits::CORE_ACCESS_INDIRECT_COMMAND_READ_BIT |
286                                            AccessFlagBits::CORE_ACCESS_SHADER_WRITE_BIT,
287             PipelineStageFlagBits::CORE_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
288                 PipelineStageFlagBits::CORE_PIPELINE_STAGE_COMPUTE_SHADER_BIT };
289 
290         cmdList.CustomMemoryBarrier(src, dst);
291         cmdList.AddCustomBarrierPoint();
292     }
293 }
294 
ParseRenderNodeInputs()295 void RenderNodeWeatherSimulation ::ParseRenderNodeInputs()
296 {
297     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
298     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
299     jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
300     jsonInputs_.dispatchResources = parserUtil.GetInputResources(jsonVal, "dispatchResources");
301     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
302     jsonInputs_.renderDataStoreSpecialization =
303         parserUtil.GetRenderDataStore(jsonVal, "renderDataStoreShaderSpecialization");
304 
305     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
306 
307     // simulate shader
308     {
309         const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
310         shader_ = shaderMgr.GetShaderHandle(shaderName);
311     }
312 
313     // init shader
314     {
315         initShader_ = shaderMgr.GetShaderHandle("3dshaders://computeshader/water_ripple_initialize.shader");
316     }
317 
318     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
319     jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
320     jsonInputs_.hasChangeableDispatchHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.dispatchResources);
321 }
322 
323 // for plugin / factory interface
Create()324 IRenderNode* RenderNodeWeatherSimulation ::Create()
325 {
326     return new RenderNodeWeatherSimulation();
327 }
328 
Destroy(IRenderNode * instance)329 void RenderNodeWeatherSimulation::Destroy(IRenderNode* instance)
330 {
331     delete static_cast<RenderNodeWeatherSimulation*>(instance);
332 }
333 CORE3D_END_NAMESPACE()
334