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