• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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_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_layout_desc.h>
21 #include <render/device/pipeline_state_desc.h>
22 #include <render/namespace.h>
23 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
24 #include <render/nodecontext/intf_node_context_pso_manager.h>
25 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
26 #include <render/nodecontext/intf_render_command_list.h>
27 #include <render/nodecontext/intf_render_node_context_manager.h>
28 #include <render/nodecontext/intf_render_node_util.h>
29 #include <render/shaders/common/render_blur_common.h>
30 
31 #include "default_engine_constants.h"
32 #include "device/gpu_resource_handle_util.h"
33 #include "render/shaders/common/render_post_process_structs_common.h"
34 #include "util/log.h"
35 
36 using namespace BASE_NS;
37 
38 RENDER_BEGIN_NAMESPACE()
39 namespace {
40 constexpr uint32_t MAX_MIP_COUNT { 16u };
41 constexpr uint32_t MAX_PASS_PER_LEVEL_COUNT { 3u };
42 constexpr bool GAUSSIAN_TYPE { true };
43 } // namespace
44 
Init(IRenderNodeContextManager & renderNodeContextMgr,const BlurInfo & blurInfo)45 void RenderBlur::Init(IRenderNodeContextManager& renderNodeContextMgr, const BlurInfo& blurInfo)
46 {
47     blurInfo_ = blurInfo;
48     {
49         const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr.GetShaderManager();
50         renderData_ = {};
51         renderData_.shader = shaderMgr.GetShaderHandle("rendershaders://shader/fullscreen_blur.shader");
52         renderData_.pipelineLayout = shaderMgr.GetReflectionPipelineLayout(renderData_.shader);
53     }
54     {
55         imageData_ = {};
56         imageData_.mipImage = blurInfo.blurTarget;
57         samplerHandle_ = renderNodeContextMgr.GetGpuResourceManager().GetSamplerHandle(
58             DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
59     }
60     {
61         constexpr uint32_t globalSet = 0u;
62         constexpr uint32_t localSet = 1u;
63 
64         constexpr uint32_t maxBinderCount = MAX_MIP_COUNT * MAX_PASS_PER_LEVEL_COUNT;
65         binders_.clear();
66         binders_.resize(maxBinderCount);
67 
68         INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr.GetDescriptorSetManager();
69         {
70             const auto& bindings = renderData_.pipelineLayout.descriptorSetLayouts[globalSet].bindings;
71             const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
72             globalSet0_ = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
73         }
74         const auto& bindings = renderData_.pipelineLayout.descriptorSetLayouts[localSet].bindings;
75         for (uint32_t idx = 0; idx < maxBinderCount; ++idx) {
76             const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
77             binders_[idx] = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
78         }
79     }
80 }
81 
PreExecute(IRenderNodeContextManager & renderNodeContextMgr,const BlurInfo & blurInfo,const PostProcessConfiguration & ppConfig)82 void RenderBlur::PreExecute(
83     IRenderNodeContextManager& renderNodeContextMgr, const BlurInfo& blurInfo, const PostProcessConfiguration& ppConfig)
84 {
85     blurInfo_ = blurInfo;
86     imageData_.mipImage = blurInfo.blurTarget;
87     globalUbo_ = blurInfo.globalUbo;
88 
89     const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr.GetGpuResourceManager();
90     const GpuImageDesc imageDesc = gpuResourceMgr.GetImageDescriptor(imageData_.mipImage);
91     imageData_.mipCount = imageDesc.mipCount;
92     imageData_.format = imageDesc.format;
93     imageData_.size = { imageDesc.width, imageDesc.height };
94     if (GAUSSIAN_TYPE) {
95         CreateTargets(renderNodeContextMgr, imageData_.size);
96     }
97 }
98 
Execute(IRenderNodeContextManager & renderNodeContextMgr,IRenderCommandList & cmdList,const PostProcessConfiguration & ppConfig)99 void RenderBlur::Execute(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList,
100     const PostProcessConfiguration& ppConfig)
101 {
102     if (!RenderHandleUtil::IsGpuImage(imageData_.mipImage)) {
103         return;
104     }
105 
106     UpdateGlobalSet(cmdList);
107 
108     RenderPass renderPass;
109     renderPass.renderPassDesc.attachmentCount = 1;
110     renderPass.renderPassDesc.renderArea = { 0, 0, imageData_.size.x, imageData_.size.y };
111     renderPass.renderPassDesc.subpassCount = 1;
112     renderPass.renderPassDesc.attachments[0].loadOp = CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
113     renderPass.renderPassDesc.attachments[0].storeOp = CORE_ATTACHMENT_STORE_OP_STORE;
114     renderPass.renderPassDesc.attachmentHandles[0] = imageData_.mipImage;
115     renderPass.subpassStartIndex = 0;
116     auto& subpass = renderPass.subpassDesc;
117     subpass.colorAttachmentCount = 1;
118     subpass.colorAttachmentIndices[0] = 0;
119 
120     if (!RenderHandleUtil::IsValid(renderData_.psoScale)) {
121         const auto& shaderMgr = renderNodeContextMgr.GetShaderManager();
122         constexpr DynamicStateFlags dynamicStateFlags =
123             DynamicStateFlagBits::CORE_DYNAMIC_STATE_VIEWPORT | DynamicStateFlagBits::CORE_DYNAMIC_STATE_SCISSOR;
124         const ShaderSpecilizationConstantView sscv = shaderMgr.GetReflectionSpecialization(renderData_.shader);
125         const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(renderData_.shader);
126         {
127             const uint32_t specializationFlags = CORE_BLUR_TYPE_DOWNSCALE_RGBA;
128             const ShaderSpecializationConstantDataView specDataView {
129                 { sscv.constants.data(), sscv.constants.size() },
130                 { &specializationFlags, 1u },
131             };
132             renderData_.psoScale = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
133                 renderData_.shader, graphicsState, renderData_.pipelineLayout, {}, specDataView, dynamicStateFlags);
134         }
135         {
136             const uint32_t specializationFlags = CORE_BLUR_TYPE_RGBA;
137             const ShaderSpecializationConstantDataView specDataView {
138                 { sscv.constants.data(), sscv.constants.size() },
139                 { &specializationFlags, 1u },
140             };
141             renderData_.psoBlur = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(
142                 renderData_.shader, graphicsState, renderData_.pipelineLayout, {}, specDataView, dynamicStateFlags);
143         }
144     }
145 
146     if (GAUSSIAN_TYPE) {
147         RenderGaussian(renderNodeContextMgr, cmdList, renderPass, ppConfig);
148     } else {
149         RenderData(renderNodeContextMgr, cmdList, renderPass, ppConfig);
150     }
151 }
152 
UpdateGlobalSet(IRenderCommandList & cmdList)153 void RenderBlur::UpdateGlobalSet(IRenderCommandList& cmdList)
154 {
155     auto& binder = *globalSet0_;
156     binder.ClearBindings();
157     uint32_t binding = 0u;
158     binder.BindBuffer(binding++, globalUbo_, 0);
159     binder.BindBuffer(binding++, globalUbo_, 0);
160     cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
161 }
162 
GetDescriptorCounts() const163 DescriptorCounts RenderBlur::GetDescriptorCounts() const
164 {
165     // expected high max mip count
166     return DescriptorCounts { {
167         { CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MAX_MIP_COUNT },
168         { CORE_DESCRIPTOR_TYPE_SAMPLER, MAX_MIP_COUNT },
169         { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u * MAX_MIP_COUNT },
170     } };
171 }
172 
173 // constants for RenderBlur::RenderData
174 namespace {
175 constexpr bool USE_CUSTOM_BARRIERS = true;
176 
177 constexpr ImageResourceBarrier SRC_UNDEFINED { 0, CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, CORE_IMAGE_LAYOUT_UNDEFINED };
178 constexpr ImageResourceBarrier COL_ATTACHMENT { CORE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
179     CORE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, CORE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
180 constexpr ImageResourceBarrier SHDR_READ { CORE_ACCESS_SHADER_READ_BIT, CORE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
181     CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
182 // transition the final mip level to read only as well
183 constexpr ImageResourceBarrier FINAL_SRC { CORE_ACCESS_SHADER_READ_BIT | CORE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
184     CORE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | CORE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
185     CORE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
186 constexpr ImageResourceBarrier FINAL_DST { CORE_ACCESS_SHADER_READ_BIT,
187     CORE_PIPELINE_STAGE_VERTEX_SHADER_BIT, // first possible shader read stage
188     CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
189 } // namespace
190 
RenderData(IRenderNodeContextManager & renderNodeContextMgr,IRenderCommandList & cmdList,const RenderPass & renderPassBase,const PostProcessConfiguration & ppConfig)191 void RenderBlur::RenderData(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList,
192     const RenderPass& renderPassBase, const PostProcessConfiguration& ppConfig)
193 {
194     RenderPass renderPass = renderPassBase;
195     const GpuImageDesc imageDesc = renderNodeContextMgr.GetGpuResourceManager().GetImageDescriptor(imageData_.mipImage);
196 
197     if (USE_CUSTOM_BARRIERS) {
198         cmdList.BeginDisableAutomaticBarrierPoints();
199     }
200 
201     RenderHandle sets[2u] {};
202     sets[0] = globalSet0_->GetDescriptorSetHandle();
203 
204     const uint32_t blurCount = Math::min(ppConfig.blurConfiguration.maxMipLevel, imageData_.mipCount);
205     // NOTE: for smoother results, first downscale -> then horiz / vert -> downscale and so on
206     ImageSubresourceRange imageSubresourceRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0,
207         PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
208     for (uint32_t idx = 1; idx < blurCount; ++idx) {
209         const uint32_t renderPassMipLevel = blurInfo_.upScale ? (blurCount - idx - 1) : idx;
210         const uint32_t inputMipLevel = blurInfo_.upScale ? (blurCount - idx) : (idx - 1);
211 
212         const uint32_t currWidth = Math::max(1u, imageDesc.width >> renderPassMipLevel);
213         const uint32_t currHeight = Math::max(1u, imageDesc.height >> renderPassMipLevel);
214         const float fCurrWidth = static_cast<float>(currWidth);
215         const float fCurrHeight = static_cast<float>(currHeight);
216 
217         renderPass.renderPassDesc.renderArea = { 0, 0, currWidth, currHeight };
218         renderPass.renderPassDesc.attachments[0].mipLevel = renderPassMipLevel;
219 
220         if (USE_CUSTOM_BARRIERS) {
221             imageSubresourceRange.baseMipLevel = renderPassMipLevel;
222             cmdList.CustomImageBarrier(imageData_.mipImage, SRC_UNDEFINED, COL_ATTACHMENT, imageSubresourceRange);
223             imageSubresourceRange.baseMipLevel = inputMipLevel;
224             if (inputMipLevel == 0) {
225                 cmdList.CustomImageBarrier(imageData_.mipImage, SHDR_READ, imageSubresourceRange);
226             } else {
227                 cmdList.CustomImageBarrier(imageData_.mipImage, COL_ATTACHMENT, SHDR_READ, imageSubresourceRange);
228             }
229             cmdList.AddCustomBarrierPoint();
230         }
231 
232         cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
233 
234         cmdList.SetDynamicStateViewport(ViewportDesc { 0.0f, 0.0f, fCurrWidth, fCurrHeight, 0.0f, 0.0f });
235         cmdList.SetDynamicStateScissor(ScissorDesc { 0, 0, currWidth, currHeight });
236 
237         cmdList.BindPipeline(renderData_.psoScale);
238 
239         {
240             auto& binder = *binders_[idx];
241             sets[1u] = binder.GetDescriptorSetHandle();
242             binder.ClearBindings();
243             binder.BindSampler(0, samplerHandle_);
244             binder.BindImage(1, { imageData_.mipImage, inputMipLevel });
245             cmdList.UpdateDescriptorSet(
246                 binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
247         }
248         cmdList.BindDescriptorSets(0u, sets);
249 
250         const LocalPostProcessPushConstantStruct pc {
251             { fCurrWidth, fCurrHeight, 1.0f / (fCurrWidth), 1.0f / (fCurrHeight) }, { 1.0f, 0.0f, 0.0f, 0.0f }
252         };
253         cmdList.PushConstant(renderData_.pipelineLayout.pushConstant, reinterpret_cast<const uint8_t*>(&pc));
254 
255         cmdList.Draw(3u, 1u, 0u, 0u);
256         cmdList.EndRenderPass();
257     }
258 
259     if (USE_CUSTOM_BARRIERS) {
260         if (imageData_.mipCount > 1u) {
261             // transition the final used mip level
262             if (blurCount > 0) {
263                 const ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, blurCount - 1, 1, 0,
264                     PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
265                 cmdList.CustomImageBarrier(imageData_.mipImage, FINAL_SRC, FINAL_DST, imgRange);
266             }
267             if (blurCount < imageData_.mipCount) {
268                 // transition the final levels which might be in undefined state
269                 const ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, blurCount,
270                     imageData_.mipCount - blurCount, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
271                 cmdList.CustomImageBarrier(imageData_.mipImage, SRC_UNDEFINED, FINAL_DST, imgRange);
272             }
273         }
274         cmdList.AddCustomBarrierPoint();
275         cmdList.EndDisableAutomaticBarrierPoints();
276     }
277 }
278 
279 namespace {
DownscaleBarrier(IRenderCommandList & cmdList,const RenderHandle image,const uint32_t mipLevel)280 void DownscaleBarrier(IRenderCommandList& cmdList, const RenderHandle image, const uint32_t mipLevel)
281 {
282     ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0,
283         PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
284     imgRange.baseMipLevel = mipLevel;
285     cmdList.CustomImageBarrier(image, SRC_UNDEFINED, COL_ATTACHMENT, imgRange);
286     const uint32_t inputMipLevel = mipLevel - 1u;
287     imgRange.baseMipLevel = inputMipLevel;
288     if (inputMipLevel == 0) {
289         cmdList.CustomImageBarrier(image, SHDR_READ, imgRange);
290     } else {
291         cmdList.CustomImageBarrier(image, COL_ATTACHMENT, SHDR_READ, imgRange);
292     }
293     cmdList.AddCustomBarrierPoint();
294 }
295 
BlurHorizontalBarrier(IRenderCommandList & cmdList,const RenderHandle realImage,const uint32_t mipLevel,const RenderHandle tmpImage)296 void BlurHorizontalBarrier(
297     IRenderCommandList& cmdList, const RenderHandle realImage, const uint32_t mipLevel, const RenderHandle tmpImage)
298 {
299     ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0,
300         PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
301     imgRange.baseMipLevel = mipLevel;
302     cmdList.CustomImageBarrier(realImage, COL_ATTACHMENT, SHDR_READ, imgRange);
303     imgRange.baseMipLevel = mipLevel - 1;
304     cmdList.CustomImageBarrier(tmpImage, SRC_UNDEFINED, COL_ATTACHMENT, imgRange);
305     cmdList.AddCustomBarrierPoint();
306 }
307 
BlurVerticalBarrier(IRenderCommandList & cmdList,const RenderHandle realImage,const uint32_t mipLevel,const RenderHandle tmpImage)308 void BlurVerticalBarrier(
309     IRenderCommandList& cmdList, const RenderHandle realImage, const uint32_t mipLevel, const RenderHandle tmpImage)
310 {
311     ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0,
312         PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
313     imgRange.baseMipLevel = mipLevel;
314     cmdList.CustomImageBarrier(realImage, SHDR_READ, COL_ATTACHMENT, imgRange);
315     imgRange.baseMipLevel = mipLevel - 1;
316     cmdList.CustomImageBarrier(tmpImage, COL_ATTACHMENT, SHDR_READ, imgRange);
317     cmdList.AddCustomBarrierPoint();
318 }
319 
320 struct ConstDrawInput {
321     IRenderCommandList& cmdList;
322     const RenderPass& renderPass;
323     const PushConstant& pushConstant;
324     const LocalPostProcessPushConstantStruct& pc;
325     RenderHandle sampler;
326 };
BlurPass(const ConstDrawInput & di,IDescriptorSetBinder & binder,IDescriptorSetBinder & globalBinder,const RenderHandle psoHandle,const RenderHandle image,const uint32_t inputMipLevel)327 void BlurPass(const ConstDrawInput& di, IDescriptorSetBinder& binder, IDescriptorSetBinder& globalBinder,
328     const RenderHandle psoHandle, const RenderHandle image, const uint32_t inputMipLevel)
329 {
330     di.cmdList.BeginRenderPass(
331         di.renderPass.renderPassDesc, di.renderPass.subpassStartIndex, di.renderPass.subpassDesc);
332     di.cmdList.BindPipeline(psoHandle);
333 
334     RenderHandle sets[2u] {};
335     sets[0] = globalBinder.GetDescriptorSetHandle();
336     {
337         binder.ClearBindings();
338         sets[1u] = binder.GetDescriptorSetHandle();
339         binder.BindSampler(0, di.sampler);
340         binder.BindImage(1u, { image, inputMipLevel });
341         di.cmdList.UpdateDescriptorSet(
342             binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
343     }
344     di.cmdList.BindDescriptorSets(0, sets);
345 
346     di.cmdList.PushConstant(di.pushConstant, reinterpret_cast<const uint8_t*>(&di.pc));
347     di.cmdList.Draw(3u, 1u, 0u, 0u);
348     di.cmdList.EndRenderPass();
349 }
350 } // namespace
351 
RenderGaussian(IRenderNodeContextManager & renderNodeContextMgr,IRenderCommandList & cmdList,const RenderPass & renderPassBase,const PostProcessConfiguration & ppConfig)352 void RenderBlur::RenderGaussian(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList,
353     const RenderPass& renderPassBase, const PostProcessConfiguration& ppConfig)
354 {
355     RenderPass renderPass = renderPassBase;
356     if (USE_CUSTOM_BARRIERS) {
357         cmdList.BeginDisableAutomaticBarrierPoints();
358     }
359 
360     // with every mip, first we do a downscale
361     // then a single horizontal and a single vertical blur
362     LocalPostProcessPushConstantStruct pc { { 1.0f, 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 0.0f } };
363     uint32_t descIdx = 0;
364     const uint32_t blurCount = Math::min(ppConfig.blurConfiguration.maxMipLevel, imageData_.mipCount);
365     const ConstDrawInput di { cmdList, renderPass, renderData_.pipelineLayout.pushConstant, pc, samplerHandle_ };
366     for (uint32_t idx = 1; idx < blurCount; ++idx) {
367         const uint32_t mip = idx;
368 
369         const Math::UVec2 size = { Math::max(1u, imageData_.size.x >> mip), Math::max(1u, imageData_.size.y >> mip) };
370         const Math::Vec2 fSize = { static_cast<float>(size.x), static_cast<float>(size.y) };
371         const Math::Vec4 texSizeInvTexSize { fSize.x * 1.0f, fSize.y * 1.0f, 1.0f / fSize.x, 1.0f / fSize.y };
372         pc = { texSizeInvTexSize, { 1.0f, 0.0f, 0.0f, 0.0f } };
373 
374         renderPass.renderPassDesc.renderArea = { 0, 0, size.x, size.y };
375         renderPass.renderPassDesc.attachments[0].mipLevel = mip;
376 
377         cmdList.SetDynamicStateViewport({ 0.0f, 0.0f, fSize.x, fSize.y, 0.0f, 1.0f });
378         cmdList.SetDynamicStateScissor({ 0, 0, size.x, size.y });
379 
380         // downscale
381         if (USE_CUSTOM_BARRIERS) {
382             DownscaleBarrier(cmdList, imageData_.mipImage, mip);
383         }
384         BlurPass(di, *binders_[descIdx++], *globalSet0_, renderData_.psoScale, imageData_.mipImage, mip - 1u);
385 
386         // horizontal (from real image to temp)
387         if (USE_CUSTOM_BARRIERS) {
388             BlurHorizontalBarrier(cmdList, imageData_.mipImage, mip, tempTarget_.tex.GetHandle());
389         }
390 
391         renderPass.renderPassDesc.attachmentHandles[0] = tempTarget_.tex.GetHandle();
392         renderPass.renderPassDesc.attachments[0].mipLevel = mip - 1u;
393         BlurPass(di, *binders_[descIdx++], *globalSet0_, renderData_.psoBlur, imageData_.mipImage, mip);
394 
395         // vertical
396         if (USE_CUSTOM_BARRIERS) {
397             BlurVerticalBarrier(cmdList, imageData_.mipImage, mip, tempTarget_.tex.GetHandle());
398         }
399 
400         renderPass.renderPassDesc.attachmentHandles[0] = imageData_.mipImage;
401         renderPass.renderPassDesc.attachments[0].mipLevel = mip;
402         pc.factor = { 0.0f, 1.0f, 0.0f, 0.0f };
403         BlurPass(di, *binders_[descIdx++], *globalSet0_, renderData_.psoBlur, tempTarget_.tex.GetHandle(), mip - 1);
404     }
405 
406     if (USE_CUSTOM_BARRIERS) {
407         if (imageData_.mipCount > 1u) {
408             // transition the final used mip level
409             if (blurCount > 0) {
410                 const ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, blurCount - 1, 1, 0,
411                     PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
412                 cmdList.CustomImageBarrier(imageData_.mipImage, FINAL_SRC, FINAL_DST, imgRange);
413             }
414             if (blurCount < imageData_.mipCount) {
415                 // transition the final levels which might be in undefined state
416                 const ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, blurCount,
417                     imageData_.mipCount - blurCount, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
418                 cmdList.CustomImageBarrier(imageData_.mipImage, SRC_UNDEFINED, FINAL_DST, imgRange);
419             }
420         }
421         cmdList.AddCustomBarrierPoint();
422         cmdList.EndDisableAutomaticBarrierPoints();
423     }
424 }
425 
CreateTargets(IRenderNodeContextManager & renderNodeContextMgr,const Math::UVec2 baseSize)426 void RenderBlur::CreateTargets(IRenderNodeContextManager& renderNodeContextMgr, const Math::UVec2 baseSize)
427 {
428     Math::UVec2 texSize = baseSize / 2u;
429     texSize.x = Math::max(1u, texSize.x);
430     texSize.x = Math::max(1u, texSize.x);
431     if (texSize.x != tempTarget_.texSize.x || texSize.y != tempTarget_.texSize.y) {
432         tempTarget_.texSize = texSize;
433         tempTarget_.format = imageData_.format;
434 
435         constexpr ImageUsageFlags usageFlags = ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
436                                                ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT |
437                                                ImageUsageFlagBits::CORE_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
438 
439         const GpuImageDesc desc {
440             ImageType::CORE_IMAGE_TYPE_2D,
441             ImageViewType::CORE_IMAGE_VIEW_TYPE_2D,
442             tempTarget_.format,
443             ImageTiling::CORE_IMAGE_TILING_OPTIMAL,
444             usageFlags,
445             MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
446             0,
447             EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS,
448             tempTarget_.texSize.x,
449             tempTarget_.texSize.y,
450             1u,
451             Math::max(1u, (imageData_.mipCount - 1u)),
452             1u,
453             SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT,
454             {},
455         };
456 #if (RENDER_VALIDATION_ENABLED == 1)
457         tempTarget_.tex =
458             renderNodeContextMgr.GetGpuResourceManager().Create(renderNodeContextMgr.GetName() + "_BLUR_TARGET", desc);
459 #else
460         tempTarget_.tex = renderNodeContextMgr.GetGpuResourceManager().Create(tempTarget_.tex, desc);
461 #endif
462     }
463 }
464 RENDER_END_NAMESPACE()
465