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