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_copy.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
308bf80f4bSopenharmony_ci#include "default_engine_constants.h"
318bf80f4bSopenharmony_ci#include "device/gpu_resource_handle_util.h"
328bf80f4bSopenharmony_ci#include "util/log.h"
338bf80f4bSopenharmony_ci
348bf80f4bSopenharmony_ci// shaders
358bf80f4bSopenharmony_ci#include <render/shaders/common/render_post_process_structs_common.h>
368bf80f4bSopenharmony_ci
378bf80f4bSopenharmony_ciusing namespace BASE_NS;
388bf80f4bSopenharmony_ci
398bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE()
408bf80f4bSopenharmony_cinamespace {
418bf80f4bSopenharmony_ciconstexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
428bf80f4bSopenharmony_ci
438bf80f4bSopenharmony_ciRenderPass CreateRenderPass(const IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandle input)
448bf80f4bSopenharmony_ci{
458bf80f4bSopenharmony_ci    const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(input);
468bf80f4bSopenharmony_ci    RenderPass rp;
478bf80f4bSopenharmony_ci    rp.renderPassDesc.attachmentCount = 1u;
488bf80f4bSopenharmony_ci    rp.renderPassDesc.attachmentHandles[0u] = input;
498bf80f4bSopenharmony_ci    rp.renderPassDesc.attachments[0u].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
508bf80f4bSopenharmony_ci    rp.renderPassDesc.attachments[0u].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
518bf80f4bSopenharmony_ci    rp.renderPassDesc.renderArea = { 0, 0, desc.width, desc.height };
528bf80f4bSopenharmony_ci
538bf80f4bSopenharmony_ci    rp.renderPassDesc.subpassCount = 1u;
548bf80f4bSopenharmony_ci    rp.subpassDesc.colorAttachmentCount = 1u;
558bf80f4bSopenharmony_ci    rp.subpassDesc.colorAttachmentIndices[0u] = 0u;
568bf80f4bSopenharmony_ci    rp.subpassStartIndex = 0u;
578bf80f4bSopenharmony_ci    return rp;
588bf80f4bSopenharmony_ci}
598bf80f4bSopenharmony_ci
608bf80f4bSopenharmony_ciRenderHandle CreatePso(
618bf80f4bSopenharmony_ci    IRenderNodeContextManager& renderNodeContextMgr, const RenderHandle& shader, const PipelineLayout& pipelineLayout)
628bf80f4bSopenharmony_ci{
638bf80f4bSopenharmony_ci    auto& psoMgr = renderNodeContextMgr.GetPsoManager();
648bf80f4bSopenharmony_ci    const auto& shaderMgr = renderNodeContextMgr.GetShaderManager();
658bf80f4bSopenharmony_ci    const RenderHandle graphicsStateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(shader);
668bf80f4bSopenharmony_ci    return psoMgr.GetGraphicsPsoHandle(
678bf80f4bSopenharmony_ci        shader, graphicsStateHandle, pipelineLayout, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
688bf80f4bSopenharmony_ci}
698bf80f4bSopenharmony_ci} // namespace
708bf80f4bSopenharmony_ci
718bf80f4bSopenharmony_civoid RenderCopy::Init(IRenderNodeContextManager& renderNodeContextMgr, const CopyInfo& copyInfo)
728bf80f4bSopenharmony_ci{
738bf80f4bSopenharmony_ci    copyInfo_ = copyInfo;
748bf80f4bSopenharmony_ci    const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr.GetShaderManager();
758bf80f4bSopenharmony_ci    {
768bf80f4bSopenharmony_ci        renderData_ = {};
778bf80f4bSopenharmony_ci        renderData_.shader = shaderMgr.GetShaderHandle("rendershaders://shader/fullscreen_copy.shader");
788bf80f4bSopenharmony_ci        renderData_.pipelineLayout = shaderMgr.GetReflectionPipelineLayout(renderData_.shader);
798bf80f4bSopenharmony_ci        renderData_.sampler = renderNodeContextMgr.GetGpuResourceManager().GetSamplerHandle(
808bf80f4bSopenharmony_ci            DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
818bf80f4bSopenharmony_ci
828bf80f4bSopenharmony_ci        renderData_.shaderLayer = shaderMgr.GetShaderHandle("rendershaders://shader/fullscreen_copy_layer.shader");
838bf80f4bSopenharmony_ci        renderData_.pipelineLayoutLayer = shaderMgr.GetReflectionPipelineLayout(renderData_.shaderLayer);
848bf80f4bSopenharmony_ci    }
858bf80f4bSopenharmony_ci    {
868bf80f4bSopenharmony_ci        // single binder for both
878bf80f4bSopenharmony_ci        INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr.GetDescriptorSetManager();
888bf80f4bSopenharmony_ci        const auto& bindings = renderData_.pipelineLayout.descriptorSetLayouts[0U].bindings;
898bf80f4bSopenharmony_ci        const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
908bf80f4bSopenharmony_ci        binder_ = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
918bf80f4bSopenharmony_ci    }
928bf80f4bSopenharmony_ci}
938bf80f4bSopenharmony_ci
948bf80f4bSopenharmony_civoid RenderCopy::PreExecute(IRenderNodeContextManager& renderNodeContextMgr, const CopyInfo& copyInfo)
958bf80f4bSopenharmony_ci{
968bf80f4bSopenharmony_ci    copyInfo_ = copyInfo;
978bf80f4bSopenharmony_ci}
988bf80f4bSopenharmony_ci
998bf80f4bSopenharmony_civoid RenderCopy::Execute(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList)
1008bf80f4bSopenharmony_ci{
1018bf80f4bSopenharmony_ci    // extra blit from input to ouput
1028bf80f4bSopenharmony_ci    if (RenderHandleUtil::IsGpuImage(copyInfo_.input.handle) && RenderHandleUtil::IsGpuImage(copyInfo_.output.handle) &&
1038bf80f4bSopenharmony_ci        binder_) {
1048bf80f4bSopenharmony_ci        auto& gpuResourceMgr = renderNodeContextMgr.GetGpuResourceManager();
1058bf80f4bSopenharmony_ci
1068bf80f4bSopenharmony_ci        auto renderPass = CreateRenderPass(gpuResourceMgr, copyInfo_.output.handle);
1078bf80f4bSopenharmony_ci        RenderHandle pso;
1088bf80f4bSopenharmony_ci        if (copyInfo_.copyType == CopyType::LAYER_COPY) {
1098bf80f4bSopenharmony_ci            if (!RenderHandleUtil::IsValid(renderData_.psoLayer)) {
1108bf80f4bSopenharmony_ci                renderData_.psoLayer =
1118bf80f4bSopenharmony_ci                    CreatePso(renderNodeContextMgr, renderData_.shaderLayer, renderData_.pipelineLayoutLayer);
1128bf80f4bSopenharmony_ci            }
1138bf80f4bSopenharmony_ci            pso = renderData_.psoLayer;
1148bf80f4bSopenharmony_ci        } else {
1158bf80f4bSopenharmony_ci            if (!RenderHandleUtil::IsValid(renderData_.pso)) {
1168bf80f4bSopenharmony_ci                renderData_.pso = CreatePso(renderNodeContextMgr, renderData_.shader, renderData_.pipelineLayout);
1178bf80f4bSopenharmony_ci            }
1188bf80f4bSopenharmony_ci            pso = renderData_.pso;
1198bf80f4bSopenharmony_ci        }
1208bf80f4bSopenharmony_ci
1218bf80f4bSopenharmony_ci        cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
1228bf80f4bSopenharmony_ci        cmdList.BindPipeline(pso);
1238bf80f4bSopenharmony_ci
1248bf80f4bSopenharmony_ci        {
1258bf80f4bSopenharmony_ci            auto& binder = *binder_;
1268bf80f4bSopenharmony_ci            binder.ClearBindings();
1278bf80f4bSopenharmony_ci            uint32_t binding = 0u;
1288bf80f4bSopenharmony_ci            binder.BindSampler(
1298bf80f4bSopenharmony_ci                binding, RenderHandleUtil::IsValid(copyInfo_.sampler) ? copyInfo_.sampler : renderData_.sampler);
1308bf80f4bSopenharmony_ci            binder.BindImage(++binding, copyInfo_.input);
1318bf80f4bSopenharmony_ci            cmdList.UpdateDescriptorSet(
1328bf80f4bSopenharmony_ci                binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
1338bf80f4bSopenharmony_ci            cmdList.BindDescriptorSet(0u, binder.GetDescriptorSetHandle());
1348bf80f4bSopenharmony_ci        }
1358bf80f4bSopenharmony_ci
1368bf80f4bSopenharmony_ci        // dynamic state
1378bf80f4bSopenharmony_ci        const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr.GetRenderNodeUtil();
1388bf80f4bSopenharmony_ci        const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
1398bf80f4bSopenharmony_ci        const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
1408bf80f4bSopenharmony_ci        cmdList.SetDynamicStateViewport(viewportDesc);
1418bf80f4bSopenharmony_ci        cmdList.SetDynamicStateScissor(scissorDesc);
1428bf80f4bSopenharmony_ci
1438bf80f4bSopenharmony_ci        const auto& pl =
1448bf80f4bSopenharmony_ci            (copyInfo_.copyType == CopyType::LAYER_COPY) ? renderData_.pipelineLayoutLayer : renderData_.pipelineLayout;
1458bf80f4bSopenharmony_ci        if (pl.pushConstant.byteSize > 0) {
1468bf80f4bSopenharmony_ci            const float fWidth = static_cast<float>(renderPass.renderPassDesc.renderArea.extentWidth);
1478bf80f4bSopenharmony_ci            const float fHeight = static_cast<float>(renderPass.renderPassDesc.renderArea.extentHeight);
1488bf80f4bSopenharmony_ci            const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
1498bf80f4bSopenharmony_ci                { static_cast<float>(copyInfo_.input.layer), 0.0f, 0.0f, 0.0f } };
1508bf80f4bSopenharmony_ci            cmdList.PushConstantData(pl.pushConstant, arrayviewU8(pc));
1518bf80f4bSopenharmony_ci        }
1528bf80f4bSopenharmony_ci
1538bf80f4bSopenharmony_ci        cmdList.Draw(3u, 1u, 0u, 0u);
1548bf80f4bSopenharmony_ci        cmdList.EndRenderPass();
1558bf80f4bSopenharmony_ci    }
1568bf80f4bSopenharmony_ci}
1578bf80f4bSopenharmony_ci
1588bf80f4bSopenharmony_ciDescriptorCounts RenderCopy::GetDescriptorCounts() const
1598bf80f4bSopenharmony_ci{
1608bf80f4bSopenharmony_ci    // prepare only for a single copy operation per frame
1618bf80f4bSopenharmony_ci    return DescriptorCounts { {
1628bf80f4bSopenharmony_ci        { CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1U },
1638bf80f4bSopenharmony_ci        { CORE_DESCRIPTOR_TYPE_SAMPLER, 1U },
1648bf80f4bSopenharmony_ci    } };
1658bf80f4bSopenharmony_ci}
1668bf80f4bSopenharmony_ciRENDER_END_NAMESPACE()
167