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