18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci 168bf80f4bSopenharmony_ci#include "render_blur.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <render/device/intf_gpu_resource_manager.h> 198bf80f4bSopenharmony_ci#include <render/device/intf_shader_manager.h> 208bf80f4bSopenharmony_ci#include <render/device/pipeline_layout_desc.h> 218bf80f4bSopenharmony_ci#include <render/device/pipeline_state_desc.h> 228bf80f4bSopenharmony_ci#include <render/namespace.h> 238bf80f4bSopenharmony_ci#include <render/nodecontext/intf_node_context_descriptor_set_manager.h> 248bf80f4bSopenharmony_ci#include <render/nodecontext/intf_node_context_pso_manager.h> 258bf80f4bSopenharmony_ci#include <render/nodecontext/intf_pipeline_descriptor_set_binder.h> 268bf80f4bSopenharmony_ci#include <render/nodecontext/intf_render_command_list.h> 278bf80f4bSopenharmony_ci#include <render/nodecontext/intf_render_node_context_manager.h> 288bf80f4bSopenharmony_ci#include <render/nodecontext/intf_render_node_util.h> 298bf80f4bSopenharmony_ci#include <render/shaders/common/render_blur_common.h> 308bf80f4bSopenharmony_ci 318bf80f4bSopenharmony_ci#include "default_engine_constants.h" 328bf80f4bSopenharmony_ci#include "device/gpu_resource_handle_util.h" 338bf80f4bSopenharmony_ci#include "render/shaders/common/render_post_process_structs_common.h" 348bf80f4bSopenharmony_ci#include "util/log.h" 358bf80f4bSopenharmony_ci 368bf80f4bSopenharmony_ciusing namespace BASE_NS; 378bf80f4bSopenharmony_ci 388bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE() 398bf80f4bSopenharmony_cinamespace { 408bf80f4bSopenharmony_ciconstexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR }; 418bf80f4bSopenharmony_ci 428bf80f4bSopenharmony_ciconstexpr uint32_t MAX_MIP_COUNT { 16u }; 438bf80f4bSopenharmony_ciconstexpr uint32_t MAX_PASS_PER_LEVEL_COUNT { 3u }; 448bf80f4bSopenharmony_ciconstexpr bool GAUSSIAN_TYPE { true }; 458bf80f4bSopenharmony_ci} // namespace 468bf80f4bSopenharmony_ci 478bf80f4bSopenharmony_civoid RenderBlur::Init(IRenderNodeContextManager& renderNodeContextMgr, const BlurInfo& blurInfo) 488bf80f4bSopenharmony_ci{ 498bf80f4bSopenharmony_ci blurInfo_ = blurInfo; 508bf80f4bSopenharmony_ci { 518bf80f4bSopenharmony_ci const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr.GetShaderManager(); 528bf80f4bSopenharmony_ci renderData_ = {}; 538bf80f4bSopenharmony_ci renderData_.shader = shaderMgr.GetShaderHandle("rendershaders://shader/fullscreen_blur.shader"); 548bf80f4bSopenharmony_ci renderData_.pipelineLayout = shaderMgr.GetReflectionPipelineLayout(renderData_.shader); 558bf80f4bSopenharmony_ci } 568bf80f4bSopenharmony_ci { 578bf80f4bSopenharmony_ci imageData_ = {}; 588bf80f4bSopenharmony_ci imageData_.mipImage = blurInfo.blurTarget.handle; 598bf80f4bSopenharmony_ci samplerHandle_ = renderNodeContextMgr.GetGpuResourceManager().GetSamplerHandle( 608bf80f4bSopenharmony_ci DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP); 618bf80f4bSopenharmony_ci } 628bf80f4bSopenharmony_ci { 638bf80f4bSopenharmony_ci constexpr uint32_t globalSet = 0u; 648bf80f4bSopenharmony_ci constexpr uint32_t localSet = 1u; 658bf80f4bSopenharmony_ci 668bf80f4bSopenharmony_ci constexpr uint32_t maxBinderCount = MAX_MIP_COUNT * MAX_PASS_PER_LEVEL_COUNT; 678bf80f4bSopenharmony_ci binders_.clear(); 688bf80f4bSopenharmony_ci binders_.resize(maxBinderCount); 698bf80f4bSopenharmony_ci 708bf80f4bSopenharmony_ci INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr.GetDescriptorSetManager(); 718bf80f4bSopenharmony_ci { 728bf80f4bSopenharmony_ci const auto& bindings = renderData_.pipelineLayout.descriptorSetLayouts[globalSet].bindings; 738bf80f4bSopenharmony_ci const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings); 748bf80f4bSopenharmony_ci globalSet0_ = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings); 758bf80f4bSopenharmony_ci } 768bf80f4bSopenharmony_ci const auto& bindings = renderData_.pipelineLayout.descriptorSetLayouts[localSet].bindings; 778bf80f4bSopenharmony_ci for (uint32_t idx = 0; idx < maxBinderCount; ++idx) { 788bf80f4bSopenharmony_ci const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings); 798bf80f4bSopenharmony_ci binders_[idx] = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings); 808bf80f4bSopenharmony_ci } 818bf80f4bSopenharmony_ci } 828bf80f4bSopenharmony_ci} 838bf80f4bSopenharmony_ci 848bf80f4bSopenharmony_civoid RenderBlur::PreExecute( 858bf80f4bSopenharmony_ci IRenderNodeContextManager& renderNodeContextMgr, const BlurInfo& blurInfo, const PostProcessConfiguration& ppConfig) 868bf80f4bSopenharmony_ci{ 878bf80f4bSopenharmony_ci blurInfo_ = blurInfo; 888bf80f4bSopenharmony_ci imageData_.mipImage = blurInfo.blurTarget.handle; 898bf80f4bSopenharmony_ci globalUbo_ = blurInfo.globalUbo; 908bf80f4bSopenharmony_ci 918bf80f4bSopenharmony_ci const IRenderNodeGpuResourceManager& gpuResourceMgr = renderNodeContextMgr.GetGpuResourceManager(); 928bf80f4bSopenharmony_ci const GpuImageDesc imageDesc = gpuResourceMgr.GetImageDescriptor(imageData_.mipImage); 938bf80f4bSopenharmony_ci imageData_.mipCount = imageDesc.mipCount; 948bf80f4bSopenharmony_ci imageData_.format = imageDesc.format; 958bf80f4bSopenharmony_ci imageData_.size = { imageDesc.width, imageDesc.height }; 968bf80f4bSopenharmony_ci if (GAUSSIAN_TYPE) { 978bf80f4bSopenharmony_ci CreateTargets(renderNodeContextMgr, imageData_.size); 988bf80f4bSopenharmony_ci } 998bf80f4bSopenharmony_ci} 1008bf80f4bSopenharmony_ci 1018bf80f4bSopenharmony_civoid RenderBlur::Execute(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList, 1028bf80f4bSopenharmony_ci const PostProcessConfiguration& ppConfig) 1038bf80f4bSopenharmony_ci{ 1048bf80f4bSopenharmony_ci if (!RenderHandleUtil::IsGpuImage(imageData_.mipImage)) { 1058bf80f4bSopenharmony_ci return; 1068bf80f4bSopenharmony_ci } 1078bf80f4bSopenharmony_ci 1088bf80f4bSopenharmony_ci UpdateGlobalSet(cmdList); 1098bf80f4bSopenharmony_ci 1108bf80f4bSopenharmony_ci RenderPass renderPass; 1118bf80f4bSopenharmony_ci renderPass.renderPassDesc.attachmentCount = 1; 1128bf80f4bSopenharmony_ci renderPass.renderPassDesc.renderArea = { 0, 0, imageData_.size.x, imageData_.size.y }; 1138bf80f4bSopenharmony_ci renderPass.renderPassDesc.subpassCount = 1; 1148bf80f4bSopenharmony_ci renderPass.renderPassDesc.attachments[0].loadOp = CORE_ATTACHMENT_LOAD_OP_DONT_CARE; 1158bf80f4bSopenharmony_ci renderPass.renderPassDesc.attachments[0].storeOp = CORE_ATTACHMENT_STORE_OP_STORE; 1168bf80f4bSopenharmony_ci renderPass.renderPassDesc.attachmentHandles[0] = imageData_.mipImage; 1178bf80f4bSopenharmony_ci renderPass.subpassStartIndex = 0; 1188bf80f4bSopenharmony_ci auto& subpass = renderPass.subpassDesc; 1198bf80f4bSopenharmony_ci subpass.colorAttachmentCount = 1; 1208bf80f4bSopenharmony_ci subpass.colorAttachmentIndices[0] = 0; 1218bf80f4bSopenharmony_ci 1228bf80f4bSopenharmony_ci if (!RenderHandleUtil::IsValid(renderData_.psoScale)) { 1238bf80f4bSopenharmony_ci const auto& shaderMgr = renderNodeContextMgr.GetShaderManager(); 1248bf80f4bSopenharmony_ci const ShaderSpecializationConstantView sscv = shaderMgr.GetReflectionSpecialization(renderData_.shader); 1258bf80f4bSopenharmony_ci const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(renderData_.shader); 1268bf80f4bSopenharmony_ci { 1278bf80f4bSopenharmony_ci const uint32_t specializationFlags[] = { blurInfo_.scaleType }; 1288bf80f4bSopenharmony_ci const ShaderSpecializationConstantDataView specDataView { sscv.constants, specializationFlags }; 1298bf80f4bSopenharmony_ci renderData_.psoScale = 1308bf80f4bSopenharmony_ci renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(renderData_.shader, graphicsState, 1318bf80f4bSopenharmony_ci renderData_.pipelineLayout, {}, specDataView, { DYNAMIC_STATES, countof(DYNAMIC_STATES) }); 1328bf80f4bSopenharmony_ci } 1338bf80f4bSopenharmony_ci { 1348bf80f4bSopenharmony_ci const uint32_t specializationFlags[] = { blurInfo_.blurType }; 1358bf80f4bSopenharmony_ci const ShaderSpecializationConstantDataView specDataView { sscv.constants, specializationFlags }; 1368bf80f4bSopenharmony_ci renderData_.psoBlur = 1378bf80f4bSopenharmony_ci renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(renderData_.shader, graphicsState, 1388bf80f4bSopenharmony_ci renderData_.pipelineLayout, {}, specDataView, { DYNAMIC_STATES, countof(DYNAMIC_STATES) }); 1398bf80f4bSopenharmony_ci } 1408bf80f4bSopenharmony_ci } 1418bf80f4bSopenharmony_ci 1428bf80f4bSopenharmony_ci if (GAUSSIAN_TYPE) { 1438bf80f4bSopenharmony_ci RenderGaussian(renderNodeContextMgr, cmdList, renderPass, ppConfig); 1448bf80f4bSopenharmony_ci } else { 1458bf80f4bSopenharmony_ci RenderData(renderNodeContextMgr, cmdList, renderPass, ppConfig); 1468bf80f4bSopenharmony_ci } 1478bf80f4bSopenharmony_ci} 1488bf80f4bSopenharmony_ci 1498bf80f4bSopenharmony_civoid RenderBlur::UpdateGlobalSet(IRenderCommandList& cmdList) 1508bf80f4bSopenharmony_ci{ 1518bf80f4bSopenharmony_ci auto& binder = *globalSet0_; 1528bf80f4bSopenharmony_ci binder.ClearBindings(); 1538bf80f4bSopenharmony_ci uint32_t binding = 0u; 1548bf80f4bSopenharmony_ci binder.BindBuffer(binding++, globalUbo_, 0); 1558bf80f4bSopenharmony_ci binder.BindBuffer(binding++, globalUbo_, sizeof(GlobalPostProcessStruct)); 1568bf80f4bSopenharmony_ci cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources()); 1578bf80f4bSopenharmony_ci} 1588bf80f4bSopenharmony_ci 1598bf80f4bSopenharmony_ciDescriptorCounts RenderBlur::GetDescriptorCounts() const 1608bf80f4bSopenharmony_ci{ 1618bf80f4bSopenharmony_ci // expected high max mip count 1628bf80f4bSopenharmony_ci return DescriptorCounts { { 1638bf80f4bSopenharmony_ci { CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MAX_MIP_COUNT }, 1648bf80f4bSopenharmony_ci { CORE_DESCRIPTOR_TYPE_SAMPLER, MAX_MIP_COUNT }, 1658bf80f4bSopenharmony_ci { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u * MAX_MIP_COUNT }, 1668bf80f4bSopenharmony_ci } }; 1678bf80f4bSopenharmony_ci} 1688bf80f4bSopenharmony_ci 1698bf80f4bSopenharmony_ci// constants for RenderBlur::RenderData 1708bf80f4bSopenharmony_cinamespace { 1718bf80f4bSopenharmony_ciconstexpr bool USE_CUSTOM_BARRIERS = true; 1728bf80f4bSopenharmony_ci 1738bf80f4bSopenharmony_ciconstexpr ImageResourceBarrier SRC_UNDEFINED { 0, CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, CORE_IMAGE_LAYOUT_UNDEFINED }; 1748bf80f4bSopenharmony_ciconstexpr ImageResourceBarrier COL_ATTACHMENT { CORE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 1758bf80f4bSopenharmony_ci CORE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, CORE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; 1768bf80f4bSopenharmony_ciconstexpr ImageResourceBarrier SHDR_READ { CORE_ACCESS_SHADER_READ_BIT, CORE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 1778bf80f4bSopenharmony_ci CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; 1788bf80f4bSopenharmony_ci// transition the final mip level to read only as well 1798bf80f4bSopenharmony_ciconstexpr ImageResourceBarrier FINAL_SRC { CORE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, 1808bf80f4bSopenharmony_ci CORE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | CORE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 1818bf80f4bSopenharmony_ci CORE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL }; 1828bf80f4bSopenharmony_ciconstexpr ImageResourceBarrier FINAL_DST { CORE_ACCESS_SHADER_READ_BIT, 1838bf80f4bSopenharmony_ci CORE_PIPELINE_STAGE_VERTEX_SHADER_BIT, // first possible shader read stage 1848bf80f4bSopenharmony_ci CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL }; 1858bf80f4bSopenharmony_ci} // namespace 1868bf80f4bSopenharmony_ci 1878bf80f4bSopenharmony_civoid RenderBlur::RenderData(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList, 1888bf80f4bSopenharmony_ci const RenderPass& renderPassBase, const PostProcessConfiguration& ppConfig) 1898bf80f4bSopenharmony_ci{ 1908bf80f4bSopenharmony_ci RenderPass renderPass = renderPassBase; 1918bf80f4bSopenharmony_ci const GpuImageDesc imageDesc = renderNodeContextMgr.GetGpuResourceManager().GetImageDescriptor(imageData_.mipImage); 1928bf80f4bSopenharmony_ci 1938bf80f4bSopenharmony_ci if (USE_CUSTOM_BARRIERS) { 1948bf80f4bSopenharmony_ci cmdList.BeginDisableAutomaticBarrierPoints(); 1958bf80f4bSopenharmony_ci } 1968bf80f4bSopenharmony_ci 1978bf80f4bSopenharmony_ci RenderHandle sets[2u] {}; 1988bf80f4bSopenharmony_ci sets[0] = globalSet0_->GetDescriptorSetHandle(); 1998bf80f4bSopenharmony_ci 2008bf80f4bSopenharmony_ci const uint32_t blurCount = Math::min(ppConfig.blurConfiguration.maxMipLevel, imageData_.mipCount); 2018bf80f4bSopenharmony_ci // NOTE: for smoother results, first downscale -> then horiz / vert -> downscale and so on 2028bf80f4bSopenharmony_ci ImageSubresourceRange imageSubresourceRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2038bf80f4bSopenharmony_ci PipelineStateConstants::GPU_IMAGE_ALL_LAYERS }; 2048bf80f4bSopenharmony_ci for (uint32_t idx = 1; idx < blurCount; ++idx) { 2058bf80f4bSopenharmony_ci const uint32_t renderPassMipLevel = blurInfo_.upScale ? (blurCount - idx - 1) : idx; 2068bf80f4bSopenharmony_ci const uint32_t inputMipLevel = blurInfo_.upScale ? (blurCount - idx) : (idx - 1); 2078bf80f4bSopenharmony_ci 2088bf80f4bSopenharmony_ci const uint32_t currWidth = Math::max(1u, imageDesc.width >> renderPassMipLevel); 2098bf80f4bSopenharmony_ci const uint32_t currHeight = Math::max(1u, imageDesc.height >> renderPassMipLevel); 2108bf80f4bSopenharmony_ci const float fCurrWidth = static_cast<float>(currWidth); 2118bf80f4bSopenharmony_ci const float fCurrHeight = static_cast<float>(currHeight); 2128bf80f4bSopenharmony_ci 2138bf80f4bSopenharmony_ci renderPass.renderPassDesc.renderArea = { 0, 0, currWidth, currHeight }; 2148bf80f4bSopenharmony_ci renderPass.renderPassDesc.attachments[0].mipLevel = renderPassMipLevel; 2158bf80f4bSopenharmony_ci 2168bf80f4bSopenharmony_ci if (USE_CUSTOM_BARRIERS) { 2178bf80f4bSopenharmony_ci imageSubresourceRange.baseMipLevel = renderPassMipLevel; 2188bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(imageData_.mipImage, SRC_UNDEFINED, COL_ATTACHMENT, imageSubresourceRange); 2198bf80f4bSopenharmony_ci imageSubresourceRange.baseMipLevel = inputMipLevel; 2208bf80f4bSopenharmony_ci if (inputMipLevel == 0) { 2218bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(imageData_.mipImage, SHDR_READ, imageSubresourceRange); 2228bf80f4bSopenharmony_ci } else { 2238bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(imageData_.mipImage, COL_ATTACHMENT, SHDR_READ, imageSubresourceRange); 2248bf80f4bSopenharmony_ci } 2258bf80f4bSopenharmony_ci cmdList.AddCustomBarrierPoint(); 2268bf80f4bSopenharmony_ci } 2278bf80f4bSopenharmony_ci 2288bf80f4bSopenharmony_ci cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc); 2298bf80f4bSopenharmony_ci 2308bf80f4bSopenharmony_ci cmdList.SetDynamicStateViewport(ViewportDesc { 0.0f, 0.0f, fCurrWidth, fCurrHeight, 0.0f, 0.0f }); 2318bf80f4bSopenharmony_ci cmdList.SetDynamicStateScissor(ScissorDesc { 0, 0, currWidth, currHeight }); 2328bf80f4bSopenharmony_ci 2338bf80f4bSopenharmony_ci cmdList.BindPipeline(renderData_.psoScale); 2348bf80f4bSopenharmony_ci 2358bf80f4bSopenharmony_ci { 2368bf80f4bSopenharmony_ci auto& binder = *binders_[idx]; 2378bf80f4bSopenharmony_ci sets[1u] = binder.GetDescriptorSetHandle(); 2388bf80f4bSopenharmony_ci binder.ClearBindings(); 2398bf80f4bSopenharmony_ci binder.BindSampler(0, samplerHandle_); 2408bf80f4bSopenharmony_ci binder.BindImage(1, { imageData_.mipImage, inputMipLevel }); 2418bf80f4bSopenharmony_ci cmdList.UpdateDescriptorSet( 2428bf80f4bSopenharmony_ci binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources()); 2438bf80f4bSopenharmony_ci } 2448bf80f4bSopenharmony_ci cmdList.BindDescriptorSets(0u, sets); 2458bf80f4bSopenharmony_ci 2468bf80f4bSopenharmony_ci const LocalPostProcessPushConstantStruct pc { 2478bf80f4bSopenharmony_ci { fCurrWidth, fCurrHeight, 1.0f / (fCurrWidth), 1.0f / (fCurrHeight) }, { 1.0f, 0.0f, 0.0f, 0.0f } 2488bf80f4bSopenharmony_ci }; 2498bf80f4bSopenharmony_ci cmdList.PushConstant(renderData_.pipelineLayout.pushConstant, reinterpret_cast<const uint8_t*>(&pc)); 2508bf80f4bSopenharmony_ci 2518bf80f4bSopenharmony_ci cmdList.Draw(3u, 1u, 0u, 0u); 2528bf80f4bSopenharmony_ci cmdList.EndRenderPass(); 2538bf80f4bSopenharmony_ci } 2548bf80f4bSopenharmony_ci 2558bf80f4bSopenharmony_ci if (USE_CUSTOM_BARRIERS) { 2568bf80f4bSopenharmony_ci if (imageData_.mipCount > 1u) { 2578bf80f4bSopenharmony_ci // transition the final used mip level 2588bf80f4bSopenharmony_ci if (blurCount > 0) { 2598bf80f4bSopenharmony_ci const ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, blurCount - 1, 1, 0, 2608bf80f4bSopenharmony_ci PipelineStateConstants::GPU_IMAGE_ALL_LAYERS }; 2618bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(imageData_.mipImage, FINAL_SRC, FINAL_DST, imgRange); 2628bf80f4bSopenharmony_ci } 2638bf80f4bSopenharmony_ci if (blurCount < imageData_.mipCount) { 2648bf80f4bSopenharmony_ci // transition the final levels which might be in undefined state 2658bf80f4bSopenharmony_ci const ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, blurCount, 2668bf80f4bSopenharmony_ci imageData_.mipCount - blurCount, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS }; 2678bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(imageData_.mipImage, SRC_UNDEFINED, FINAL_DST, imgRange); 2688bf80f4bSopenharmony_ci } 2698bf80f4bSopenharmony_ci } 2708bf80f4bSopenharmony_ci cmdList.AddCustomBarrierPoint(); 2718bf80f4bSopenharmony_ci cmdList.EndDisableAutomaticBarrierPoints(); 2728bf80f4bSopenharmony_ci } 2738bf80f4bSopenharmony_ci} 2748bf80f4bSopenharmony_ci 2758bf80f4bSopenharmony_cinamespace { 2768bf80f4bSopenharmony_civoid DownscaleBarrier(IRenderCommandList& cmdList, const RenderHandle image, const uint32_t mipLevel) 2778bf80f4bSopenharmony_ci{ 2788bf80f4bSopenharmony_ci ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2798bf80f4bSopenharmony_ci PipelineStateConstants::GPU_IMAGE_ALL_LAYERS }; 2808bf80f4bSopenharmony_ci imgRange.baseMipLevel = mipLevel; 2818bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(image, SRC_UNDEFINED, COL_ATTACHMENT, imgRange); 2828bf80f4bSopenharmony_ci const uint32_t inputMipLevel = mipLevel - 1u; 2838bf80f4bSopenharmony_ci imgRange.baseMipLevel = inputMipLevel; 2848bf80f4bSopenharmony_ci if (inputMipLevel == 0) { 2858bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(image, SHDR_READ, imgRange); 2868bf80f4bSopenharmony_ci } else { 2878bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(image, COL_ATTACHMENT, SHDR_READ, imgRange); 2888bf80f4bSopenharmony_ci } 2898bf80f4bSopenharmony_ci cmdList.AddCustomBarrierPoint(); 2908bf80f4bSopenharmony_ci} 2918bf80f4bSopenharmony_ci 2928bf80f4bSopenharmony_civoid BlurHorizontalBarrier( 2938bf80f4bSopenharmony_ci IRenderCommandList& cmdList, const RenderHandle realImage, const uint32_t mipLevel, const RenderHandle tmpImage) 2948bf80f4bSopenharmony_ci{ 2958bf80f4bSopenharmony_ci ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 2968bf80f4bSopenharmony_ci PipelineStateConstants::GPU_IMAGE_ALL_LAYERS }; 2978bf80f4bSopenharmony_ci imgRange.baseMipLevel = mipLevel; 2988bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(realImage, COL_ATTACHMENT, SHDR_READ, imgRange); 2998bf80f4bSopenharmony_ci imgRange.baseMipLevel = mipLevel - 1; 3008bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(tmpImage, SRC_UNDEFINED, COL_ATTACHMENT, imgRange); 3018bf80f4bSopenharmony_ci cmdList.AddCustomBarrierPoint(); 3028bf80f4bSopenharmony_ci} 3038bf80f4bSopenharmony_ci 3048bf80f4bSopenharmony_civoid BlurVerticalBarrier( 3058bf80f4bSopenharmony_ci IRenderCommandList& cmdList, const RenderHandle realImage, const uint32_t mipLevel, const RenderHandle tmpImage) 3068bf80f4bSopenharmony_ci{ 3078bf80f4bSopenharmony_ci ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 3088bf80f4bSopenharmony_ci PipelineStateConstants::GPU_IMAGE_ALL_LAYERS }; 3098bf80f4bSopenharmony_ci imgRange.baseMipLevel = mipLevel; 3108bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(realImage, SHDR_READ, COL_ATTACHMENT, imgRange); 3118bf80f4bSopenharmony_ci imgRange.baseMipLevel = mipLevel - 1; 3128bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(tmpImage, COL_ATTACHMENT, SHDR_READ, imgRange); 3138bf80f4bSopenharmony_ci cmdList.AddCustomBarrierPoint(); 3148bf80f4bSopenharmony_ci} 3158bf80f4bSopenharmony_ci 3168bf80f4bSopenharmony_cistruct ConstDrawInput { 3178bf80f4bSopenharmony_ci IRenderCommandList& cmdList; 3188bf80f4bSopenharmony_ci const RenderPass& renderPass; 3198bf80f4bSopenharmony_ci const PushConstant& pushConstant; 3208bf80f4bSopenharmony_ci const LocalPostProcessPushConstantStruct& pc; 3218bf80f4bSopenharmony_ci RenderHandle sampler; 3228bf80f4bSopenharmony_ci}; 3238bf80f4bSopenharmony_civoid BlurPass(const ConstDrawInput& di, IDescriptorSetBinder& binder, IDescriptorSetBinder& globalBinder, 3248bf80f4bSopenharmony_ci const RenderHandle psoHandle, const RenderHandle image, const uint32_t inputMipLevel) 3258bf80f4bSopenharmony_ci{ 3268bf80f4bSopenharmony_ci di.cmdList.BeginRenderPass( 3278bf80f4bSopenharmony_ci di.renderPass.renderPassDesc, di.renderPass.subpassStartIndex, di.renderPass.subpassDesc); 3288bf80f4bSopenharmony_ci di.cmdList.BindPipeline(psoHandle); 3298bf80f4bSopenharmony_ci 3308bf80f4bSopenharmony_ci RenderHandle sets[2u] {}; 3318bf80f4bSopenharmony_ci sets[0] = globalBinder.GetDescriptorSetHandle(); 3328bf80f4bSopenharmony_ci { 3338bf80f4bSopenharmony_ci binder.ClearBindings(); 3348bf80f4bSopenharmony_ci sets[1u] = binder.GetDescriptorSetHandle(); 3358bf80f4bSopenharmony_ci binder.BindSampler(0, di.sampler); 3368bf80f4bSopenharmony_ci binder.BindImage(1u, { image, inputMipLevel }); 3378bf80f4bSopenharmony_ci di.cmdList.UpdateDescriptorSet( 3388bf80f4bSopenharmony_ci binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources()); 3398bf80f4bSopenharmony_ci } 3408bf80f4bSopenharmony_ci di.cmdList.BindDescriptorSets(0, sets); 3418bf80f4bSopenharmony_ci 3428bf80f4bSopenharmony_ci di.cmdList.PushConstant(di.pushConstant, reinterpret_cast<const uint8_t*>(&di.pc)); 3438bf80f4bSopenharmony_ci di.cmdList.Draw(3u, 1u, 0u, 0u); 3448bf80f4bSopenharmony_ci di.cmdList.EndRenderPass(); 3458bf80f4bSopenharmony_ci} 3468bf80f4bSopenharmony_ci} // namespace 3478bf80f4bSopenharmony_ci 3488bf80f4bSopenharmony_civoid RenderBlur::RenderGaussian(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList, 3498bf80f4bSopenharmony_ci const RenderPass& renderPassBase, const PostProcessConfiguration& ppConfig) 3508bf80f4bSopenharmony_ci{ 3518bf80f4bSopenharmony_ci RenderPass renderPass = renderPassBase; 3528bf80f4bSopenharmony_ci if (USE_CUSTOM_BARRIERS) { 3538bf80f4bSopenharmony_ci cmdList.BeginDisableAutomaticBarrierPoints(); 3548bf80f4bSopenharmony_ci } 3558bf80f4bSopenharmony_ci 3568bf80f4bSopenharmony_ci // with every mip, first we do a downscale 3578bf80f4bSopenharmony_ci // then a single horizontal and a single vertical blur 3588bf80f4bSopenharmony_ci LocalPostProcessPushConstantStruct pc { { 1.0f, 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 0.0f } }; 3598bf80f4bSopenharmony_ci uint32_t descIdx = 0; 3608bf80f4bSopenharmony_ci const uint32_t blurCount = Math::min(ppConfig.blurConfiguration.maxMipLevel, imageData_.mipCount); 3618bf80f4bSopenharmony_ci const ConstDrawInput di { cmdList, renderPass, renderData_.pipelineLayout.pushConstant, pc, samplerHandle_ }; 3628bf80f4bSopenharmony_ci for (uint32_t idx = 1; idx < blurCount; ++idx) { 3638bf80f4bSopenharmony_ci const uint32_t mip = idx; 3648bf80f4bSopenharmony_ci 3658bf80f4bSopenharmony_ci const Math::UVec2 size = { Math::max(1u, imageData_.size.x >> mip), Math::max(1u, imageData_.size.y >> mip) }; 3668bf80f4bSopenharmony_ci const Math::Vec2 fSize = { static_cast<float>(size.x), static_cast<float>(size.y) }; 3678bf80f4bSopenharmony_ci const Math::Vec4 texSizeInvTexSize { fSize.x * 1.0f, fSize.y * 1.0f, 1.0f / fSize.x, 1.0f / fSize.y }; 3688bf80f4bSopenharmony_ci pc = { texSizeInvTexSize, { 1.0f, 0.0f, 0.0f, 0.0f } }; 3698bf80f4bSopenharmony_ci 3708bf80f4bSopenharmony_ci renderPass.renderPassDesc.renderArea = { 0, 0, size.x, size.y }; 3718bf80f4bSopenharmony_ci renderPass.renderPassDesc.attachments[0].mipLevel = mip; 3728bf80f4bSopenharmony_ci 3738bf80f4bSopenharmony_ci cmdList.SetDynamicStateViewport({ 0.0f, 0.0f, fSize.x, fSize.y, 0.0f, 1.0f }); 3748bf80f4bSopenharmony_ci cmdList.SetDynamicStateScissor({ 0, 0, size.x, size.y }); 3758bf80f4bSopenharmony_ci 3768bf80f4bSopenharmony_ci // downscale 3778bf80f4bSopenharmony_ci if (USE_CUSTOM_BARRIERS) { 3788bf80f4bSopenharmony_ci DownscaleBarrier(cmdList, imageData_.mipImage, mip); 3798bf80f4bSopenharmony_ci } 3808bf80f4bSopenharmony_ci BlurPass(di, *binders_[descIdx++], *globalSet0_, renderData_.psoScale, imageData_.mipImage, mip - 1u); 3818bf80f4bSopenharmony_ci 3828bf80f4bSopenharmony_ci // horizontal (from real image to temp) 3838bf80f4bSopenharmony_ci if (USE_CUSTOM_BARRIERS) { 3848bf80f4bSopenharmony_ci BlurHorizontalBarrier(cmdList, imageData_.mipImage, mip, tempTarget_.tex.GetHandle()); 3858bf80f4bSopenharmony_ci } 3868bf80f4bSopenharmony_ci 3878bf80f4bSopenharmony_ci renderPass.renderPassDesc.attachmentHandles[0] = tempTarget_.tex.GetHandle(); 3888bf80f4bSopenharmony_ci renderPass.renderPassDesc.attachments[0].mipLevel = mip - 1u; 3898bf80f4bSopenharmony_ci BlurPass(di, *binders_[descIdx++], *globalSet0_, renderData_.psoBlur, imageData_.mipImage, mip); 3908bf80f4bSopenharmony_ci 3918bf80f4bSopenharmony_ci // vertical 3928bf80f4bSopenharmony_ci if (USE_CUSTOM_BARRIERS) { 3938bf80f4bSopenharmony_ci BlurVerticalBarrier(cmdList, imageData_.mipImage, mip, tempTarget_.tex.GetHandle()); 3948bf80f4bSopenharmony_ci } 3958bf80f4bSopenharmony_ci 3968bf80f4bSopenharmony_ci renderPass.renderPassDesc.attachmentHandles[0] = imageData_.mipImage; 3978bf80f4bSopenharmony_ci renderPass.renderPassDesc.attachments[0].mipLevel = mip; 3988bf80f4bSopenharmony_ci pc.factor = { 0.0f, 1.0f, 0.0f, 0.0f }; 3998bf80f4bSopenharmony_ci BlurPass(di, *binders_[descIdx++], *globalSet0_, renderData_.psoBlur, tempTarget_.tex.GetHandle(), mip - 1); 4008bf80f4bSopenharmony_ci } 4018bf80f4bSopenharmony_ci 4028bf80f4bSopenharmony_ci if (USE_CUSTOM_BARRIERS) { 4038bf80f4bSopenharmony_ci if (imageData_.mipCount > 1u) { 4048bf80f4bSopenharmony_ci // transition the final used mip level 4058bf80f4bSopenharmony_ci if (blurCount > 0) { 4068bf80f4bSopenharmony_ci const ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, blurCount - 1, 1, 0, 4078bf80f4bSopenharmony_ci PipelineStateConstants::GPU_IMAGE_ALL_LAYERS }; 4088bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(imageData_.mipImage, FINAL_SRC, FINAL_DST, imgRange); 4098bf80f4bSopenharmony_ci } 4108bf80f4bSopenharmony_ci if (blurCount < imageData_.mipCount) { 4118bf80f4bSopenharmony_ci // transition the final levels which might be in undefined state 4128bf80f4bSopenharmony_ci const ImageSubresourceRange imgRange { CORE_IMAGE_ASPECT_COLOR_BIT, blurCount, 4138bf80f4bSopenharmony_ci imageData_.mipCount - blurCount, 0, PipelineStateConstants::GPU_IMAGE_ALL_LAYERS }; 4148bf80f4bSopenharmony_ci cmdList.CustomImageBarrier(imageData_.mipImage, SRC_UNDEFINED, FINAL_DST, imgRange); 4158bf80f4bSopenharmony_ci } 4168bf80f4bSopenharmony_ci } 4178bf80f4bSopenharmony_ci cmdList.AddCustomBarrierPoint(); 4188bf80f4bSopenharmony_ci cmdList.EndDisableAutomaticBarrierPoints(); 4198bf80f4bSopenharmony_ci } 4208bf80f4bSopenharmony_ci} 4218bf80f4bSopenharmony_ci 4228bf80f4bSopenharmony_civoid RenderBlur::CreateTargets(IRenderNodeContextManager& renderNodeContextMgr, const Math::UVec2 baseSize) 4238bf80f4bSopenharmony_ci{ 4248bf80f4bSopenharmony_ci Math::UVec2 texSize = baseSize / 2u; 4258bf80f4bSopenharmony_ci texSize.x = Math::max(1u, texSize.x); 4268bf80f4bSopenharmony_ci texSize.y = Math::max(1u, texSize.y); 4278bf80f4bSopenharmony_ci if (texSize.x != tempTarget_.texSize.x || texSize.y != tempTarget_.texSize.y) { 4288bf80f4bSopenharmony_ci tempTarget_.texSize = texSize; 4298bf80f4bSopenharmony_ci tempTarget_.format = imageData_.format; 4308bf80f4bSopenharmony_ci 4318bf80f4bSopenharmony_ci constexpr ImageUsageFlags usageFlags = ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | 4328bf80f4bSopenharmony_ci ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT | 4338bf80f4bSopenharmony_ci ImageUsageFlagBits::CORE_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; 4348bf80f4bSopenharmony_ci 4358bf80f4bSopenharmony_ci const GpuImageDesc desc { 4368bf80f4bSopenharmony_ci ImageType::CORE_IMAGE_TYPE_2D, 4378bf80f4bSopenharmony_ci ImageViewType::CORE_IMAGE_VIEW_TYPE_2D, 4388bf80f4bSopenharmony_ci tempTarget_.format, 4398bf80f4bSopenharmony_ci ImageTiling::CORE_IMAGE_TILING_OPTIMAL, 4408bf80f4bSopenharmony_ci usageFlags, 4418bf80f4bSopenharmony_ci MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 4428bf80f4bSopenharmony_ci 0, 4438bf80f4bSopenharmony_ci EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS, 4448bf80f4bSopenharmony_ci tempTarget_.texSize.x, 4458bf80f4bSopenharmony_ci tempTarget_.texSize.y, 4468bf80f4bSopenharmony_ci 1u, 4478bf80f4bSopenharmony_ci Math::max(1u, (imageData_.mipCount - 1u)), 4488bf80f4bSopenharmony_ci 1u, 4498bf80f4bSopenharmony_ci SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT, 4508bf80f4bSopenharmony_ci {}, 4518bf80f4bSopenharmony_ci }; 4528bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1) 4538bf80f4bSopenharmony_ci tempTarget_.tex = 4548bf80f4bSopenharmony_ci renderNodeContextMgr.GetGpuResourceManager().Create(renderNodeContextMgr.GetName() + "_BLUR_TARGET", desc); 4558bf80f4bSopenharmony_ci#else 4568bf80f4bSopenharmony_ci tempTarget_.tex = renderNodeContextMgr.GetGpuResourceManager().Create(tempTarget_.tex, desc); 4578bf80f4bSopenharmony_ci#endif 4588bf80f4bSopenharmony_ci } 4598bf80f4bSopenharmony_ci} 4608bf80f4bSopenharmony_ciRENDER_END_NAMESPACE() 461