• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_node_fullscreen_generic.h"
17 
18 #include <base/math/mathf.h>
19 #include <render/datastore/intf_render_data_store_manager.h>
20 #include <render/datastore/intf_render_data_store_pod.h>
21 #include <render/device/intf_gpu_resource_manager.h>
22 #include <render/device/intf_shader_manager.h>
23 #include <render/device/pipeline_state_desc.h>
24 #include <render/namespace.h>
25 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
26 #include <render/nodecontext/intf_node_context_pso_manager.h>
27 #include <render/nodecontext/intf_render_command_list.h>
28 #include <render/nodecontext/intf_render_node_context_manager.h>
29 #include <render/nodecontext/intf_render_node_parser_util.h>
30 #include <render/nodecontext/intf_render_node_util.h>
31 
32 #include "util/log.h"
33 
34 using namespace BASE_NS;
35 
RENDER_BEGIN_NAMESPACE()36 RENDER_BEGIN_NAMESPACE()
37 void RenderNodeFullscreenGeneric::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
38 {
39     renderNodeContextMgr_ = &renderNodeContextMgr;
40     pipelineData_ = {};
41     ParseRenderNodeInputs();
42 
43     useDataStoreShaderSpecialization_ = !jsonInputs_.renderDataStoreSpecialization.dataStoreName.empty();
44 
45     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
46     if (RenderHandleUtil::GetHandleType(pipelineData_.gsd.shader) != RenderHandleType::SHADER_STATE_OBJECT) {
47         PLUGIN_LOG_E("RenderNodeFullscreenGeneric needs a valid shader handle");
48     }
49 
50     if (useDataStoreShaderSpecialization_) {
51         const ShaderSpecializationConstantView sscv = shaderMgr.GetReflectionSpecialization(pipelineData_.gsd.shader);
52         shaderSpecializationData_.constants.resize(sscv.constants.size());
53         shaderSpecializationData_.data.resize(sscv.constants.size());
54         for (size_t idx = 0; idx < shaderSpecializationData_.constants.size(); ++idx) {
55             shaderSpecializationData_.constants[idx] = sscv.constants[idx];
56             shaderSpecializationData_.data[idx] = ~0u;
57         }
58         useDataStoreShaderSpecialization_ = !sscv.constants.empty();
59     }
60 
61     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
62     pipelineData_.gsd = shaderMgr.GetGraphicsShaderDataByShaderHandle(pipelineData_.gsd.shader);
63     pipelineData_.pso = GetPsoHandle();
64 
65     {
66         const DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(pipelineData_.gsd.pipelineLayoutData);
67         renderNodeContextMgr.GetDescriptorSetManager().ResetAndReserve(dc);
68     }
69 
70     pipelineDescriptorSetBinder_ =
71         renderNodeUtil.CreatePipelineDescriptorSetBinder(pipelineData_.gsd.pipelineLayoutData);
72     renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
73 
74     useDataStorePushConstant_ = (pipelineData_.gsd.pipelineLayoutData.pushConstant.byteSize > 0) &&
75                                 (!jsonInputs_.renderDataStore.dataStoreName.empty()) &&
76                                 (!jsonInputs_.renderDataStore.configurationName.empty());
77 }
78 
PreExecuteFrame()79 void RenderNodeFullscreenGeneric::PreExecuteFrame()
80 {
81     // re-create needed gpu resources
82 }
83 
ExecuteFrame(IRenderCommandList & cmdList)84 void RenderNodeFullscreenGeneric::ExecuteFrame(IRenderCommandList& cmdList)
85 {
86     if (!RENDER_NS::RenderHandleUtil::IsValid(pipelineData_.pso)) {
87         return;
88     }
89 
90     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
91     if (jsonInputs_.hasChangeableRenderPassHandles) {
92         inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
93     }
94     if (jsonInputs_.hasChangeableResourceHandles) {
95         inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
96         renderNodeUtil.BindResourcesToBinder(inputResources_, *pipelineDescriptorSetBinder_);
97     }
98 
99     const RenderPass renderPass = renderNodeUtil.CreateRenderPass(inputRenderPass_);
100     const ViewportDesc viewportDesc = renderNodeUtil.CreateDefaultViewport(renderPass);
101     const ScissorDesc scissorDesc = renderNodeUtil.CreateDefaultScissor(renderPass);
102 
103     const auto setIndices = pipelineDescriptorSetBinder_->GetSetIndices();
104     const uint32_t firstSetIndex = pipelineDescriptorSetBinder_->GetFirstSet();
105     for (auto refIndex : setIndices) {
106         const auto descHandle = pipelineDescriptorSetBinder_->GetDescriptorSetHandle(refIndex);
107         const auto bindings = pipelineDescriptorSetBinder_->GetDescriptorSetLayoutBindingResources(refIndex);
108         cmdList.UpdateDescriptorSet(descHandle, bindings);
109     }
110 #if (RENDER_VALIDATION_ENABLED == 1)
111     if (!pipelineDescriptorSetBinder_->GetPipelineDescriptorSetLayoutBindingValidity()) {
112         PLUGIN_LOG_ONCE_E(renderNodeContextMgr_->GetName() + "_RCL_UpdateDescriptorSet_invalid_",
113             "RENDER_VALIDATION: RenderNodeFullscreenGeneric: bindings missing (RN: %s)",
114             renderNodeContextMgr_->GetName().data());
115     }
116 #endif
117 
118     cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
119 
120     const RenderHandle psoHandle = GetPsoHandle();
121     cmdList.BindPipeline(psoHandle);
122 
123     // bind all sets from the first on-wards
124     cmdList.BindDescriptorSets(firstSetIndex, pipelineDescriptorSetBinder_->GetDescriptorSetHandles());
125 
126     // dynamic state
127     cmdList.SetDynamicStateViewport(viewportDesc);
128     cmdList.SetDynamicStateScissor(scissorDesc);
129     if (renderPass.subpassDesc.fragmentShadingRateAttachmentCount > 0) {
130         cmdList.SetDynamicStateFragmentShadingRate(
131             { 1u, 1u }, FragmentShadingRateCombinerOps { CORE_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE,
132                             CORE_FRAGMENT_SHADING_RATE_COMBINER_OP_REPLACE });
133     }
134 
135     // push constants
136     if (useDataStorePushConstant_) {
137         const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
138         const auto dataStore = static_cast<const IRenderDataStorePod*>(
139             renderDataStoreMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName));
140         if (dataStore) {
141             const auto dataView = dataStore->Get(jsonInputs_.renderDataStore.configurationName);
142             if (!dataView.empty()) {
143                 cmdList.PushConstant(pipelineData_.gsd.pipelineLayoutData.pushConstant, dataView.data());
144             }
145         }
146     }
147 
148     cmdList.Draw(3u, 1u, 0u, 0u); // vertex count, instance count, first vertex, first instance
149     cmdList.EndRenderPass();
150 }
151 
GetPsoHandle()152 RenderHandle RenderNodeFullscreenGeneric::GetPsoHandle()
153 {
154     // controlled by count
155     constexpr DynamicStateEnum dynamicStates[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR,
156         CORE_DYNAMIC_STATE_ENUM_FRAGMENT_SHADING_RATE };
157     if (useDataStoreShaderSpecialization_) {
158         const auto& renderDataStoreMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
159         const auto dataStore = static_cast<const IRenderDataStorePod*>(
160             renderDataStoreMgr.GetRenderDataStore(jsonInputs_.renderDataStoreSpecialization.dataStoreName));
161         if (!dataStore) {
162             return pipelineData_.pso;
163         }
164         const auto dataView = dataStore->Get(jsonInputs_.renderDataStoreSpecialization.configurationName);
165         if (dataView.data() && (dataView.size_bytes() == sizeof(ShaderSpecializationRenderPod))) {
166             const auto* spec = reinterpret_cast<const ShaderSpecializationRenderPod*>(dataView.data());
167             bool valuesChanged = false;
168             const uint32_t specializationCount = Math::min(
169                 Math::min(spec->specializationConstantCount, (uint32_t)shaderSpecializationData_.constants.size()),
170                 ShaderSpecializationRenderPod::MAX_SPECIALIZATION_CONSTANT_COUNT);
171             for (uint32_t idx = 0; idx < specializationCount; ++idx) {
172                 const auto& ref = shaderSpecializationData_.constants[idx];
173                 const uint32_t constantId = ref.offset / sizeof(uint32_t);
174                 const uint32_t specId = ref.id;
175                 if ((specId < ShaderSpecializationRenderPod::MAX_SPECIALIZATION_CONSTANT_COUNT) &&
176                     (shaderSpecializationData_.data[constantId] != spec->specializationFlags[specId].value)) {
177                     shaderSpecializationData_.data[constantId] = spec->specializationFlags[specId].value;
178                     valuesChanged = true;
179                 }
180             }
181             if (valuesChanged) {
182                 const ShaderSpecializationConstantDataView specialization {
183                     { shaderSpecializationData_.constants.data(), specializationCount },
184                     { shaderSpecializationData_.data.data(), specializationCount }
185                 };
186                 const uint32_t dynamicStateCount =
187                     (inputRenderPass_.fragmentShadingRateAttachmentIndex != ~0u) ? 3u : 2u;
188                 pipelineData_.pso = renderNodeContextMgr_->GetPsoManager().GetGraphicsPsoHandle(
189                     pipelineData_.gsd.shader, pipelineData_.gsd.graphicsState, pipelineData_.gsd.pipelineLayout, {},
190                     specialization, { dynamicStates, dynamicStateCount });
191             }
192         } else {
193 #if (RENDER_VALIDATION_ENABLED == 1)
194             const string logName = "RenderNodeFullscreenGeneric_ShaderSpecialization" +
195                                    string(jsonInputs_.renderDataStoreSpecialization.configurationName);
196             PLUGIN_LOG_ONCE_E(logName.c_str(),
197                 "RENDER_VALIDATION: RenderNodeFullscreenGeneric shader specilization render data store size "
198                 "mismatch, name: %s, size:%u, podsize%u",
199                 jsonInputs_.renderDataStoreSpecialization.configurationName.c_str(),
200                 static_cast<uint32_t>(sizeof(ShaderSpecializationRenderPod)),
201                 static_cast<uint32_t>(dataView.size_bytes()));
202 #endif
203         }
204     } else if (!RenderHandleUtil::IsValid(pipelineData_.pso)) {
205         const uint32_t dynamicStateCount = (inputRenderPass_.fragmentShadingRateAttachmentIndex != ~0u) ? 3u : 2u;
206         pipelineData_.pso = renderNodeContextMgr_->GetPsoManager().GetGraphicsPsoHandle(pipelineData_.gsd.shader,
207             pipelineData_.gsd.graphicsState, pipelineData_.gsd.pipelineLayout, {}, {},
208             { dynamicStates, dynamicStateCount });
209     }
210     return pipelineData_.pso;
211 }
212 
ParseRenderNodeInputs()213 void RenderNodeFullscreenGeneric::ParseRenderNodeInputs()
214 {
215     const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
216     const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
217     jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
218     jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
219     jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
220     jsonInputs_.renderDataStoreSpecialization =
221         parserUtil.GetRenderDataStore(jsonVal, "renderDataStoreShaderSpecialization");
222 
223     const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
224     const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
225     pipelineData_.gsd.shader = shaderMgr.GetShaderHandle(shaderName);
226 
227     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
228     inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
229     inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
230 
231     jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
232     jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
233 }
234 
235 // for plugin / factory interface
Create()236 IRenderNode* RenderNodeFullscreenGeneric::Create()
237 {
238     return new RenderNodeFullscreenGeneric();
239 }
240 
Destroy(IRenderNode * instance)241 void RenderNodeFullscreenGeneric::Destroy(IRenderNode* instance)
242 {
243     delete static_cast<RenderNodeFullscreenGeneric*>(instance);
244 }
245 RENDER_END_NAMESPACE()
246