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_bloom.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <base/containers/fixed_string.h>
198bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h>
208bf80f4bSopenharmony_ci#include <base/math/vector.h>
218bf80f4bSopenharmony_ci#include <render/datastore/intf_render_data_store_manager.h>
228bf80f4bSopenharmony_ci#include <render/datastore/intf_render_data_store_pod.h>
238bf80f4bSopenharmony_ci#include <render/datastore/render_data_store_render_pods.h>
248bf80f4bSopenharmony_ci#include <render/device/intf_gpu_resource_manager.h>
258bf80f4bSopenharmony_ci#include <render/device/intf_shader_manager.h>
268bf80f4bSopenharmony_ci#include <render/namespace.h>
278bf80f4bSopenharmony_ci#include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
288bf80f4bSopenharmony_ci#include <render/nodecontext/intf_node_context_pso_manager.h>
298bf80f4bSopenharmony_ci#include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
308bf80f4bSopenharmony_ci#include <render/nodecontext/intf_render_command_list.h>
318bf80f4bSopenharmony_ci#include <render/nodecontext/intf_render_node_context_manager.h>
328bf80f4bSopenharmony_ci#include <render/nodecontext/intf_render_node_util.h>
338bf80f4bSopenharmony_ci
348bf80f4bSopenharmony_ci#include "util/log.h"
358bf80f4bSopenharmony_ci
368bf80f4bSopenharmony_ci// shaders
378bf80f4bSopenharmony_ci#include <render/shaders/common/render_post_process_structs_common.h>
388bf80f4bSopenharmony_ci
398bf80f4bSopenharmony_ciusing namespace BASE_NS;
408bf80f4bSopenharmony_ci
418bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE()
428bf80f4bSopenharmony_cinamespace {
438bf80f4bSopenharmony_ciconstexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
448bf80f4bSopenharmony_ci}
458bf80f4bSopenharmony_ci
468bf80f4bSopenharmony_civoid RenderBloom::Init(IRenderNodeContextManager& renderNodeContextMgr, const BloomInfo& bloomInfo)
478bf80f4bSopenharmony_ci{
488bf80f4bSopenharmony_ci    bloomInfo_ = bloomInfo;
498bf80f4bSopenharmony_ci
508bf80f4bSopenharmony_ci    // NOTE: target counts etc. should probably be resized based on configuration
518bf80f4bSopenharmony_ci    CreatePsos(renderNodeContextMgr);
528bf80f4bSopenharmony_ci
538bf80f4bSopenharmony_ci    auto& gpuResourceMgr = renderNodeContextMgr.GetGpuResourceManager();
548bf80f4bSopenharmony_ci    samplerHandle_ = gpuResourceMgr.Create(samplerHandle_,
558bf80f4bSopenharmony_ci        GpuSamplerDesc {
568bf80f4bSopenharmony_ci            Filter::CORE_FILTER_LINEAR,                                  // magFilter
578bf80f4bSopenharmony_ci            Filter::CORE_FILTER_LINEAR,                                  // minFilter
588bf80f4bSopenharmony_ci            Filter::CORE_FILTER_LINEAR,                                  // mipMapMode
598bf80f4bSopenharmony_ci            SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
608bf80f4bSopenharmony_ci            SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
618bf80f4bSopenharmony_ci            SamplerAddressMode::CORE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
628bf80f4bSopenharmony_ci        });
638bf80f4bSopenharmony_ci}
648bf80f4bSopenharmony_ci
658bf80f4bSopenharmony_civoid RenderBloom::PreExecute(IRenderNodeContextManager& renderNodeContextMgr, const BloomInfo& bloomInfo,
668bf80f4bSopenharmony_ci    const PostProcessConfiguration& ppConfig)
678bf80f4bSopenharmony_ci{
688bf80f4bSopenharmony_ci    bloomInfo_ = bloomInfo;
698bf80f4bSopenharmony_ci
708bf80f4bSopenharmony_ci    const GpuImageDesc& imgDesc =
718bf80f4bSopenharmony_ci        renderNodeContextMgr.GetGpuResourceManager().GetImageDescriptor(bloomInfo_.input.handle);
728bf80f4bSopenharmony_ci    uint32_t sizeDenom = 1u;
738bf80f4bSopenharmony_ci    if (ppConfig.bloomConfiguration.bloomQualityType == BloomConfiguration::QUALITY_TYPE_LOW) {
748bf80f4bSopenharmony_ci        sizeDenom = 2u;
758bf80f4bSopenharmony_ci    }
768bf80f4bSopenharmony_ci    CreateTargets(renderNodeContextMgr, Math::UVec2(imgDesc.width, imgDesc.height) / sizeDenom);
778bf80f4bSopenharmony_ci}
788bf80f4bSopenharmony_ci
798bf80f4bSopenharmony_civoid RenderBloom::Execute(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList,
808bf80f4bSopenharmony_ci    const PostProcessConfiguration& ppConfig)
818bf80f4bSopenharmony_ci{
828bf80f4bSopenharmony_ci    bloomEnabled_ = false;
838bf80f4bSopenharmony_ci    BloomConfiguration bloomConfiguration;
848bf80f4bSopenharmony_ci    if (ppConfig.enableFlags & PostProcessConfiguration::ENABLE_BLOOM_BIT) {
858bf80f4bSopenharmony_ci        bloomConfiguration.thresholdHard = ppConfig.bloomConfiguration.thresholdHard;
868bf80f4bSopenharmony_ci        bloomConfiguration.thresholdSoft = ppConfig.bloomConfiguration.thresholdSoft;
878bf80f4bSopenharmony_ci        bloomConfiguration.amountCoefficient = ppConfig.bloomConfiguration.amountCoefficient;
888bf80f4bSopenharmony_ci        bloomConfiguration.dirtMaskCoefficient = ppConfig.bloomConfiguration.dirtMaskCoefficient;
898bf80f4bSopenharmony_ci
908bf80f4bSopenharmony_ci        bloomEnabled_ = true;
918bf80f4bSopenharmony_ci    }
928bf80f4bSopenharmony_ci
938bf80f4bSopenharmony_ci    const auto bloomQualityType = ppConfig.bloomConfiguration.bloomQualityType;
948bf80f4bSopenharmony_ci    PLUGIN_ASSERT(bloomQualityType < CORE_BLOOM_QUALITY_COUNT);
958bf80f4bSopenharmony_ci    if (bloomInfo_.useCompute) {
968bf80f4bSopenharmony_ci        psos_.downscale = psos_.downscaleHandlesCompute[bloomQualityType].regular;
978bf80f4bSopenharmony_ci        psos_.downscaleAndThreshold = psos_.downscaleHandlesCompute[bloomQualityType].threshold;
988bf80f4bSopenharmony_ci    } else {
998bf80f4bSopenharmony_ci        psos_.downscale = psos_.downscaleHandles[bloomQualityType].regular;
1008bf80f4bSopenharmony_ci        psos_.downscaleAndThreshold = psos_.downscaleHandles[bloomQualityType].threshold;
1018bf80f4bSopenharmony_ci    }
1028bf80f4bSopenharmony_ci
1038bf80f4bSopenharmony_ci    if (!bloomEnabled_) {
1048bf80f4bSopenharmony_ci        bloomConfiguration.amountCoefficient = 0.0f;
1058bf80f4bSopenharmony_ci    }
1068bf80f4bSopenharmony_ci
1078bf80f4bSopenharmony_ci    bloomParameters_ = Math::Vec4(
1088bf80f4bSopenharmony_ci        // .x = thresholdHard, luma values below this won't bloom
1098bf80f4bSopenharmony_ci        bloomConfiguration.thresholdHard,
1108bf80f4bSopenharmony_ci        // .y = thresholdSoft, luma values from this value to hard threshold will reduce bloom input from 1.0 -> 0.0
1118bf80f4bSopenharmony_ci        // i.e. this creates softer threshold for bloom
1128bf80f4bSopenharmony_ci        bloomConfiguration.thresholdSoft,
1138bf80f4bSopenharmony_ci        // .z = amountCoefficient, will multiply the colors from the bloom textures when combined with original color
1148bf80f4bSopenharmony_ci        // target
1158bf80f4bSopenharmony_ci        bloomConfiguration.amountCoefficient,
1168bf80f4bSopenharmony_ci        // .w = -will multiply the dirt mask effect
1178bf80f4bSopenharmony_ci        bloomConfiguration.dirtMaskCoefficient);
1188bf80f4bSopenharmony_ci
1198bf80f4bSopenharmony_ci    const bool validBinders = binders_.globalSet0.get() != nullptr;
1208bf80f4bSopenharmony_ci    if (validBinders) {
1218bf80f4bSopenharmony_ci        if (bloomInfo_.useCompute) {
1228bf80f4bSopenharmony_ci            ComputeBloom(renderNodeContextMgr, cmdList);
1238bf80f4bSopenharmony_ci        } else {
1248bf80f4bSopenharmony_ci            GraphicsBloom(renderNodeContextMgr, cmdList);
1258bf80f4bSopenharmony_ci        }
1268bf80f4bSopenharmony_ci    }
1278bf80f4bSopenharmony_ci}
1288bf80f4bSopenharmony_ci
1298bf80f4bSopenharmony_ciDescriptorCounts RenderBloom::GetDescriptorCounts() const
1308bf80f4bSopenharmony_ci{
1318bf80f4bSopenharmony_ci    // NOTE: when added support for various bloom target counts, might need to be calculated for max
1328bf80f4bSopenharmony_ci    return DescriptorCounts { {
1338bf80f4bSopenharmony_ci        { CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 32u },
1348bf80f4bSopenharmony_ci        { CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 32u },
1358bf80f4bSopenharmony_ci        { CORE_DESCRIPTOR_TYPE_STORAGE_IMAGE, 32u },
1368bf80f4bSopenharmony_ci        { CORE_DESCRIPTOR_TYPE_SAMPLER, 24u },
1378bf80f4bSopenharmony_ci        { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2u },
1388bf80f4bSopenharmony_ci    } };
1398bf80f4bSopenharmony_ci}
1408bf80f4bSopenharmony_ci
1418bf80f4bSopenharmony_ciRenderHandle RenderBloom::GetFinalTarget() const
1428bf80f4bSopenharmony_ci{
1438bf80f4bSopenharmony_ci    if (RenderHandleUtil::IsValid(bloomInfo_.output.handle)) {
1448bf80f4bSopenharmony_ci        return bloomInfo_.output.handle;
1458bf80f4bSopenharmony_ci    } else {
1468bf80f4bSopenharmony_ci        // output tex1 on compute and tex2 on graphics
1478bf80f4bSopenharmony_ci        return bloomInfo_.useCompute ? (targets_.tex1[0u].GetHandle()) : (targets_.tex2[0u].GetHandle());
1488bf80f4bSopenharmony_ci    }
1498bf80f4bSopenharmony_ci}
1508bf80f4bSopenharmony_ci
1518bf80f4bSopenharmony_civoid RenderBloom::UpdateGlobalSet(IRenderCommandList& cmdList)
1528bf80f4bSopenharmony_ci{
1538bf80f4bSopenharmony_ci    auto& binder = *binders_.globalSet0;
1548bf80f4bSopenharmony_ci    binder.ClearBindings();
1558bf80f4bSopenharmony_ci    uint32_t binding = 0u;
1568bf80f4bSopenharmony_ci    binder.BindBuffer(binding++, bloomInfo_.globalUbo, 0);
1578bf80f4bSopenharmony_ci    binder.BindBuffer(binding++, bloomInfo_.globalUbo, sizeof(GlobalPostProcessStruct));
1588bf80f4bSopenharmony_ci    cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
1598bf80f4bSopenharmony_ci}
1608bf80f4bSopenharmony_ci
1618bf80f4bSopenharmony_civoid RenderBloom::ComputeBloom(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList)
1628bf80f4bSopenharmony_ci{
1638bf80f4bSopenharmony_ci    constexpr PushConstant pc { ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT,
1648bf80f4bSopenharmony_ci        sizeof(LocalPostProcessPushConstantStruct) };
1658bf80f4bSopenharmony_ci
1668bf80f4bSopenharmony_ci    UpdateGlobalSet(cmdList);
1678bf80f4bSopenharmony_ci    if (bloomEnabled_) {
1688bf80f4bSopenharmony_ci        ComputeDownscaleAndThreshold(pc, cmdList);
1698bf80f4bSopenharmony_ci        ComputeDownscale(pc, cmdList);
1708bf80f4bSopenharmony_ci        ComputeUpscale(pc, cmdList);
1718bf80f4bSopenharmony_ci    }
1728bf80f4bSopenharmony_ci    // needs to be done even when bloom is disabled if node is in use
1738bf80f4bSopenharmony_ci    if (RenderHandleUtil::IsValid(bloomInfo_.output.handle)) {
1748bf80f4bSopenharmony_ci        ComputeCombine(pc, cmdList);
1758bf80f4bSopenharmony_ci    }
1768bf80f4bSopenharmony_ci}
1778bf80f4bSopenharmony_ci
1788bf80f4bSopenharmony_civoid RenderBloom::ComputeDownscaleAndThreshold(const PushConstant& pc, IRenderCommandList& cmdList)
1798bf80f4bSopenharmony_ci{
1808bf80f4bSopenharmony_ci    RenderHandle sets[2u] {};
1818bf80f4bSopenharmony_ci    sets[0u] = binders_.globalSet0->GetDescriptorSetHandle();
1828bf80f4bSopenharmony_ci    {
1838bf80f4bSopenharmony_ci        auto& binder = *binders_.downscaleAndThreshold;
1848bf80f4bSopenharmony_ci        sets[1u] = binder.GetDescriptorSetHandle();
1858bf80f4bSopenharmony_ci        binder.ClearBindings();
1868bf80f4bSopenharmony_ci
1878bf80f4bSopenharmony_ci        uint32_t binding = 0;
1888bf80f4bSopenharmony_ci        binder.BindImage(binding++, { targets_.tex1[0].GetHandle() });
1898bf80f4bSopenharmony_ci        binder.BindImage(binding++, { bloomInfo_.input });
1908bf80f4bSopenharmony_ci        binder.BindSampler(binding++, { samplerHandle_.GetHandle() });
1918bf80f4bSopenharmony_ci
1928bf80f4bSopenharmony_ci        cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
1938bf80f4bSopenharmony_ci    }
1948bf80f4bSopenharmony_ci
1958bf80f4bSopenharmony_ci    cmdList.BindPipeline(psos_.downscaleAndThreshold);
1968bf80f4bSopenharmony_ci    const ShaderThreadGroup tgs = psos_.downscaleAndThresholdTGS;
1978bf80f4bSopenharmony_ci
1988bf80f4bSopenharmony_ci    // bind all sets
1998bf80f4bSopenharmony_ci    cmdList.BindDescriptorSets(0, sets);
2008bf80f4bSopenharmony_ci
2018bf80f4bSopenharmony_ci    const auto targetSize = targets_.tex1Size[0];
2028bf80f4bSopenharmony_ci
2038bf80f4bSopenharmony_ci    LocalPostProcessPushConstantStruct uPc;
2048bf80f4bSopenharmony_ci    uPc.factor = bloomParameters_;
2058bf80f4bSopenharmony_ci    uPc.viewportSizeInvSize = Math::Vec4(static_cast<float>(targetSize.x), static_cast<float>(targetSize.y),
2068bf80f4bSopenharmony_ci        1.0f / static_cast<float>(targetSize.x), 1.0f / static_cast<float>(targetSize.y));
2078bf80f4bSopenharmony_ci
2088bf80f4bSopenharmony_ci    cmdList.PushConstantData(pc, arrayviewU8(uPc));
2098bf80f4bSopenharmony_ci
2108bf80f4bSopenharmony_ci    cmdList.Dispatch((targetSize.x + tgs.x - 1) / tgs.x, (targetSize.y + tgs.y - 1) / tgs.y, 1);
2118bf80f4bSopenharmony_ci}
2128bf80f4bSopenharmony_ci
2138bf80f4bSopenharmony_civoid RenderBloom::ComputeDownscale(const PushConstant& pc, IRenderCommandList& cmdList)
2148bf80f4bSopenharmony_ci{
2158bf80f4bSopenharmony_ci    cmdList.BindPipeline(psos_.downscale);
2168bf80f4bSopenharmony_ci    const ShaderThreadGroup tgs = psos_.downscaleTGS;
2178bf80f4bSopenharmony_ci
2188bf80f4bSopenharmony_ci    RenderHandle sets[2u] {};
2198bf80f4bSopenharmony_ci    sets[0u] = binders_.globalSet0->GetDescriptorSetHandle();
2208bf80f4bSopenharmony_ci    for (size_t i = 1; i < targets_.tex1.size(); ++i) {
2218bf80f4bSopenharmony_ci        {
2228bf80f4bSopenharmony_ci            auto& binder = *binders_.downscale[i];
2238bf80f4bSopenharmony_ci            sets[1u] = binder.GetDescriptorSetHandle();
2248bf80f4bSopenharmony_ci            binder.ClearBindings();
2258bf80f4bSopenharmony_ci
2268bf80f4bSopenharmony_ci            uint32_t binding = 0;
2278bf80f4bSopenharmony_ci            binder.BindImage(binding++, { targets_.tex1[i].GetHandle() });
2288bf80f4bSopenharmony_ci            binder.BindImage(binding++, { targets_.tex1[i - 1].GetHandle() });
2298bf80f4bSopenharmony_ci            binder.BindSampler(binding++, { samplerHandle_.GetHandle() });
2308bf80f4bSopenharmony_ci
2318bf80f4bSopenharmony_ci            cmdList.UpdateDescriptorSet(
2328bf80f4bSopenharmony_ci                binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
2338bf80f4bSopenharmony_ci        }
2348bf80f4bSopenharmony_ci        cmdList.BindDescriptorSets(0u, sets);
2358bf80f4bSopenharmony_ci
2368bf80f4bSopenharmony_ci        const auto targetSize = targets_.tex1Size[i];
2378bf80f4bSopenharmony_ci
2388bf80f4bSopenharmony_ci        LocalPostProcessPushConstantStruct uPc;
2398bf80f4bSopenharmony_ci        uPc.factor = bloomParameters_;
2408bf80f4bSopenharmony_ci        uPc.viewportSizeInvSize = Math::Vec4(static_cast<float>(targetSize.x), static_cast<float>(targetSize.y),
2418bf80f4bSopenharmony_ci            1.0f / static_cast<float>(targetSize.x), 1.0f / static_cast<float>(targetSize.y));
2428bf80f4bSopenharmony_ci        cmdList.PushConstantData(pc, arrayviewU8(uPc));
2438bf80f4bSopenharmony_ci
2448bf80f4bSopenharmony_ci        cmdList.Dispatch((targetSize.x + tgs.x - 1) / tgs.x, (targetSize.y + tgs.y - 1) / tgs.y, 1);
2458bf80f4bSopenharmony_ci    }
2468bf80f4bSopenharmony_ci}
2478bf80f4bSopenharmony_ci
2488bf80f4bSopenharmony_civoid RenderBloom::ComputeUpscale(const PushConstant& pc, IRenderCommandList& cmdList)
2498bf80f4bSopenharmony_ci{
2508bf80f4bSopenharmony_ci    cmdList.BindPipeline(psos_.upscale);
2518bf80f4bSopenharmony_ci    const ShaderThreadGroup tgs = psos_.upscaleTGS;
2528bf80f4bSopenharmony_ci
2538bf80f4bSopenharmony_ci    RenderHandle sets[2u] {};
2548bf80f4bSopenharmony_ci    sets[0u] = binders_.globalSet0->GetDescriptorSetHandle();
2558bf80f4bSopenharmony_ci
2568bf80f4bSopenharmony_ci    for (size_t i = targets_.tex1.size() - 1; i != 0; --i) {
2578bf80f4bSopenharmony_ci        {
2588bf80f4bSopenharmony_ci            auto& binder = *binders_.upscale[i];
2598bf80f4bSopenharmony_ci            sets[1u] = binder.GetDescriptorSetHandle();
2608bf80f4bSopenharmony_ci            binder.ClearBindings();
2618bf80f4bSopenharmony_ci
2628bf80f4bSopenharmony_ci            binder.BindImage(0u, { targets_.tex1[i - 1].GetHandle() });
2638bf80f4bSopenharmony_ci            binder.BindImage(1u, { targets_.tex1[i].GetHandle() });
2648bf80f4bSopenharmony_ci            binder.BindSampler(2u, { samplerHandle_.GetHandle() });
2658bf80f4bSopenharmony_ci
2668bf80f4bSopenharmony_ci            cmdList.UpdateDescriptorSet(
2678bf80f4bSopenharmony_ci                binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
2688bf80f4bSopenharmony_ci        }
2698bf80f4bSopenharmony_ci        cmdList.BindDescriptorSets(0u, sets);
2708bf80f4bSopenharmony_ci
2718bf80f4bSopenharmony_ci        const auto targetSize = targets_.tex1Size[i - 1];
2728bf80f4bSopenharmony_ci
2738bf80f4bSopenharmony_ci        LocalPostProcessPushConstantStruct uPc;
2748bf80f4bSopenharmony_ci        uPc.factor = bloomParameters_;
2758bf80f4bSopenharmony_ci        uPc.viewportSizeInvSize = Math::Vec4(static_cast<float>(targetSize.x), static_cast<float>(targetSize.y),
2768bf80f4bSopenharmony_ci            1.0f / static_cast<float>(targetSize.x), 1.0f / static_cast<float>(targetSize.y));
2778bf80f4bSopenharmony_ci        cmdList.PushConstantData(pc, arrayviewU8(uPc));
2788bf80f4bSopenharmony_ci
2798bf80f4bSopenharmony_ci        cmdList.Dispatch((targetSize.x + tgs.x - 1) / tgs.x, (targetSize.y + tgs.y - 1) / tgs.y, 1);
2808bf80f4bSopenharmony_ci    }
2818bf80f4bSopenharmony_ci}
2828bf80f4bSopenharmony_ci
2838bf80f4bSopenharmony_civoid RenderBloom::ComputeCombine(const PushConstant& pc, IRenderCommandList& cmdList)
2848bf80f4bSopenharmony_ci{
2858bf80f4bSopenharmony_ci    cmdList.BindPipeline(psos_.combine);
2868bf80f4bSopenharmony_ci    const ShaderThreadGroup tgs = psos_.combineTGS;
2878bf80f4bSopenharmony_ci
2888bf80f4bSopenharmony_ci    RenderHandle sets[2u] {};
2898bf80f4bSopenharmony_ci    sets[0u] = binders_.globalSet0->GetDescriptorSetHandle();
2908bf80f4bSopenharmony_ci    {
2918bf80f4bSopenharmony_ci        auto& binder = *binders_.combine;
2928bf80f4bSopenharmony_ci        sets[1u] = binder.GetDescriptorSetHandle();
2938bf80f4bSopenharmony_ci        binder.ClearBindings();
2948bf80f4bSopenharmony_ci        // bind resources to set 1
2958bf80f4bSopenharmony_ci        uint32_t binding = 0;
2968bf80f4bSopenharmony_ci        binder.BindImage(binding++, { bloomInfo_.output });
2978bf80f4bSopenharmony_ci        binder.BindImage(binding++, { bloomInfo_.input });
2988bf80f4bSopenharmony_ci        binder.BindImage(binding++, { targets_.tex1[0].GetHandle() });
2998bf80f4bSopenharmony_ci        binder.BindSampler(binding++, { samplerHandle_.GetHandle() });
3008bf80f4bSopenharmony_ci
3018bf80f4bSopenharmony_ci        // update the descriptor set bindings for set 1
3028bf80f4bSopenharmony_ci        cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
3038bf80f4bSopenharmony_ci    }
3048bf80f4bSopenharmony_ci
3058bf80f4bSopenharmony_ci    cmdList.BindDescriptorSets(0u, sets);
3068bf80f4bSopenharmony_ci
3078bf80f4bSopenharmony_ci    const auto targetSize = baseSize_;
3088bf80f4bSopenharmony_ci
3098bf80f4bSopenharmony_ci    LocalPostProcessPushConstantStruct uPc;
3108bf80f4bSopenharmony_ci    uPc.factor = bloomParameters_;
3118bf80f4bSopenharmony_ci    uPc.viewportSizeInvSize = Math::Vec4(static_cast<float>(targetSize.x), static_cast<float>(targetSize.y),
3128bf80f4bSopenharmony_ci        1.0f / static_cast<float>(targetSize.x), 1.0f / static_cast<float>(targetSize.y));
3138bf80f4bSopenharmony_ci    cmdList.PushConstantData(pc, arrayviewU8(uPc));
3148bf80f4bSopenharmony_ci
3158bf80f4bSopenharmony_ci    cmdList.Dispatch((targetSize.x + tgs.x - 1) / tgs.x, (targetSize.y + tgs.y - 1) / tgs.y, 1);
3168bf80f4bSopenharmony_ci}
3178bf80f4bSopenharmony_ci
3188bf80f4bSopenharmony_civoid RenderBloom::GraphicsBloom(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList)
3198bf80f4bSopenharmony_ci{
3208bf80f4bSopenharmony_ci    RenderPass renderPass;
3218bf80f4bSopenharmony_ci    renderPass.renderPassDesc.attachmentCount = 1;
3228bf80f4bSopenharmony_ci    renderPass.renderPassDesc.subpassCount = 1;
3238bf80f4bSopenharmony_ci    renderPass.renderPassDesc.attachments[0].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
3248bf80f4bSopenharmony_ci    renderPass.renderPassDesc.attachments[0].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
3258bf80f4bSopenharmony_ci
3268bf80f4bSopenharmony_ci    RenderPassSubpassDesc& subpassDesc = renderPass.subpassDesc;
3278bf80f4bSopenharmony_ci    subpassDesc.colorAttachmentCount = 1;
3288bf80f4bSopenharmony_ci    subpassDesc.colorAttachmentIndices[0] = 0;
3298bf80f4bSopenharmony_ci
3308bf80f4bSopenharmony_ci    constexpr PushConstant pc { ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT,
3318bf80f4bSopenharmony_ci        sizeof(LocalPostProcessPushConstantStruct) };
3328bf80f4bSopenharmony_ci
3338bf80f4bSopenharmony_ci    UpdateGlobalSet(cmdList);
3348bf80f4bSopenharmony_ci    if (bloomEnabled_) {
3358bf80f4bSopenharmony_ci        RenderDownscaleAndThreshold(renderPass, pc, cmdList);
3368bf80f4bSopenharmony_ci        RenderDownscale(renderPass, pc, cmdList);
3378bf80f4bSopenharmony_ci        RenderUpscale(renderPass, pc, cmdList);
3388bf80f4bSopenharmony_ci    }
3398bf80f4bSopenharmony_ci    // combine (needs to be done even when bloom is disabled if node is in use
3408bf80f4bSopenharmony_ci    if (RenderHandleUtil::IsValid(bloomInfo_.output.handle)) {
3418bf80f4bSopenharmony_ci        RenderCombine(renderPass, pc, cmdList);
3428bf80f4bSopenharmony_ci    }
3438bf80f4bSopenharmony_ci}
3448bf80f4bSopenharmony_ci
3458bf80f4bSopenharmony_civoid RenderBloom::RenderDownscaleAndThreshold(
3468bf80f4bSopenharmony_ci    RenderPass& renderPass, const PushConstant& pc, IRenderCommandList& cmdList)
3478bf80f4bSopenharmony_ci{
3488bf80f4bSopenharmony_ci    const auto targetSize = targets_.tex1Size[0];
3498bf80f4bSopenharmony_ci    const ViewportDesc viewportDesc { 0, 0, static_cast<float>(targetSize.x), static_cast<float>(targetSize.y) };
3508bf80f4bSopenharmony_ci    const ScissorDesc scissorDesc = { 0, 0, targetSize.x, targetSize.y };
3518bf80f4bSopenharmony_ci
3528bf80f4bSopenharmony_ci    renderPass.renderPassDesc.attachmentHandles[0] = targets_.tex1[0].GetHandle();
3538bf80f4bSopenharmony_ci    renderPass.renderPassDesc.renderArea = { 0, 0, targetSize.x, targetSize.y };
3548bf80f4bSopenharmony_ci    cmdList.BeginRenderPass(renderPass.renderPassDesc, 0, renderPass.subpassDesc);
3558bf80f4bSopenharmony_ci
3568bf80f4bSopenharmony_ci    cmdList.SetDynamicStateViewport(viewportDesc);
3578bf80f4bSopenharmony_ci    cmdList.SetDynamicStateScissor(scissorDesc);
3588bf80f4bSopenharmony_ci    cmdList.BindPipeline(psos_.downscaleAndThreshold);
3598bf80f4bSopenharmony_ci
3608bf80f4bSopenharmony_ci    RenderHandle sets[2u] {};
3618bf80f4bSopenharmony_ci    sets[0u] = binders_.globalSet0->GetDescriptorSetHandle();
3628bf80f4bSopenharmony_ci    {
3638bf80f4bSopenharmony_ci        auto& binder = *binders_.downscaleAndThreshold;
3648bf80f4bSopenharmony_ci        sets[1u] = binder.GetDescriptorSetHandle();
3658bf80f4bSopenharmony_ci        binder.ClearBindings();
3668bf80f4bSopenharmony_ci
3678bf80f4bSopenharmony_ci        binder.BindImage(0u, { bloomInfo_.input });
3688bf80f4bSopenharmony_ci        binder.BindSampler(1u, { samplerHandle_.GetHandle() });
3698bf80f4bSopenharmony_ci        cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
3708bf80f4bSopenharmony_ci    }
3718bf80f4bSopenharmony_ci    cmdList.BindDescriptorSets(0u, sets);
3728bf80f4bSopenharmony_ci
3738bf80f4bSopenharmony_ci    LocalPostProcessPushConstantStruct uPc;
3748bf80f4bSopenharmony_ci    uPc.factor = bloomParameters_;
3758bf80f4bSopenharmony_ci    uPc.viewportSizeInvSize = Math::Vec4(static_cast<float>(targetSize.x), static_cast<float>(targetSize.y),
3768bf80f4bSopenharmony_ci        1.0f / static_cast<float>(targetSize.x), 1.0f / static_cast<float>(targetSize.y));
3778bf80f4bSopenharmony_ci
3788bf80f4bSopenharmony_ci    cmdList.PushConstantData(pc, arrayviewU8(uPc));
3798bf80f4bSopenharmony_ci    cmdList.Draw(3u, 1u, 0u, 0u);
3808bf80f4bSopenharmony_ci    cmdList.EndRenderPass();
3818bf80f4bSopenharmony_ci}
3828bf80f4bSopenharmony_ci
3838bf80f4bSopenharmony_civoid RenderBloom::RenderDownscale(RenderPass& renderPass, const PushConstant& pc, IRenderCommandList& cmdList)
3848bf80f4bSopenharmony_ci{
3858bf80f4bSopenharmony_ci    LocalPostProcessPushConstantStruct uPc;
3868bf80f4bSopenharmony_ci    uPc.factor = bloomParameters_;
3878bf80f4bSopenharmony_ci
3888bf80f4bSopenharmony_ci    RenderHandle sets[2u] {};
3898bf80f4bSopenharmony_ci    sets[0u] = binders_.globalSet0->GetDescriptorSetHandle();
3908bf80f4bSopenharmony_ci    for (size_t idx = 1; idx < targets_.tex1.size(); ++idx) {
3918bf80f4bSopenharmony_ci        const auto targetSize = targets_.tex1Size[idx];
3928bf80f4bSopenharmony_ci        const ViewportDesc viewportDesc { 0, 0, static_cast<float>(targetSize.x), static_cast<float>(targetSize.y) };
3938bf80f4bSopenharmony_ci        const ScissorDesc scissorDesc = { 0, 0, targetSize.x, targetSize.y };
3948bf80f4bSopenharmony_ci
3958bf80f4bSopenharmony_ci        renderPass.renderPassDesc.attachmentHandles[0] = targets_.tex1[idx].GetHandle();
3968bf80f4bSopenharmony_ci        renderPass.renderPassDesc.renderArea = { 0, 0, targetSize.x, targetSize.y };
3978bf80f4bSopenharmony_ci        cmdList.BeginRenderPass(renderPass.renderPassDesc, 0, renderPass.subpassDesc);
3988bf80f4bSopenharmony_ci
3998bf80f4bSopenharmony_ci        cmdList.SetDynamicStateViewport(viewportDesc);
4008bf80f4bSopenharmony_ci        cmdList.SetDynamicStateScissor(scissorDesc);
4018bf80f4bSopenharmony_ci
4028bf80f4bSopenharmony_ci        cmdList.BindPipeline(psos_.downscale);
4038bf80f4bSopenharmony_ci
4048bf80f4bSopenharmony_ci        {
4058bf80f4bSopenharmony_ci            auto& binder = *binders_.downscale[idx];
4068bf80f4bSopenharmony_ci            sets[1u] = binder.GetDescriptorSetHandle();
4078bf80f4bSopenharmony_ci            binder.ClearBindings();
4088bf80f4bSopenharmony_ci            binder.BindImage(0u, { targets_.tex1[idx - 1].GetHandle() });
4098bf80f4bSopenharmony_ci            binder.BindSampler(1u, { samplerHandle_.GetHandle() });
4108bf80f4bSopenharmony_ci            cmdList.UpdateDescriptorSet(
4118bf80f4bSopenharmony_ci                binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
4128bf80f4bSopenharmony_ci        }
4138bf80f4bSopenharmony_ci        cmdList.BindDescriptorSets(0u, sets);
4148bf80f4bSopenharmony_ci
4158bf80f4bSopenharmony_ci        uPc.viewportSizeInvSize = Math::Vec4(static_cast<float>(targetSize.x), static_cast<float>(targetSize.y),
4168bf80f4bSopenharmony_ci            1.0f / static_cast<float>(targetSize.x), 1.0f / static_cast<float>(targetSize.y));
4178bf80f4bSopenharmony_ci
4188bf80f4bSopenharmony_ci        cmdList.PushConstantData(pc, arrayviewU8(uPc));
4198bf80f4bSopenharmony_ci        cmdList.Draw(3u, 1u, 0u, 0u);
4208bf80f4bSopenharmony_ci        cmdList.EndRenderPass();
4218bf80f4bSopenharmony_ci    }
4228bf80f4bSopenharmony_ci}
4238bf80f4bSopenharmony_ci
4248bf80f4bSopenharmony_civoid RenderBloom::RenderUpscale(RenderPass& renderPass, const PushConstant& pc, IRenderCommandList& cmdList)
4258bf80f4bSopenharmony_ci{
4268bf80f4bSopenharmony_ci    RenderPass renderPassUpscale = renderPass;
4278bf80f4bSopenharmony_ci    renderPassUpscale.subpassDesc.inputAttachmentCount = 1;
4288bf80f4bSopenharmony_ci    renderPassUpscale.subpassDesc.inputAttachmentIndices[0] = 0;
4298bf80f4bSopenharmony_ci    renderPassUpscale.renderPassDesc.attachments[0].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
4308bf80f4bSopenharmony_ci    renderPassUpscale.renderPassDesc.attachments[0].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
4318bf80f4bSopenharmony_ci
4328bf80f4bSopenharmony_ci    RenderHandle sets[2u] {};
4338bf80f4bSopenharmony_ci    sets[0u] = binders_.globalSet0->GetDescriptorSetHandle();
4348bf80f4bSopenharmony_ci    PLUGIN_ASSERT(targets_.tex1.size() == targets_.tex2.size());
4358bf80f4bSopenharmony_ci    RenderHandle input;
4368bf80f4bSopenharmony_ci    if (targets_.tex1.size() >= 1) {
4378bf80f4bSopenharmony_ci        input = targets_.tex1[targets_.tex1.size() - 1].GetHandle();
4388bf80f4bSopenharmony_ci    }
4398bf80f4bSopenharmony_ci    for (size_t idx = targets_.tex1.size() - 1; idx != 0; --idx) {
4408bf80f4bSopenharmony_ci        const auto targetSize = targets_.tex1Size[idx - 1];
4418bf80f4bSopenharmony_ci        const ViewportDesc viewportDesc { 0, 0, static_cast<float>(targetSize.x), static_cast<float>(targetSize.y) };
4428bf80f4bSopenharmony_ci        const ScissorDesc scissorDesc = { 0, 0, targetSize.x, targetSize.y };
4438bf80f4bSopenharmony_ci
4448bf80f4bSopenharmony_ci        // tex2 as output
4458bf80f4bSopenharmony_ci        renderPassUpscale.renderPassDesc.attachmentHandles[0] = targets_.tex2[idx - 1].GetHandle();
4468bf80f4bSopenharmony_ci        renderPassUpscale.renderPassDesc.renderArea = { 0, 0, targetSize.x, targetSize.y };
4478bf80f4bSopenharmony_ci        cmdList.BeginRenderPass(renderPassUpscale.renderPassDesc, 0, renderPassUpscale.subpassDesc);
4488bf80f4bSopenharmony_ci
4498bf80f4bSopenharmony_ci        cmdList.SetDynamicStateViewport(viewportDesc);
4508bf80f4bSopenharmony_ci        cmdList.SetDynamicStateScissor(scissorDesc);
4518bf80f4bSopenharmony_ci
4528bf80f4bSopenharmony_ci        cmdList.BindPipeline(psos_.upscale);
4538bf80f4bSopenharmony_ci
4548bf80f4bSopenharmony_ci        {
4558bf80f4bSopenharmony_ci            auto& binder = *binders_.upscale[idx];
4568bf80f4bSopenharmony_ci            sets[1u] = binder.GetDescriptorSetHandle();
4578bf80f4bSopenharmony_ci            binder.ClearBindings();
4588bf80f4bSopenharmony_ci
4598bf80f4bSopenharmony_ci            uint32_t binding = 0;
4608bf80f4bSopenharmony_ci            binder.BindImage(binding++, { input });
4618bf80f4bSopenharmony_ci            binder.BindImage(binding++, { targets_.tex1[idx - 1].GetHandle() });
4628bf80f4bSopenharmony_ci            binder.BindSampler(binding++, { samplerHandle_.GetHandle() });
4638bf80f4bSopenharmony_ci            cmdList.UpdateDescriptorSet(
4648bf80f4bSopenharmony_ci                binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
4658bf80f4bSopenharmony_ci        }
4668bf80f4bSopenharmony_ci        cmdList.BindDescriptorSets(0u, sets);
4678bf80f4bSopenharmony_ci        LocalPostProcessPushConstantStruct uPc;
4688bf80f4bSopenharmony_ci        uPc.factor = bloomParameters_;
4698bf80f4bSopenharmony_ci        uPc.viewportSizeInvSize = Math::Vec4(static_cast<float>(targetSize.x), static_cast<float>(targetSize.y),
4708bf80f4bSopenharmony_ci            1.0f / static_cast<float>(targetSize.x), 1.0f / static_cast<float>(targetSize.y));
4718bf80f4bSopenharmony_ci
4728bf80f4bSopenharmony_ci        cmdList.PushConstantData(pc, arrayviewU8(uPc));
4738bf80f4bSopenharmony_ci        cmdList.Draw(3u, 1u, 0u, 0u);
4748bf80f4bSopenharmony_ci        cmdList.EndRenderPass();
4758bf80f4bSopenharmony_ci
4768bf80f4bSopenharmony_ci        // next pass input
4778bf80f4bSopenharmony_ci        input = renderPassUpscale.renderPassDesc.attachmentHandles[0];
4788bf80f4bSopenharmony_ci    }
4798bf80f4bSopenharmony_ci}
4808bf80f4bSopenharmony_ci
4818bf80f4bSopenharmony_civoid RenderBloom::RenderCombine(RenderPass& renderPass, const PushConstant& pc, IRenderCommandList& cmdList)
4828bf80f4bSopenharmony_ci{
4838bf80f4bSopenharmony_ci    const auto targetSize = baseSize_;
4848bf80f4bSopenharmony_ci
4858bf80f4bSopenharmony_ci    renderPass.renderPassDesc.attachmentHandles[0] = bloomInfo_.output.handle;
4868bf80f4bSopenharmony_ci    renderPass.renderPassDesc.renderArea = { 0, 0, targetSize.x, targetSize.y };
4878bf80f4bSopenharmony_ci    cmdList.BeginRenderPass(renderPass.renderPassDesc, 0, renderPass.subpassDesc);
4888bf80f4bSopenharmony_ci
4898bf80f4bSopenharmony_ci    cmdList.SetDynamicStateViewport(baseViewportDesc_);
4908bf80f4bSopenharmony_ci    cmdList.SetDynamicStateScissor(baseScissorDesc_);
4918bf80f4bSopenharmony_ci
4928bf80f4bSopenharmony_ci    cmdList.BindPipeline(psos_.combine);
4938bf80f4bSopenharmony_ci
4948bf80f4bSopenharmony_ci    RenderHandle sets[2u] {};
4958bf80f4bSopenharmony_ci    sets[0u] = binders_.globalSet0->GetDescriptorSetHandle();
4968bf80f4bSopenharmony_ci    {
4978bf80f4bSopenharmony_ci        auto& binder = *binders_.combine;
4988bf80f4bSopenharmony_ci        sets[1u] = binder.GetDescriptorSetHandle();
4998bf80f4bSopenharmony_ci        binder.ClearBindings();
5008bf80f4bSopenharmony_ci
5018bf80f4bSopenharmony_ci        uint32_t binding = 0;
5028bf80f4bSopenharmony_ci        binder.BindImage(binding++, { bloomInfo_.input });
5038bf80f4bSopenharmony_ci        // tex2 handle has the final result
5048bf80f4bSopenharmony_ci        binder.BindImage(binding++, { targets_.tex2[0].GetHandle() });
5058bf80f4bSopenharmony_ci        binder.BindSampler(binding++, { samplerHandle_.GetHandle() });
5068bf80f4bSopenharmony_ci
5078bf80f4bSopenharmony_ci        cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
5088bf80f4bSopenharmony_ci    }
5098bf80f4bSopenharmony_ci    cmdList.BindDescriptorSets(0u, sets);
5108bf80f4bSopenharmony_ci
5118bf80f4bSopenharmony_ci    LocalPostProcessPushConstantStruct uPc;
5128bf80f4bSopenharmony_ci    uPc.factor = bloomParameters_;
5138bf80f4bSopenharmony_ci    uPc.viewportSizeInvSize = Math::Vec4(static_cast<float>(targetSize.x), static_cast<float>(targetSize.y),
5148bf80f4bSopenharmony_ci        1.0f / static_cast<float>(targetSize.x), 1.0f / static_cast<float>(targetSize.y));
5158bf80f4bSopenharmony_ci
5168bf80f4bSopenharmony_ci    cmdList.PushConstantData(pc, arrayviewU8(uPc));
5178bf80f4bSopenharmony_ci    cmdList.Draw(3u, 1u, 0u, 0u);
5188bf80f4bSopenharmony_ci    cmdList.EndRenderPass();
5198bf80f4bSopenharmony_ci}
5208bf80f4bSopenharmony_ci
5218bf80f4bSopenharmony_civoid RenderBloom::CreateTargets(IRenderNodeContextManager& renderNodeContextMgr, const Math::UVec2 baseSize)
5228bf80f4bSopenharmony_ci{
5238bf80f4bSopenharmony_ci    if (baseSize.x != baseSize_.x || baseSize.y != baseSize_.y) {
5248bf80f4bSopenharmony_ci        baseSize_ = baseSize;
5258bf80f4bSopenharmony_ci
5268bf80f4bSopenharmony_ci        format_ = Format::BASE_FORMAT_B10G11R11_UFLOAT_PACK32;
5278bf80f4bSopenharmony_ci        ImageUsageFlags usageFlags = CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | CORE_IMAGE_USAGE_SAMPLED_BIT |
5288bf80f4bSopenharmony_ci                                     CORE_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
5298bf80f4bSopenharmony_ci
5308bf80f4bSopenharmony_ci        if (bloomInfo_.useCompute) {
5318bf80f4bSopenharmony_ci            format_ = Format::BASE_FORMAT_R16G16B16A16_SFLOAT; // used due to GLES
5328bf80f4bSopenharmony_ci            usageFlags = CORE_IMAGE_USAGE_STORAGE_BIT | CORE_IMAGE_USAGE_SAMPLED_BIT;
5338bf80f4bSopenharmony_ci        } else {
5348bf80f4bSopenharmony_ci            baseViewportDesc_ = { 0.0f, 0.0f, static_cast<float>(baseSize.x), static_cast<float>(baseSize.y), 0.0f,
5358bf80f4bSopenharmony_ci                1.0f };
5368bf80f4bSopenharmony_ci            baseScissorDesc_ = { 0, 0, baseSize.x, baseSize.y };
5378bf80f4bSopenharmony_ci        }
5388bf80f4bSopenharmony_ci
5398bf80f4bSopenharmony_ci        // create target image
5408bf80f4bSopenharmony_ci        const Math::UVec2 startTargetSize = baseSize_;
5418bf80f4bSopenharmony_ci        GpuImageDesc desc {
5428bf80f4bSopenharmony_ci            ImageType::CORE_IMAGE_TYPE_2D,
5438bf80f4bSopenharmony_ci            ImageViewType::CORE_IMAGE_VIEW_TYPE_2D,
5448bf80f4bSopenharmony_ci            format_,
5458bf80f4bSopenharmony_ci            ImageTiling::CORE_IMAGE_TILING_OPTIMAL,
5468bf80f4bSopenharmony_ci            usageFlags,
5478bf80f4bSopenharmony_ci            MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
5488bf80f4bSopenharmony_ci            0,
5498bf80f4bSopenharmony_ci            EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS |
5508bf80f4bSopenharmony_ci                EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_RESET_STATE_ON_FRAME_BORDERS,
5518bf80f4bSopenharmony_ci            startTargetSize.x,
5528bf80f4bSopenharmony_ci            startTargetSize.y,
5538bf80f4bSopenharmony_ci            1u,
5548bf80f4bSopenharmony_ci            1u,
5558bf80f4bSopenharmony_ci            1u,
5568bf80f4bSopenharmony_ci            SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT,
5578bf80f4bSopenharmony_ci            {},
5588bf80f4bSopenharmony_ci        };
5598bf80f4bSopenharmony_ci
5608bf80f4bSopenharmony_ci        auto& gpuResourceMgr = renderNodeContextMgr.GetGpuResourceManager();
5618bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
5628bf80f4bSopenharmony_ci        const string_view nodeName = renderNodeContextMgr.GetName();
5638bf80f4bSopenharmony_ci#endif
5648bf80f4bSopenharmony_ci        for (size_t idx = 0; idx < targets_.tex1.size(); ++idx) {
5658bf80f4bSopenharmony_ci            // every bloom target is half the size of the original/ previous bloom target
5668bf80f4bSopenharmony_ci            desc.width /= 2u;
5678bf80f4bSopenharmony_ci            desc.height /= 2u;
5688bf80f4bSopenharmony_ci            desc.width = (desc.width >= 1u) ? desc.width : 1u;
5698bf80f4bSopenharmony_ci            desc.height = (desc.height >= 1u) ? desc.height : 1u;
5708bf80f4bSopenharmony_ci            targets_.tex1Size[idx] = Math::UVec2(desc.width, desc.height);
5718bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
5728bf80f4bSopenharmony_ci            const auto baseTargetName = nodeName + "_Bloom_" + to_string(idx);
5738bf80f4bSopenharmony_ci            targets_.tex1[idx] = gpuResourceMgr.Create(baseTargetName + "_A", desc);
5748bf80f4bSopenharmony_ci            if (!bloomInfo_.useCompute) {
5758bf80f4bSopenharmony_ci                targets_.tex2[idx] = gpuResourceMgr.Create(baseTargetName + "_B", desc);
5768bf80f4bSopenharmony_ci            }
5778bf80f4bSopenharmony_ci#else
5788bf80f4bSopenharmony_ci            targets_.tex1[idx] = gpuResourceMgr.Create(targets_.tex1[idx], desc);
5798bf80f4bSopenharmony_ci            if (!bloomInfo_.useCompute) {
5808bf80f4bSopenharmony_ci                targets_.tex2[idx] = gpuResourceMgr.Create(targets_.tex2[idx], desc);
5818bf80f4bSopenharmony_ci            }
5828bf80f4bSopenharmony_ci#endif
5838bf80f4bSopenharmony_ci        }
5848bf80f4bSopenharmony_ci    }
5858bf80f4bSopenharmony_ci}
5868bf80f4bSopenharmony_ci
5878bf80f4bSopenharmony_civoid RenderBloom::CreatePsos(IRenderNodeContextManager& renderNodeContextMgr)
5888bf80f4bSopenharmony_ci{
5898bf80f4bSopenharmony_ci    if (bloomInfo_.useCompute) {
5908bf80f4bSopenharmony_ci        CreateComputePsos(renderNodeContextMgr);
5918bf80f4bSopenharmony_ci    } else {
5928bf80f4bSopenharmony_ci        CreateRenderPsos(renderNodeContextMgr);
5938bf80f4bSopenharmony_ci    }
5948bf80f4bSopenharmony_ci}
5958bf80f4bSopenharmony_ci
5968bf80f4bSopenharmony_civoid RenderBloom::CreateComputePsos(IRenderNodeContextManager& renderNodeContextMgr)
5978bf80f4bSopenharmony_ci{
5988bf80f4bSopenharmony_ci    const auto& shaderMgr = renderNodeContextMgr.GetShaderManager();
5998bf80f4bSopenharmony_ci    INodeContextPsoManager& psoMgr = renderNodeContextMgr.GetPsoManager();
6008bf80f4bSopenharmony_ci    INodeContextDescriptorSetManager& dSetMgr = renderNodeContextMgr.GetDescriptorSetManager();
6018bf80f4bSopenharmony_ci
6028bf80f4bSopenharmony_ci    constexpr BASE_NS::pair<BloomConfiguration::BloomQualityType, uint32_t> configurations[] = {
6038bf80f4bSopenharmony_ci        { BloomConfiguration::BloomQualityType::QUALITY_TYPE_LOW, RenderBloom::CORE_BLOOM_QUALITY_LOW },
6048bf80f4bSopenharmony_ci        { BloomConfiguration::BloomQualityType::QUALITY_TYPE_NORMAL, RenderBloom::CORE_BLOOM_QUALITY_NORMAL },
6058bf80f4bSopenharmony_ci        { BloomConfiguration::BloomQualityType::QUALITY_TYPE_HIGH, RenderBloom::CORE_BLOOM_QUALITY_HIGH }
6068bf80f4bSopenharmony_ci    };
6078bf80f4bSopenharmony_ci    for (const auto& configuration : configurations) {
6088bf80f4bSopenharmony_ci        {
6098bf80f4bSopenharmony_ci            auto shader = shaderMgr.GetShaderHandle("rendershaders://computeshader/bloom_downscale.shader");
6108bf80f4bSopenharmony_ci            const PipelineLayout& pl = shaderMgr.GetReflectionPipelineLayout(shader);
6118bf80f4bSopenharmony_ci            ShaderSpecializationConstantView specializations = shaderMgr.GetReflectionSpecialization(shader);
6128bf80f4bSopenharmony_ci            const ShaderSpecializationConstantDataView specDataView {
6138bf80f4bSopenharmony_ci                { specializations.constants.data(), specializations.constants.size() },
6148bf80f4bSopenharmony_ci                { &configuration.second, 1u },
6158bf80f4bSopenharmony_ci            };
6168bf80f4bSopenharmony_ci
6178bf80f4bSopenharmony_ci            psos_.downscaleHandlesCompute[configuration.first].regular =
6188bf80f4bSopenharmony_ci                psoMgr.GetComputePsoHandle(shader, pl, specDataView);
6198bf80f4bSopenharmony_ci        }
6208bf80f4bSopenharmony_ci        {
6218bf80f4bSopenharmony_ci            auto shader = shaderMgr.GetShaderHandle("rendershaders://computeshader/bloom_downscale_threshold.shader");
6228bf80f4bSopenharmony_ci            const PipelineLayout& pl = shaderMgr.GetReflectionPipelineLayout(shader);
6238bf80f4bSopenharmony_ci
6248bf80f4bSopenharmony_ci            ShaderSpecializationConstantView specializations = shaderMgr.GetReflectionSpecialization(shader);
6258bf80f4bSopenharmony_ci            const ShaderSpecializationConstantDataView specDataView {
6268bf80f4bSopenharmony_ci                { specializations.constants.data(), specializations.constants.size() },
6278bf80f4bSopenharmony_ci                { &configuration.second, 1u },
6288bf80f4bSopenharmony_ci            };
6298bf80f4bSopenharmony_ci            psos_.downscaleHandlesCompute[configuration.first].threshold =
6308bf80f4bSopenharmony_ci                psoMgr.GetComputePsoHandle(shader, pl, specDataView);
6318bf80f4bSopenharmony_ci        }
6328bf80f4bSopenharmony_ci    }
6338bf80f4bSopenharmony_ci
6348bf80f4bSopenharmony_ci    constexpr uint32_t globalSet = 0u;
6358bf80f4bSopenharmony_ci    constexpr uint32_t localSetIdx = 1u;
6368bf80f4bSopenharmony_ci    // the first one creates the global set as well
6378bf80f4bSopenharmony_ci    {
6388bf80f4bSopenharmony_ci        const RenderHandle shaderHandle =
6398bf80f4bSopenharmony_ci            shaderMgr.GetShaderHandle("rendershaders://computeshader/bloom_downscale_threshold.shader");
6408bf80f4bSopenharmony_ci        const PipelineLayout& pl = shaderMgr.GetReflectionPipelineLayout(shaderHandle);
6418bf80f4bSopenharmony_ci        psos_.downscaleAndThreshold = psoMgr.GetComputePsoHandle(shaderHandle, pl, {});
6428bf80f4bSopenharmony_ci        psos_.downscaleAndThresholdTGS = shaderMgr.GetReflectionThreadGroupSize(shaderHandle);
6438bf80f4bSopenharmony_ci
6448bf80f4bSopenharmony_ci        const auto& gBinds = pl.descriptorSetLayouts[globalSet].bindings;
6458bf80f4bSopenharmony_ci        binders_.globalSet0 = dSetMgr.CreateDescriptorSetBinder(dSetMgr.CreateDescriptorSet(gBinds), gBinds);
6468bf80f4bSopenharmony_ci
6478bf80f4bSopenharmony_ci        const auto& lBinds = pl.descriptorSetLayouts[localSetIdx].bindings;
6488bf80f4bSopenharmony_ci        binders_.downscaleAndThreshold = dSetMgr.CreateDescriptorSetBinder(dSetMgr.CreateDescriptorSet(lBinds), lBinds);
6498bf80f4bSopenharmony_ci    }
6508bf80f4bSopenharmony_ci    {
6518bf80f4bSopenharmony_ci        const RenderHandle shaderHandle =
6528bf80f4bSopenharmony_ci            shaderMgr.GetShaderHandle("rendershaders://computeshader/bloom_downscale.shader");
6538bf80f4bSopenharmony_ci        const PipelineLayout& pl = shaderMgr.GetReflectionPipelineLayout(shaderHandle);
6548bf80f4bSopenharmony_ci        psos_.downscale = psoMgr.GetComputePsoHandle(shaderHandle, pl, {});
6558bf80f4bSopenharmony_ci        psos_.downscaleTGS = shaderMgr.GetReflectionThreadGroupSize(shaderHandle);
6568bf80f4bSopenharmony_ci
6578bf80f4bSopenharmony_ci        PLUGIN_ASSERT(binders_.downscale.size() >= TARGET_COUNT);
6588bf80f4bSopenharmony_ci        const auto& binds = pl.descriptorSetLayouts[localSetIdx].bindings;
6598bf80f4bSopenharmony_ci        for (uint32_t idx = 0; idx < TARGET_COUNT; ++idx) {
6608bf80f4bSopenharmony_ci            binders_.downscale[idx] = dSetMgr.CreateDescriptorSetBinder(dSetMgr.CreateDescriptorSet(binds), binds);
6618bf80f4bSopenharmony_ci        }
6628bf80f4bSopenharmony_ci    }
6638bf80f4bSopenharmony_ci    {
6648bf80f4bSopenharmony_ci        const RenderHandle shaderHandle =
6658bf80f4bSopenharmony_ci            shaderMgr.GetShaderHandle("rendershaders://computeshader/bloom_upscale.shader");
6668bf80f4bSopenharmony_ci        const PipelineLayout& pl = shaderMgr.GetReflectionPipelineLayout(shaderHandle);
6678bf80f4bSopenharmony_ci        psos_.upscale = psoMgr.GetComputePsoHandle(shaderHandle, pl, {});
6688bf80f4bSopenharmony_ci        psos_.upscaleTGS = shaderMgr.GetReflectionThreadGroupSize(shaderHandle);
6698bf80f4bSopenharmony_ci
6708bf80f4bSopenharmony_ci        PLUGIN_ASSERT(binders_.upscale.size() >= TARGET_COUNT);
6718bf80f4bSopenharmony_ci        const auto& binds = pl.descriptorSetLayouts[localSetIdx].bindings;
6728bf80f4bSopenharmony_ci        for (uint32_t idx = 0; idx < TARGET_COUNT; ++idx) {
6738bf80f4bSopenharmony_ci            binders_.upscale[idx] = dSetMgr.CreateDescriptorSetBinder(dSetMgr.CreateDescriptorSet(binds), binds);
6748bf80f4bSopenharmony_ci        }
6758bf80f4bSopenharmony_ci    }
6768bf80f4bSopenharmony_ci    {
6778bf80f4bSopenharmony_ci        const RenderHandle shaderHandle =
6788bf80f4bSopenharmony_ci            shaderMgr.GetShaderHandle("rendershaders://computeshader/bloom_combine.shader");
6798bf80f4bSopenharmony_ci        const PipelineLayout& pl = shaderMgr.GetReflectionPipelineLayout(shaderHandle);
6808bf80f4bSopenharmony_ci        psos_.combine = psoMgr.GetComputePsoHandle(shaderHandle, pl, {});
6818bf80f4bSopenharmony_ci        psos_.combineTGS = shaderMgr.GetReflectionThreadGroupSize(shaderHandle);
6828bf80f4bSopenharmony_ci
6838bf80f4bSopenharmony_ci        const auto& binds = pl.descriptorSetLayouts[localSetIdx].bindings;
6848bf80f4bSopenharmony_ci        binders_.combine = dSetMgr.CreateDescriptorSetBinder(dSetMgr.CreateDescriptorSet(binds), binds);
6858bf80f4bSopenharmony_ci    }
6868bf80f4bSopenharmony_ci}
6878bf80f4bSopenharmony_ci
6888bf80f4bSopenharmony_cistd::pair<RenderHandle, const PipelineLayout&> RenderBloom::CreateAndReflectRenderPso(
6898bf80f4bSopenharmony_ci    IRenderNodeContextManager& renderNodeContextMgr, const string_view shader, const RenderPass& renderPass)
6908bf80f4bSopenharmony_ci{
6918bf80f4bSopenharmony_ci    const auto& shaderMgr = renderNodeContextMgr.GetShaderManager();
6928bf80f4bSopenharmony_ci    const RenderHandle shaderHandle = shaderMgr.GetShaderHandle(shader.data());
6938bf80f4bSopenharmony_ci    const RenderHandle graphicsStateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(shaderHandle);
6948bf80f4bSopenharmony_ci    const PipelineLayout& pl = shaderMgr.GetReflectionPipelineLayout(shaderHandle);
6958bf80f4bSopenharmony_ci
6968bf80f4bSopenharmony_ci    auto& psoMgr = renderNodeContextMgr.GetPsoManager();
6978bf80f4bSopenharmony_ci    const RenderHandle pso = psoMgr.GetGraphicsPsoHandle(
6988bf80f4bSopenharmony_ci        shaderHandle, graphicsStateHandle, pl, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
6998bf80f4bSopenharmony_ci    return { pso, pl };
7008bf80f4bSopenharmony_ci}
7018bf80f4bSopenharmony_ci
7028bf80f4bSopenharmony_civoid RenderBloom::CreateRenderPsos(IRenderNodeContextManager& renderNodeContextMgr)
7038bf80f4bSopenharmony_ci{
7048bf80f4bSopenharmony_ci    RenderPass renderPass;
7058bf80f4bSopenharmony_ci    renderPass.renderPassDesc.attachmentCount = 1;
7068bf80f4bSopenharmony_ci    renderPass.renderPassDesc.attachmentHandles[0] = bloomInfo_.input.handle;
7078bf80f4bSopenharmony_ci    renderPass.renderPassDesc.renderArea = { 0, 0, baseSize_.x, baseSize_.y };
7088bf80f4bSopenharmony_ci    renderPass.renderPassDesc.subpassCount = 1;
7098bf80f4bSopenharmony_ci    renderPass.renderPassDesc.attachments[0].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
7108bf80f4bSopenharmony_ci    renderPass.renderPassDesc.attachments[0].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
7118bf80f4bSopenharmony_ci
7128bf80f4bSopenharmony_ci    RenderPassSubpassDesc subpassDesc = renderPass.subpassDesc;
7138bf80f4bSopenharmony_ci    subpassDesc.colorAttachmentCount = 1;
7148bf80f4bSopenharmony_ci    subpassDesc.colorAttachmentIndices[0] = 0;
7158bf80f4bSopenharmony_ci
7168bf80f4bSopenharmony_ci    constexpr BASE_NS::pair<BloomConfiguration::BloomQualityType, uint32_t> configurations[] = {
7178bf80f4bSopenharmony_ci        { BloomConfiguration::BloomQualityType::QUALITY_TYPE_LOW, RenderBloom::CORE_BLOOM_QUALITY_LOW },
7188bf80f4bSopenharmony_ci        { BloomConfiguration::BloomQualityType::QUALITY_TYPE_NORMAL, RenderBloom::CORE_BLOOM_QUALITY_NORMAL },
7198bf80f4bSopenharmony_ci        { BloomConfiguration::BloomQualityType::QUALITY_TYPE_HIGH, RenderBloom::CORE_BLOOM_QUALITY_HIGH }
7208bf80f4bSopenharmony_ci    };
7218bf80f4bSopenharmony_ci
7228bf80f4bSopenharmony_ci    const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr.GetShaderManager();
7238bf80f4bSopenharmony_ci    INodeContextPsoManager& psoMgr = renderNodeContextMgr.GetPsoManager();
7248bf80f4bSopenharmony_ci
7258bf80f4bSopenharmony_ci    for (const auto& configuration : configurations) {
7268bf80f4bSopenharmony_ci        {
7278bf80f4bSopenharmony_ci            auto shader = shaderMgr.GetShaderHandle("rendershaders://shader/bloom_downscale.shader");
7288bf80f4bSopenharmony_ci            const PipelineLayout& pl = shaderMgr.GetReflectionPipelineLayout(shader);
7298bf80f4bSopenharmony_ci            ShaderSpecializationConstantView specializations = shaderMgr.GetReflectionSpecialization(shader);
7308bf80f4bSopenharmony_ci            const ShaderSpecializationConstantDataView specDataView {
7318bf80f4bSopenharmony_ci                { specializations.constants.data(), specializations.constants.size() },
7328bf80f4bSopenharmony_ci                { &configuration.second, 1u },
7338bf80f4bSopenharmony_ci            };
7348bf80f4bSopenharmony_ci            const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(shader);
7358bf80f4bSopenharmony_ci            psos_.downscaleHandles[configuration.first].regular = psoMgr.GetGraphicsPsoHandle(
7368bf80f4bSopenharmony_ci                shader, graphicsState, pl, {}, specDataView, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
7378bf80f4bSopenharmony_ci        }
7388bf80f4bSopenharmony_ci
7398bf80f4bSopenharmony_ci        {
7408bf80f4bSopenharmony_ci            auto shader = shaderMgr.GetShaderHandle("rendershaders://shader/bloom_downscale_threshold.shader");
7418bf80f4bSopenharmony_ci            const PipelineLayout& pl = shaderMgr.GetReflectionPipelineLayout(shader);
7428bf80f4bSopenharmony_ci            ShaderSpecializationConstantView specializations = shaderMgr.GetReflectionSpecialization(shader);
7438bf80f4bSopenharmony_ci            const ShaderSpecializationConstantDataView specDataView {
7448bf80f4bSopenharmony_ci                { specializations.constants.data(), specializations.constants.size() },
7458bf80f4bSopenharmony_ci                { &configuration.second, 1u },
7468bf80f4bSopenharmony_ci            };
7478bf80f4bSopenharmony_ci            const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(shader);
7488bf80f4bSopenharmony_ci            psos_.downscaleHandles[configuration.first].threshold = psoMgr.GetGraphicsPsoHandle(
7498bf80f4bSopenharmony_ci                shader, graphicsState, pl, {}, specDataView, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
7508bf80f4bSopenharmony_ci        }
7518bf80f4bSopenharmony_ci    }
7528bf80f4bSopenharmony_ci
7538bf80f4bSopenharmony_ci    INodeContextDescriptorSetManager& dSetMgr = renderNodeContextMgr.GetDescriptorSetManager();
7548bf80f4bSopenharmony_ci    constexpr uint32_t globalSet = 0u;
7558bf80f4bSopenharmony_ci    constexpr uint32_t localSet = 1u;
7568bf80f4bSopenharmony_ci    // the first one creates the global set as well
7578bf80f4bSopenharmony_ci    {
7588bf80f4bSopenharmony_ci        const auto [pso, pipelineLayout] = CreateAndReflectRenderPso(
7598bf80f4bSopenharmony_ci            renderNodeContextMgr, "rendershaders://shader/bloom_downscale_threshold.shader", renderPass);
7608bf80f4bSopenharmony_ci        psos_.downscaleAndThreshold = pso;
7618bf80f4bSopenharmony_ci
7628bf80f4bSopenharmony_ci        const auto& gBinds = pipelineLayout.descriptorSetLayouts[globalSet].bindings;
7638bf80f4bSopenharmony_ci        binders_.globalSet0 = dSetMgr.CreateDescriptorSetBinder(dSetMgr.CreateDescriptorSet(gBinds), gBinds);
7648bf80f4bSopenharmony_ci
7658bf80f4bSopenharmony_ci        const auto& lBinds = pipelineLayout.descriptorSetLayouts[localSet].bindings;
7668bf80f4bSopenharmony_ci        binders_.downscaleAndThreshold = dSetMgr.CreateDescriptorSetBinder(dSetMgr.CreateDescriptorSet(lBinds), lBinds);
7678bf80f4bSopenharmony_ci    }
7688bf80f4bSopenharmony_ci    {
7698bf80f4bSopenharmony_ci        const auto [pso, pipelineLayout] = CreateAndReflectRenderPso(
7708bf80f4bSopenharmony_ci            renderNodeContextMgr, "rendershaders://shader/bloom_downscale.shader", renderPass);
7718bf80f4bSopenharmony_ci        psos_.downscale = pso;
7728bf80f4bSopenharmony_ci        const auto& binds = pipelineLayout.descriptorSetLayouts[localSet].bindings;
7738bf80f4bSopenharmony_ci        for (uint32_t idx = 0; idx < TARGET_COUNT; ++idx) {
7748bf80f4bSopenharmony_ci            binders_.downscale[idx] = dSetMgr.CreateDescriptorSetBinder(dSetMgr.CreateDescriptorSet(binds), binds);
7758bf80f4bSopenharmony_ci        }
7768bf80f4bSopenharmony_ci    }
7778bf80f4bSopenharmony_ci    {
7788bf80f4bSopenharmony_ci        const auto [pso, pipelineLayout] =
7798bf80f4bSopenharmony_ci            CreateAndReflectRenderPso(renderNodeContextMgr, "rendershaders://shader/bloom_upscale.shader", renderPass);
7808bf80f4bSopenharmony_ci        psos_.upscale = pso;
7818bf80f4bSopenharmony_ci        const auto& binds = pipelineLayout.descriptorSetLayouts[localSet].bindings;
7828bf80f4bSopenharmony_ci        for (uint32_t idx = 0; idx < TARGET_COUNT; ++idx) {
7838bf80f4bSopenharmony_ci            binders_.upscale[idx] = dSetMgr.CreateDescriptorSetBinder(dSetMgr.CreateDescriptorSet(binds), binds);
7848bf80f4bSopenharmony_ci        }
7858bf80f4bSopenharmony_ci    }
7868bf80f4bSopenharmony_ci    {
7878bf80f4bSopenharmony_ci        const auto [pso, pipelineLayout] =
7888bf80f4bSopenharmony_ci            CreateAndReflectRenderPso(renderNodeContextMgr, "rendershaders://shader/bloom_combine.shader", renderPass);
7898bf80f4bSopenharmony_ci        psos_.combine = pso;
7908bf80f4bSopenharmony_ci        const auto& binds = pipelineLayout.descriptorSetLayouts[localSet].bindings;
7918bf80f4bSopenharmony_ci        binders_.combine = dSetMgr.CreateDescriptorSetBinder(dSetMgr.CreateDescriptorSet(binds), binds);
7928bf80f4bSopenharmony_ci    }
7938bf80f4bSopenharmony_ci}
7948bf80f4bSopenharmony_ciRENDER_END_NAMESPACE()
795