• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_motion_blur.h"
17 
18 #include <render/device/intf_gpu_resource_manager.h>
19 #include <render/device/intf_shader_manager.h>
20 #include <render/device/pipeline_state_desc.h>
21 #include <render/namespace.h>
22 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
23 #include <render/nodecontext/intf_node_context_pso_manager.h>
24 #include <render/nodecontext/intf_render_command_list.h>
25 #include <render/nodecontext/intf_render_node_context_manager.h>
26 #include <render/nodecontext/intf_render_node_util.h>
27 
28 #include "default_engine_constants.h"
29 #include "device/gpu_resource_handle_util.h"
30 #include "render/shaders/common/render_post_process_structs_common.h"
31 
32 using namespace BASE_NS;
33 
34 RENDER_BEGIN_NAMESPACE()
35 namespace {
36 // needs to match motion blur shaders
37 constexpr uint32_t CORE_SPREAD_TYPE_NEIGHBORHOOD { 0U };
38 constexpr uint32_t CORE_SPREAD_TYPE_HORIZONTAL { 1U };
39 constexpr uint32_t CORE_SPREAD_TYPE_VERTICAL { 2U };
40 constexpr uint32_t VELOCITY_TILE_SIZE { 8U };
41 
42 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
43 
44 constexpr uint32_t MAX_PASS_COUNT { 3u };
45 } // namespace
46 
Init(IRenderNodeContextManager & renderNodeContextMgr,const MotionBlurInfo & motionBlurInfo)47 void RenderMotionBlur::Init(IRenderNodeContextManager& renderNodeContextMgr, const MotionBlurInfo& motionBlurInfo)
48 {
49     motionBlurInfo_ = motionBlurInfo;
50     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr.GetShaderManager();
51     {
52         renderData_ = {};
53         renderData_.shader = shaderMgr.GetShaderHandle("rendershaders://shader/fullscreen_motion_blur.shader");
54         renderData_.pipelineLayout = shaderMgr.GetReflectionPipelineLayout(renderData_.shader);
55         const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(renderData_.shader);
56         renderData_.pso = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(renderData_.shader, graphicsState,
57             renderData_.pipelineLayout, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
58     }
59     {
60         renderTileMaxData_ = {};
61         renderTileMaxData_.shader =
62             shaderMgr.GetShaderHandle("rendershaders://shader/fullscreen_motion_blur_tile_max.shader");
63         renderTileMaxData_.pipelineLayout = shaderMgr.GetReflectionPipelineLayout(renderTileMaxData_.shader);
64         const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(renderTileMaxData_.shader);
65         renderTileMaxData_.pso = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(renderTileMaxData_.shader,
66             graphicsState, renderTileMaxData_.pipelineLayout, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
67     }
68     {
69         renderTileNeighborData_ = {};
70         renderTileNeighborData_.shader =
71             shaderMgr.GetShaderHandle("rendershaders://shader/fullscreen_motion_blur_tile_neighborhood.shader");
72         renderTileNeighborData_.pipelineLayout = shaderMgr.GetReflectionPipelineLayout(renderTileNeighborData_.shader);
73         const RenderHandle graphicsState =
74             shaderMgr.GetGraphicsStateHandleByShaderHandle(renderTileNeighborData_.shader);
75         const ShaderSpecializationConstantView specView =
76             shaderMgr.GetReflectionSpecialization(renderTileNeighborData_.shader);
77         {
78             const uint32_t specFlags[] = { CORE_SPREAD_TYPE_NEIGHBORHOOD };
79             const ShaderSpecializationConstantDataView specDataView { specView.constants, specFlags };
80             renderTileNeighborData_.psoNeighborhood = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
81                 renderTileNeighborData_.shader, graphicsState, renderTileNeighborData_.pipelineLayout, {}, specDataView,
82                 { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
83         }
84         {
85             const uint32_t specFlags[] = { CORE_SPREAD_TYPE_HORIZONTAL };
86             const ShaderSpecializationConstantDataView specDataView { specView.constants, specFlags };
87             renderTileNeighborData_.psoHorizontal = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
88                 renderTileNeighborData_.shader, graphicsState, renderTileNeighborData_.pipelineLayout, {}, specDataView,
89                 { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
90         }
91         {
92             const uint32_t specFlags[] = { CORE_SPREAD_TYPE_VERTICAL };
93             const ShaderSpecializationConstantDataView specDataView { specView.constants, specFlags };
94             renderTileNeighborData_.psoVertical = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
95                 renderTileNeighborData_.shader, graphicsState, renderTileNeighborData_.pipelineLayout, {}, specDataView,
96                 { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
97         }
98     }
99     samplerHandle_ = renderNodeContextMgr.GetGpuResourceManager().GetSamplerHandle(
100         DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
101     samplerNearestHandle_ = renderNodeContextMgr.GetGpuResourceManager().GetSamplerHandle(
102         DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_NEAREST_CLAMP);
103     {
104         constexpr uint32_t globalSet = 0u;
105         constexpr uint32_t localSet = 1u;
106 
107         INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr.GetDescriptorSetManager();
108         {
109             const auto& bindings = renderData_.pipelineLayout.descriptorSetLayouts[globalSet].bindings;
110             const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
111             globalSet0_ = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
112         }
113         {
114             const auto& bindings = renderData_.pipelineLayout.descriptorSetLayouts[localSet].bindings;
115             const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
116             localSet1_ = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
117         }
118         {
119             const auto& bindings = renderTileMaxData_.pipelineLayout.descriptorSetLayouts[localSet].bindings;
120             const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
121             localTileMaxSet1_ = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
122         }
123         {
124             const auto& bindings = renderTileNeighborData_.pipelineLayout.descriptorSetLayouts[localSet].bindings;
125             {
126                 const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
127                 localTileNeighborhoodSet1_[0U] = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
128             }
129             {
130                 const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
131                 localTileNeighborhoodSet1_[1U] = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
132             }
133         }
134     }
135 }
136 
PreExecute(IRenderNodeContextManager & renderNodeContextMgr,const MotionBlurInfo & blurInfo,const PostProcessConfiguration & ppConfig)137 void RenderMotionBlur::PreExecute(IRenderNodeContextManager& renderNodeContextMgr, const MotionBlurInfo& blurInfo,
138     const PostProcessConfiguration& ppConfig)
139 {
140     motionBlurInfo_ = blurInfo;
141 
142     if ((ppConfig.motionBlurConfiguration.quality == MotionBlurConfiguration::Quality::MEDIUM) ||
143         (ppConfig.motionBlurConfiguration.quality == MotionBlurConfiguration::Quality::HIGH)) {
144         const uint32_t compSizeX = (motionBlurInfo_.size.x + VELOCITY_TILE_SIZE - 1U) / VELOCITY_TILE_SIZE;
145         const uint32_t compSizeY = (motionBlurInfo_.size.y + VELOCITY_TILE_SIZE - 1U) / VELOCITY_TILE_SIZE;
146         if ((!tileVelocityImages_[0U]) || (tileImageSize_.x != compSizeX) || (tileImageSize_.y != compSizeY)) {
147             IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr.GetGpuResourceManager();
148             GpuImageDesc desc = renderNodeContextMgr.GetGpuResourceManager().GetImageDescriptor(blurInfo.velocity);
149             desc.engineCreationFlags =
150                 CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS | CORE_ENGINE_IMAGE_CREATION_RESET_STATE_ON_FRAME_BORDERS;
151             desc.usageFlags = CORE_IMAGE_USAGE_SAMPLED_BIT | CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
152             desc.mipCount = 1U;
153             desc.layerCount = 1U;
154             desc.width = compSizeX;
155             desc.height = compSizeY;
156             tileVelocityImages_[0U] = gpuResourceMgr.Create(tileVelocityImages_[0U], desc);
157             tileVelocityImages_[1U] = gpuResourceMgr.Create(tileVelocityImages_[1U], desc);
158 
159             tileImageSize_ = { compSizeX, compSizeY };
160         }
161     }
162 }
163 
Execute(IRenderNodeContextManager & renderNodeContextMgr,IRenderCommandList & cmdList,const MotionBlurInfo & blurInfo,const PostProcessConfiguration & ppConfig)164 void RenderMotionBlur::Execute(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList,
165     const MotionBlurInfo& blurInfo, const PostProcessConfiguration& ppConfig)
166 {
167     if (!RenderHandleUtil::IsGpuImage(blurInfo.output)) {
168         return;
169     }
170 
171     RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderMotionBlur", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
172 
173     // Update global descriptor set 0 for both passes
174     UpdateDescriptorSet0(cmdList, blurInfo);
175 
176     const RenderHandle velocity = blurInfo.velocity;
177     RenderHandle tileVelocity = blurInfo.velocity;
178     if ((ppConfig.motionBlurConfiguration.quality == MotionBlurConfiguration::Quality::MEDIUM) ||
179         (ppConfig.motionBlurConfiguration.quality == MotionBlurConfiguration::Quality::HIGH)) {
180         ExecuteTileVelocity(renderNodeContextMgr, cmdList, blurInfo);
181         const RenderHandle tv = GetTileVelocityForMotionBlur();
182         tileVelocity = RenderHandleUtil::IsValid(tv) ? tv : velocity;
183     }
184 
185     const auto& renderData = renderData_;
186 
187     RenderPass renderPass;
188     renderPass.renderPassDesc.attachmentCount = 1;
189     renderPass.renderPassDesc.renderArea = { 0, 0, motionBlurInfo_.size.x, motionBlurInfo_.size.y };
190     renderPass.renderPassDesc.subpassCount = 1;
191     renderPass.renderPassDesc.attachments[0].loadOp = CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
192     renderPass.renderPassDesc.attachments[0].storeOp = CORE_ATTACHMENT_STORE_OP_STORE;
193     renderPass.renderPassDesc.attachmentHandles[0] = blurInfo.output;
194     renderPass.subpassStartIndex = 0;
195     auto& subpass = renderPass.subpassDesc;
196     subpass.colorAttachmentCount = 1;
197     subpass.colorAttachmentIndices[0] = 0;
198 
199     cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
200     cmdList.BindPipeline(renderData.pso);
201 
202     RenderHandle sets[2u] {};
203     {
204         auto& binder = *globalSet0_;
205         sets[0u] = binder.GetDescriptorSetHandle();
206     }
207     {
208         auto& binder = *localSet1_;
209         binder.ClearBindings();
210         uint32_t binding = 0u;
211         binder.BindImage(binding++, blurInfo.input, samplerHandle_);
212         binder.BindImage(binding++, blurInfo.depth, samplerNearestHandle_);
213         binder.BindImage(binding++, velocity, samplerHandle_);
214         binder.BindImage(binding++, tileVelocity, samplerHandle_);
215         cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
216         sets[1u] = binder.GetDescriptorSetHandle();
217     }
218     cmdList.BindDescriptorSets(0u, sets);
219 
220     if (renderData.pipelineLayout.pushConstant.byteSize > 0) {
221         const auto fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
222         const auto fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
223         const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight }, {} };
224         cmdList.PushConstantData(renderData_.pipelineLayout.pushConstant, arrayviewU8(pc));
225     }
226 
227     // dynamic state
228     cmdList.SetDynamicStateViewport(renderNodeContextMgr.GetRenderNodeUtil().CreateDefaultViewport(renderPass));
229     cmdList.SetDynamicStateScissor(renderNodeContextMgr.GetRenderNodeUtil().CreateDefaultScissor(renderPass));
230 
231     cmdList.Draw(3u, 1u, 0u, 0u);
232     cmdList.EndRenderPass();
233 }
234 
ExecuteTileVelocity(IRenderNodeContextManager & renderNodeContextMgr,IRenderCommandList & cmdList,const MotionBlurInfo & blurInfo)235 void RenderMotionBlur::ExecuteTileVelocity(
236     IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList, const MotionBlurInfo& blurInfo)
237 {
238     if ((!RenderHandleUtil::IsGpuImage(blurInfo.output)) || (!tileVelocityImages_[0U])) {
239         return;
240     }
241 
242     RenderPass renderPass;
243     renderPass.renderPassDesc.attachmentCount = 1;
244     renderPass.renderPassDesc.renderArea = { 0, 0, tileImageSize_.x, tileImageSize_.y };
245     renderPass.renderPassDesc.subpassCount = 1;
246     renderPass.renderPassDesc.attachments[0].loadOp = CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
247     renderPass.renderPassDesc.attachments[0].storeOp = CORE_ATTACHMENT_STORE_OP_STORE;
248     renderPass.subpassStartIndex = 0;
249     auto& subpass = renderPass.subpassDesc;
250     subpass.colorAttachmentCount = 1;
251     subpass.colorAttachmentIndices[0] = 0;
252 
253     const RenderHandle vel0 = tileVelocityImages_[0U].GetHandle();
254     const RenderHandle vel1 = tileVelocityImages_[1U].GetHandle();
255 
256     const ViewportDesc viewport = renderNodeContextMgr.GetRenderNodeUtil().CreateDefaultViewport(renderPass);
257     const ScissorDesc scissor = renderNodeContextMgr.GetRenderNodeUtil().CreateDefaultScissor(renderPass);
258 
259     const auto fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
260     const auto fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
261     const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight }, {} };
262 
263     RenderHandle sets[2u] {};
264     {
265         auto& binder = *globalSet0_;
266         sets[0u] = binder.GetDescriptorSetHandle();
267     }
268 
269     // tile max pass
270     {
271         const auto& renderData = renderTileMaxData_;
272         renderPass.renderPassDesc.attachmentHandles[0] = vel0;
273 
274         cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
275         cmdList.BindPipeline(renderData.pso);
276 
277         {
278             auto& binder = *localTileMaxSet1_;
279             binder.ClearBindings();
280             binder.BindImage(0U, blurInfo.velocity, samplerHandle_);
281             cmdList.UpdateDescriptorSet(
282                 binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
283             sets[1u] = binder.GetDescriptorSetHandle();
284         }
285         cmdList.BindDescriptorSets(0u, sets);
286 
287         if (renderData.pipelineLayout.pushConstant.byteSize > 0) {
288             cmdList.PushConstant(renderData.pipelineLayout.pushConstant, arrayviewU8(pc).data());
289         }
290 
291         // dynamic state
292         cmdList.SetDynamicStateViewport(viewport);
293         cmdList.SetDynamicStateScissor(scissor);
294 
295         cmdList.Draw(3U, 1U, 0U, 0U);
296         cmdList.EndRenderPass();
297     }
298     // tile neighborhood pass
299     {
300         const auto& renderData = renderTileNeighborData_;
301         {
302             const RenderHandle pso =
303                 renderTileNeighborData_.doublePass ? renderData.psoHorizontal : renderData.psoNeighborhood;
304 
305             renderPass.renderPassDesc.attachmentHandles[0] = vel1;
306 
307             cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
308             cmdList.BindPipeline(pso);
309 
310             {
311                 auto& binder = *localTileNeighborhoodSet1_[0U];
312                 binder.ClearBindings();
313                 binder.BindImage(0U, vel0, samplerHandle_);
314                 cmdList.UpdateDescriptorSet(
315                     binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
316                 sets[1u] = binder.GetDescriptorSetHandle();
317             }
318             cmdList.BindDescriptorSets(0u, sets);
319 
320             if (renderData.pipelineLayout.pushConstant.byteSize > 0) {
321                 cmdList.PushConstant(renderData.pipelineLayout.pushConstant, arrayviewU8(pc).data());
322             }
323 
324             // dynamic state
325             cmdList.SetDynamicStateViewport(viewport);
326             cmdList.SetDynamicStateScissor(scissor);
327 
328             cmdList.Draw(3U, 1U, 0U, 0U);
329             cmdList.EndRenderPass();
330         }
331         if (renderTileNeighborData_.doublePass) {
332             const RenderHandle pso = renderData.psoVertical;
333 
334             renderPass.renderPassDesc.attachmentHandles[0] = vel0;
335 
336             cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
337             cmdList.BindPipeline(pso);
338 
339             {
340                 auto& binder = *localTileNeighborhoodSet1_[1U];
341                 binder.ClearBindings();
342                 binder.BindImage(0U, vel1, samplerHandle_);
343                 cmdList.UpdateDescriptorSet(
344                     binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
345                 sets[1u] = binder.GetDescriptorSetHandle();
346             }
347             cmdList.BindDescriptorSets(0u, sets);
348 
349             if (renderData.pipelineLayout.pushConstant.byteSize > 0) {
350                 cmdList.PushConstant(renderData.pipelineLayout.pushConstant, arrayviewU8(pc).data());
351             }
352 
353             // dynamic state
354             cmdList.SetDynamicStateViewport(viewport);
355             cmdList.SetDynamicStateScissor(scissor);
356 
357             cmdList.Draw(3U, 1U, 0U, 0U);
358             cmdList.EndRenderPass();
359         }
360     }
361 }
362 
UpdateDescriptorSet0(IRenderCommandList & cmdList,const MotionBlurInfo & blurInfo)363 void RenderMotionBlur::UpdateDescriptorSet0(IRenderCommandList& cmdList, const MotionBlurInfo& blurInfo)
364 {
365     const RenderHandle ubo = blurInfo.globalUbo;
366     auto& binder = *globalSet0_;
367     binder.ClearBindings();
368     uint32_t binding = 0u;
369     binder.BindBuffer(binding++, ubo, 0u);
370     binder.BindBuffer(binding++, ubo, blurInfo.globalUboByteOffset, sizeof(GlobalPostProcessStruct));
371     cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
372 }
373 
GetTileVelocityForMotionBlur() const374 RenderHandle RenderMotionBlur::GetTileVelocityForMotionBlur() const
375 {
376     return renderTileNeighborData_.doublePass ? tileVelocityImages_[0U].GetHandle()
377                                               : tileVelocityImages_[1U].GetHandle();
378 }
379 
GetDescriptorCounts()380 DescriptorCounts RenderMotionBlur::GetDescriptorCounts()
381 {
382     // expected high max mip count
383     return DescriptorCounts { {
384         { CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_PASS_COUNT },
385         { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u * MAX_PASS_COUNT },
386     } };
387 }
388 RENDER_END_NAMESPACE()
389