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