1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "render_copy_helper.h"
17 
18 #include <render/device/intf_gpu_resource_manager.h>
19 #include <render/device/intf_shader_manager.h>
20 #include <render/device/pipeline_layout_desc.h>
21 #include <render/device/pipeline_state_desc.h>
22 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
23 #include <render/nodecontext/intf_node_context_pso_manager.h>
24 #include <render/nodecontext/intf_pipeline_descriptor_set_binder.h>
25 #include <render/nodecontext/intf_render_command_list.h>
26 #include <render/nodecontext/intf_render_node_context_manager.h>
27 #include <render/nodecontext/intf_render_node_util.h>
28 
29 using namespace BASE_NS;
30 using namespace RENDER_NS;
31 
32 CORE3D_BEGIN_NAMESPACE()
33 namespace {
34 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
35 
CreateRenderPass(const IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandle input)36 RenderPass CreateRenderPass(const IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandle input)
37 {
38     const GpuImageDesc desc = gpuResourceMgr.GetImageDescriptor(input);
39     RenderPass rp;
40     rp.renderPassDesc.attachmentCount = 1u;
41     rp.renderPassDesc.attachmentHandles[0u] = input;
42     rp.renderPassDesc.attachments[0u].loadOp = AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
43     rp.renderPassDesc.attachments[0u].storeOp = AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE;
44     rp.renderPassDesc.renderArea = { 0, 0, desc.width, desc.height };
45 
46     rp.renderPassDesc.subpassCount = 1u;
47     rp.subpassDesc.colorAttachmentCount = 1u;
48     rp.subpassDesc.colorAttachmentIndices[0u] = 0u;
49     rp.subpassStartIndex = 0u;
50     return rp;
51 }
52 } // namespace
53 
Init(IRenderNodeContextManager & renderNodeContextMgr,const CopyInfo & copyInfo)54 void RenderCopyHelper::Init(IRenderNodeContextManager& renderNodeContextMgr, const CopyInfo& copyInfo)
55 {
56     copyInfo_ = copyInfo;
57     {
58         const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr.GetShaderManager();
59         renderData_ = {};
60         renderData_.shader = shaderMgr.GetShaderHandle("rendershaders://shader/fullscreen_copy.shader");
61         renderData_.pipelineLayout = shaderMgr.GetReflectionPipelineLayout(renderData_.shader);
62         renderData_.sampler =
63             renderNodeContextMgr.GetGpuResourceManager().GetSamplerHandle("CORE_DEFAULT_SAMPLER_LINEAR_CLAMP");
64     }
65     {
66         INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr.GetDescriptorSetManager();
67         const auto& bindings = renderData_.pipelineLayout.descriptorSetLayouts[0U].bindings;
68         const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
69         binder_ = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
70     }
71 }
72 
PreExecute(IRenderNodeContextManager & renderNodeContextMgr,const CopyInfo & copyInfo)73 void RenderCopyHelper::PreExecute(IRenderNodeContextManager& renderNodeContextMgr, const CopyInfo& copyInfo)
74 {
75     copyInfo_ = copyInfo;
76 }
77 
Execute(IRenderNodeContextManager & renderNodeContextMgr,IRenderCommandList & cmdList)78 void RenderCopyHelper::Execute(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList)
79 {
80     // extra copy from input to ouput
81     if ((RenderHandleUtil::GetHandleType(copyInfo_.input) == RenderHandleType::GPU_IMAGE) &&
82         (RenderHandleUtil::GetHandleType(copyInfo_.output) == RenderHandleType::GPU_IMAGE) && binder_) {
83         auto& gpuResourceMgr = renderNodeContextMgr.GetGpuResourceManager();
84         auto renderPass = CreateRenderPass(gpuResourceMgr, copyInfo_.output);
85         if (!RenderHandleUtil::IsValid(renderData_.pso)) {
86             auto& psoMgr = renderNodeContextMgr.GetPsoManager();
87             const auto& shaderMgr = renderNodeContextMgr.GetShaderManager();
88             const RenderHandle graphicsStateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(renderData_.shader);
89             renderData_.pso = psoMgr.GetGraphicsPsoHandle(renderData_.shader, graphicsStateHandle,
90                 renderData_.pipelineLayout, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
91         }
92 
93         cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
94         cmdList.BindPipeline(renderData_.pso);
95 
96         {
97             auto& binder = *binder_;
98             binder.ClearBindings();
99             uint32_t binding = 0u;
100             binder.BindSampler(
101                 binding, RenderHandleUtil::IsValid(copyInfo_.sampler) ? copyInfo_.sampler : renderData_.sampler);
102             binder.BindImage(++binding, copyInfo_.input);
103             cmdList.UpdateDescriptorSet(
104                 binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
105             cmdList.BindDescriptorSet(0u, binder.GetDescriptorSetHandle());
106         }
107 
108         // dynamic state
109         const IRenderNodeUtil& renderNodeUtil = renderNodeContextMgr.GetRenderNodeUtil();
110         const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
111         const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
112         cmdList.SetDynamicStateViewport(viewportDesc);
113         cmdList.SetDynamicStateScissor(scissorDesc);
114 
115         cmdList.Draw(3u, 1u, 0u, 0u);
116         cmdList.EndRenderPass();
117     }
118 }
119 
GetDescriptorCounts() const120 DescriptorCounts RenderCopyHelper::GetDescriptorCounts() const
121 {
122     // expected high max mip count
123     return DescriptorCounts { {
124         { CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1U },
125         { CORE_DESCRIPTOR_TYPE_SAMPLER, 1U },
126     } };
127 }
128 CORE3D_END_NAMESPACE()
129