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_post_process_motion_blur_node.h"
17
18 #include <base/containers/fixed_string.h>
19 #include <base/containers/unordered_map.h>
20 #include <base/math/vector.h>
21 #include <core/property/property_types.h>
22 #include <core/property_tools/property_api_impl.inl>
23 #include <render/datastore/intf_render_data_store_manager.h>
24 #include <render/datastore/intf_render_data_store_pod.h>
25 #include <render/datastore/render_data_store_render_pods.h>
26 #include <render/device/intf_gpu_resource_manager.h>
27 #include <render/device/intf_shader_manager.h>
28 #include <render/namespace.h>
29 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
30 #include <render/nodecontext/intf_node_context_pso_manager.h>
31 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
32 #include <render/nodecontext/intf_render_command_list.h>
33 #include <render/nodecontext/intf_render_node_context_manager.h>
34 #include <render/nodecontext/intf_render_node_util.h>
35 #include <render/property/property_types.h>
36
37 #include "datastore/render_data_store_pod.h"
38 #include "datastore/render_data_store_post_process.h"
39 #include "default_engine_constants.h"
40 #include "device/gpu_resource_handle_util.h"
41 #include "render_post_process_motion_blur.h"
42 #include "util/log.h"
43
44 // shaders
45 #include <render/shaders/common/render_post_process_structs_common.h>
46
47 using namespace BASE_NS;
48 using namespace CORE_NS;
49 using namespace RENDER_NS;
50
51 CORE_BEGIN_NAMESPACE()
52 DATA_TYPE_METADATA(RenderPostProcessMotionBlurNode::NodeInputs, MEMBER_PROPERTY(input, "input", 0),
53 MEMBER_PROPERTY(velocity, "velocity", 0), MEMBER_PROPERTY(depth, "depth", 0))
54 DATA_TYPE_METADATA(RenderPostProcessMotionBlurNode::NodeOutputs, MEMBER_PROPERTY(output, "output", 0))
55 CORE_END_NAMESPACE()
56
57 RENDER_BEGIN_NAMESPACE()
58 namespace {
59 constexpr uint32_t CORE_SPREAD_TYPE_NEIGHBORHOOD { 0U };
60 constexpr uint32_t CORE_SPREAD_TYPE_HORIZONTAL { 1U };
61 constexpr uint32_t CORE_SPREAD_TYPE_VERTICAL { 2U };
62 constexpr uint32_t VELOCITY_TILE_SIZE { 8U };
63
64 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
65
66 constexpr uint32_t MAX_PASS_COUNT { 3u };
67
68 constexpr int32_t BUFFER_SIZE_IN_BYTES = sizeof(BASE_NS::Math::Vec4);
69 constexpr GpuBufferDesc BUFFER_DESC { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
70 (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
71 CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER, 0U };
72
CreateGpuBuffers(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)73 RenderHandleReference CreateGpuBuffers(
74 IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
75 {
76 // Create buffer for the shader data.
77 GpuBufferDesc desc = BUFFER_DESC;
78 desc.byteSize = BUFFER_SIZE_IN_BYTES;
79 return gpuResourceMgr.Create(handle, desc);
80 }
81
UpdateBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandle & handle,const BASE_NS::Math::Vec4 & shaderParameters)82 void UpdateBuffer(IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandle& handle,
83 const BASE_NS::Math::Vec4& shaderParameters)
84 {
85 if (void* data = gpuResourceMgr.MapBuffer(handle); data) {
86 CloneData(data, sizeof(BASE_NS::Math::Vec4), &shaderParameters, sizeof(BASE_NS::Math::Vec4));
87 gpuResourceMgr.UnmapBuffer(handle);
88 }
89 }
90 } // namespace
91
RenderPostProcessMotionBlurNode()92 RenderPostProcessMotionBlurNode::RenderPostProcessMotionBlurNode()
93 : inputProperties_(
94 &nodeInputsData, array_view(PropertyType::DataType<RenderPostProcessMotionBlurNode::NodeInputs>::properties)),
95 outputProperties_(&nodeOutputsData,
96 array_view(PropertyType::DataType<RenderPostProcessMotionBlurNode::NodeOutputs>::properties))
97
98 {}
99
GetRenderInputProperties()100 IPropertyHandle* RenderPostProcessMotionBlurNode::GetRenderInputProperties()
101 {
102 return inputProperties_.GetData();
103 }
104
GetRenderOutputProperties()105 IPropertyHandle* RenderPostProcessMotionBlurNode::GetRenderOutputProperties()
106 {
107 return outputProperties_.GetData();
108 }
109
SetRenderAreaRequest(const RenderAreaRequest & renderAreaRequest)110 void RenderPostProcessMotionBlurNode::SetRenderAreaRequest(const RenderAreaRequest& renderAreaRequest)
111 {
112 useRequestedRenderArea_ = true;
113 renderAreaRequest_ = renderAreaRequest;
114 }
115
GetExecuteFlags() const116 IRenderNode::ExecuteFlags RenderPostProcessMotionBlurNode::GetExecuteFlags() const
117 {
118 if (effectProperties_.enabled) {
119 return 0;
120 } else {
121 return IRenderNode::ExecuteFlagBits::EXECUTE_FLAG_BITS_DO_NOT_EXECUTE;
122 }
123 }
124
Init(const IRenderPostProcess::Ptr & postProcess,IRenderNodeContextManager & renderNodeContextMgr)125 void RenderPostProcessMotionBlurNode::Init(
126 const IRenderPostProcess::Ptr& postProcess, IRenderNodeContextManager& renderNodeContextMgr)
127 {
128 renderNodeContextMgr_ = &renderNodeContextMgr;
129 postProcess_ = postProcess;
130
131 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr.GetShaderManager();
132 {
133 renderData_ = {};
134 renderData_.shader = shaderMgr.GetShaderHandle("rendershaders://shader/fullscreen_motion_blur.shader");
135 renderData_.pipelineLayout = shaderMgr.GetReflectionPipelineLayout(renderData_.shader);
136 const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(renderData_.shader);
137 renderData_.pso = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(renderData_.shader, graphicsState,
138 renderData_.pipelineLayout, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
139 }
140 {
141 renderTileMaxData_ = {};
142 renderTileMaxData_.shader =
143 shaderMgr.GetShaderHandle("rendershaders://shader/fullscreen_motion_blur_tile_max.shader");
144 renderTileMaxData_.pipelineLayout = shaderMgr.GetReflectionPipelineLayout(renderTileMaxData_.shader);
145 const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(renderTileMaxData_.shader);
146 renderTileMaxData_.pso = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(renderTileMaxData_.shader,
147 graphicsState, renderTileMaxData_.pipelineLayout, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
148 }
149 {
150 renderTileNeighborData_ = {};
151 renderTileNeighborData_.shader =
152 shaderMgr.GetShaderHandle("rendershaders://shader/fullscreen_motion_blur_tile_neighborhood.shader");
153 renderTileNeighborData_.pipelineLayout = shaderMgr.GetReflectionPipelineLayout(renderTileNeighborData_.shader);
154 const RenderHandle graphicsState =
155 shaderMgr.GetGraphicsStateHandleByShaderHandle(renderTileNeighborData_.shader);
156 const ShaderSpecializationConstantView specView =
157 shaderMgr.GetReflectionSpecialization(renderTileNeighborData_.shader);
158 {
159 const uint32_t specFlags[] = { CORE_SPREAD_TYPE_NEIGHBORHOOD };
160 const ShaderSpecializationConstantDataView specDataView { specView.constants, specFlags };
161 renderTileNeighborData_.psoNeighborhood = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
162 renderTileNeighborData_.shader, graphicsState, renderTileNeighborData_.pipelineLayout, {}, specDataView,
163 { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
164 }
165 {
166 const uint32_t specFlags[] = { CORE_SPREAD_TYPE_HORIZONTAL };
167 const ShaderSpecializationConstantDataView specDataView { specView.constants, specFlags };
168 renderTileNeighborData_.psoHorizontal = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
169 renderTileNeighborData_.shader, graphicsState, renderTileNeighborData_.pipelineLayout, {}, specDataView,
170 { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
171 }
172 {
173 const uint32_t specFlags[] = { CORE_SPREAD_TYPE_VERTICAL };
174 const ShaderSpecializationConstantDataView specDataView { specView.constants, specFlags };
175 renderTileNeighborData_.psoVertical = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
176 renderTileNeighborData_.shader, graphicsState, renderTileNeighborData_.pipelineLayout, {}, specDataView,
177 { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
178 }
179 }
180
181 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
182 samplerHandle_ = renderNodeContextMgr.GetGpuResourceManager().GetSamplerHandle(
183 DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
184 samplerNearestHandle_ = renderNodeContextMgr.GetGpuResourceManager().GetSamplerHandle(
185 DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_NEAREST_CLAMP);
186 gpuBuffer_ = CreateGpuBuffers(gpuResourceMgr, gpuBuffer_);
187
188 valid_ = true;
189 }
190
PreExecute()191 void RenderPostProcessMotionBlurNode::PreExecute()
192 {
193 if (valid_ && postProcess_) {
194 const array_view<const uint8_t> propertyView = postProcess_->GetData();
195 // this node is directly dependant
196 PLUGIN_ASSERT(propertyView.size_bytes() == sizeof(RenderPostProcessMotionBlurNode::EffectProperties));
197 if (propertyView.size_bytes() == sizeof(RenderPostProcessMotionBlurNode::EffectProperties)) {
198 effectProperties_ = (const RenderPostProcessMotionBlurNode::EffectProperties&)(*propertyView.data());
199 if ((effectProperties_.motionBlurConfiguration.quality == MotionBlurConfiguration::Quality::MEDIUM) ||
200 (effectProperties_.motionBlurConfiguration.quality == MotionBlurConfiguration::Quality::HIGH)) {
201 const uint32_t compSizeX = (effectProperties_.size.x + VELOCITY_TILE_SIZE - 1U) / VELOCITY_TILE_SIZE;
202 const uint32_t compSizeY = (effectProperties_.size.y + VELOCITY_TILE_SIZE - 1U) / VELOCITY_TILE_SIZE;
203 if ((!tileVelocityImages_[0U]) || (tileImageSize_.x != compSizeX) || (tileImageSize_.y != compSizeY)) {
204 IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
205 GpuImageDesc desc = renderNodeContextMgr_->GetGpuResourceManager().GetImageDescriptor(
206 nodeInputsData.velocity.handle);
207 desc.engineCreationFlags = CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS |
208 CORE_ENGINE_IMAGE_CREATION_RESET_STATE_ON_FRAME_BORDERS;
209 desc.usageFlags = CORE_IMAGE_USAGE_SAMPLED_BIT | CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
210 desc.mipCount = 1U;
211 desc.layerCount = 1U;
212 desc.width = compSizeX;
213 desc.height = compSizeY;
214 tileVelocityImages_[0U] = gpuResourceMgr.Create(tileVelocityImages_[0U], desc);
215 tileVelocityImages_[1U] = gpuResourceMgr.Create(tileVelocityImages_[1U], desc);
216
217 tileImageSize_ = { compSizeX, compSizeY };
218 }
219 }
220 }
221 } else {
222 effectProperties_.enabled = false;
223 }
224 }
225
Execute(IRenderCommandList & cmdList)226 void RenderPostProcessMotionBlurNode::Execute(IRenderCommandList& cmdList)
227 {
228 if (!RenderHandleUtil::IsGpuImage(nodeOutputsData.output.handle)) {
229 return;
230 }
231
232 CheckDescriptorSetNeed();
233
234 RENDER_DEBUG_MARKER_COL_SCOPE(cmdList, "RenderMotionBlur", DefaultDebugConstants::CORE_DEFAULT_DEBUG_COLOR);
235
236 const RenderHandle velocity = nodeInputsData.velocity.handle;
237 RenderHandle tileVelocity = nodeInputsData.velocity.handle;
238 if ((effectProperties_.motionBlurConfiguration.quality == MotionBlurConfiguration::Quality::MEDIUM) ||
239 (effectProperties_.motionBlurConfiguration.quality == MotionBlurConfiguration::Quality::HIGH)) {
240 ExecuteTileVelocity(cmdList);
241 const RenderHandle tv = GetTileVelocityForMotionBlur();
242 tileVelocity = RenderHandleUtil::IsValid(tv) ? tv : velocity;
243 }
244
245 const auto& renderData = renderData_;
246
247 RenderPass renderPass;
248 renderPass.renderPassDesc.attachmentCount = 1;
249 renderPass.renderPassDesc.renderArea = { 0, 0, effectProperties_.size.x, effectProperties_.size.y };
250 renderPass.renderPassDesc.subpassCount = 1;
251 renderPass.renderPassDesc.attachments[0].loadOp = CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
252 renderPass.renderPassDesc.attachments[0].storeOp = CORE_ATTACHMENT_STORE_OP_STORE;
253 renderPass.renderPassDesc.attachmentHandles[0] = nodeOutputsData.output.handle;
254 renderPass.subpassStartIndex = 0;
255 auto& subpass = renderPass.subpassDesc;
256 subpass.colorAttachmentCount = 1;
257 subpass.colorAttachmentIndices[0] = 0;
258
259 cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
260 cmdList.BindPipeline(renderData.pso);
261
262 shaderParameters_ = GetFactorMotionBlur();
263 UpdateBuffer(renderNodeContextMgr_->GetGpuResourceManager(), gpuBuffer_.GetHandle(), shaderParameters_);
264
265 {
266 auto& binder = *binders_.localSet0;
267 binder.ClearBindings();
268 uint32_t binding = 0u;
269 binder.BindImage(binding++, nodeInputsData.input.handle, samplerHandle_);
270 binder.BindImage(binding++, nodeInputsData.depth.handle, samplerNearestHandle_);
271 binder.BindImage(binding++, velocity, samplerHandle_);
272 binder.BindImage(binding++, tileVelocity, samplerHandle_);
273 binder.BindBuffer(binding++, gpuBuffer_.GetHandle(), 0u);
274
275 cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
276 cmdList.BindDescriptorSet(0u, binder.GetDescriptorSetHandle());
277 }
278
279 if (renderData.pipelineLayout.pushConstant.byteSize > 0) {
280 const auto fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
281 const auto fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
282 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight }, {} };
283 cmdList.PushConstantData(renderData_.pipelineLayout.pushConstant, arrayviewU8(pc));
284 }
285
286 // dynamic state
287 cmdList.SetDynamicStateViewport(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultViewport(renderPass));
288 cmdList.SetDynamicStateScissor(renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultScissor(renderPass));
289
290 cmdList.Draw(3u, 1u, 0u, 0u);
291 cmdList.EndRenderPass();
292 }
293
ExecuteTileVelocity(IRenderCommandList & cmdList)294 void RenderPostProcessMotionBlurNode::ExecuteTileVelocity(IRenderCommandList& cmdList)
295 {
296 if ((!RenderHandleUtil::IsGpuImage(nodeOutputsData.output.handle)) || (!tileVelocityImages_[0U])) {
297 return;
298 }
299
300 RenderPass renderPass;
301 renderPass.renderPassDesc.attachmentCount = 1;
302 renderPass.renderPassDesc.renderArea = { 0, 0, tileImageSize_.x, tileImageSize_.y };
303 renderPass.renderPassDesc.subpassCount = 1;
304 renderPass.renderPassDesc.attachments[0].loadOp = CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
305 renderPass.renderPassDesc.attachments[0].storeOp = CORE_ATTACHMENT_STORE_OP_STORE;
306 renderPass.subpassStartIndex = 0;
307 auto& subpass = renderPass.subpassDesc;
308 subpass.colorAttachmentCount = 1;
309 subpass.colorAttachmentIndices[0] = 0;
310
311 const RenderHandle vel0 = tileVelocityImages_[0U].GetHandle();
312 const RenderHandle vel1 = tileVelocityImages_[1U].GetHandle();
313
314 const ViewportDesc viewport = renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultViewport(renderPass);
315 const ScissorDesc scissor = renderNodeContextMgr_->GetRenderNodeUtil().CreateDefaultScissor(renderPass);
316
317 const auto fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
318 const auto fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
319 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight }, {} };
320
321 // tile max pass
322 {
323 const auto& renderData = renderTileMaxData_;
324 renderPass.renderPassDesc.attachmentHandles[0] = vel0;
325
326 cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
327 cmdList.BindPipeline(renderData.pso);
328
329 {
330 auto& binder = *binders_.localTileMaxSet0;
331 binder.ClearBindings();
332 binder.BindImage(0U, nodeInputsData.velocity.handle, samplerHandle_);
333 cmdList.UpdateDescriptorSet(
334 binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
335 cmdList.BindDescriptorSet(0u, binder.GetDescriptorSetHandle());
336 }
337
338 if (renderData.pipelineLayout.pushConstant.byteSize > 0) {
339 cmdList.PushConstant(renderData.pipelineLayout.pushConstant, arrayviewU8(pc).data());
340 }
341
342 // dynamic state
343 cmdList.SetDynamicStateViewport(viewport);
344 cmdList.SetDynamicStateScissor(scissor);
345
346 cmdList.Draw(3U, 1U, 0U, 0U);
347 cmdList.EndRenderPass();
348 }
349 // tile neighborhood pass
350 {
351 const auto& renderData = renderTileNeighborData_;
352 {
353 const RenderHandle pso =
354 renderTileNeighborData_.doublePass ? renderData.psoHorizontal : renderData.psoNeighborhood;
355
356 renderPass.renderPassDesc.attachmentHandles[0] = vel1;
357
358 cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
359 cmdList.BindPipeline(pso);
360
361 {
362 auto& binder = *binders_.localTileNeighborhoodSet0[0U];
363 binder.ClearBindings();
364 binder.BindImage(0U, vel0, samplerHandle_);
365 cmdList.UpdateDescriptorSet(
366 binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
367 cmdList.BindDescriptorSet(0u, binder.GetDescriptorSetHandle());
368 }
369
370 if (renderData.pipelineLayout.pushConstant.byteSize > 0) {
371 cmdList.PushConstant(renderData.pipelineLayout.pushConstant, arrayviewU8(pc).data());
372 }
373
374 // dynamic state
375 cmdList.SetDynamicStateViewport(viewport);
376 cmdList.SetDynamicStateScissor(scissor);
377
378 cmdList.Draw(3U, 1U, 0U, 0U);
379 cmdList.EndRenderPass();
380 }
381 if (renderTileNeighborData_.doublePass) {
382 const RenderHandle pso = renderData.psoVertical;
383
384 renderPass.renderPassDesc.attachmentHandles[0] = vel0;
385
386 cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
387 cmdList.BindPipeline(pso);
388
389 {
390 auto& binder = *binders_.localTileNeighborhoodSet0[1U];
391 binder.ClearBindings();
392 binder.BindImage(0U, vel1, samplerHandle_);
393 cmdList.UpdateDescriptorSet(
394 binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
395 cmdList.BindDescriptorSet(0u, binder.GetDescriptorSetHandle());
396 }
397
398 if (renderData.pipelineLayout.pushConstant.byteSize > 0) {
399 cmdList.PushConstant(renderData.pipelineLayout.pushConstant, arrayviewU8(pc).data());
400 }
401
402 // dynamic state
403 cmdList.SetDynamicStateViewport(viewport);
404 cmdList.SetDynamicStateScissor(scissor);
405
406 cmdList.Draw(3U, 1U, 0U, 0U);
407 cmdList.EndRenderPass();
408 }
409 }
410 }
411
GetFactorMotionBlur() const412 BASE_NS::Math::Vec4 RenderPostProcessMotionBlurNode::GetFactorMotionBlur() const
413 {
414 return {
415 static_cast<float>(effectProperties_.motionBlurConfiguration.sharpness),
416 static_cast<float>(effectProperties_.motionBlurConfiguration.quality),
417 effectProperties_.motionBlurConfiguration.alpha,
418 effectProperties_.motionBlurConfiguration.velocityCoefficient,
419 };
420 }
421
GetTileVelocityForMotionBlur() const422 RenderHandle RenderPostProcessMotionBlurNode::GetTileVelocityForMotionBlur() const
423 {
424 return renderTileNeighborData_.doublePass ? tileVelocityImages_[0U].GetHandle()
425 : tileVelocityImages_[1U].GetHandle();
426 }
427
GetRenderDescriptorCounts() const428 DescriptorCounts RenderPostProcessMotionBlurNode::GetRenderDescriptorCounts() const
429 {
430 // expected high max mip count
431 return DescriptorCounts { {
432 { CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, MAX_PASS_COUNT },
433 { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u * MAX_PASS_COUNT },
434 } };
435 }
436
CheckDescriptorSetNeed()437 void RenderPostProcessMotionBlurNode::CheckDescriptorSetNeed()
438 {
439 if (!binders_.localSet0) {
440 constexpr uint32_t localSet = 0u;
441 INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr_->GetDescriptorSetManager();
442 {
443 const auto& bindings = renderData_.pipelineLayout.descriptorSetLayouts[localSet].bindings;
444 const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
445 binders_.localSet0 = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
446 }
447 {
448 const auto& bindings = renderTileMaxData_.pipelineLayout.descriptorSetLayouts[localSet].bindings;
449 const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
450 binders_.localTileMaxSet0 = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
451 }
452 {
453 const auto& bindings = renderTileNeighborData_.pipelineLayout.descriptorSetLayouts[localSet].bindings;
454 {
455 const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
456 binders_.localTileNeighborhoodSet0[0U] =
457 descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
458 }
459 {
460 const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
461 binders_.localTileNeighborhoodSet0[1U] =
462 descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
463 }
464 }
465 }
466 }
467
468 RENDER_END_NAMESPACE()
469