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_mip_chain_post_process.h"
17
18 #include <algorithm>
19
20 #include <base/containers/string_view.h>
21 #include <base/containers/type_traits.h>
22 #include <base/math/mathf.h>
23 #include <render/datastore/intf_render_data_store_manager.h>
24 #include <render/datastore/intf_render_data_store_pod.h>
25 #include <render/datastore/render_data_store_render_pods.h>
26 #include <render/device/intf_gpu_resource_manager.h>
27 #include <render/device/intf_shader_manager.h>
28 #include <render/nodecontext/intf_node_context_descriptor_set_manager.h>
29 #include <render/nodecontext/intf_node_context_pso_manager.h>
30 #include <render/nodecontext/intf_render_command_list.h>
31 #include <render/nodecontext/intf_render_node_context_manager.h>
32 #include <render/nodecontext/intf_render_node_graph_share_manager.h>
33 #include <render/nodecontext/intf_render_node_parser_util.h>
34 #include <render/nodecontext/intf_render_node_util.h>
35 #include <render/shaders/common/render_post_process_structs_common.h>
36
37 #include "datastore/render_data_store_pod.h"
38 #include "datastore/render_data_store_post_process.h"
39 #include "default_engine_constants.h"
40 #include "util/log.h"
41
42 using namespace BASE_NS;
43
44 RENDER_BEGIN_NAMESPACE()
45 namespace {
46 constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR };
47
48 constexpr uint32_t GLOBAL_POST_PROCESS_SET { 0u };
49 constexpr uint32_t LOCAL_POST_PROCESS_SET { 1u };
50 constexpr string_view RENDER_DATA_STORE_POD_NAME { RenderDataStorePod::TYPE_NAME };
51 constexpr string_view INPUT = "input";
52 constexpr string_view OUTPUT = "output";
53
54 constexpr string_view POST_PROCESS_BASE_PIPELINE_LAYOUT { "renderpipelinelayouts://post_process_common.shaderpl" };
55
56 constexpr uint32_t MAX_MIP_COUNT { 16u };
57 constexpr uint32_t MAX_PASS_PER_LEVEL_COUNT { 1u };
58 constexpr uint32_t MAX_LOCAL_BINDER_COUNT = MAX_MIP_COUNT * MAX_PASS_PER_LEVEL_COUNT;
59
CreatePostProcessDataUniformBuffer(IRenderNodeGpuResourceManager & gpuResourceMgr,const RenderHandleReference & handle)60 RenderHandleReference CreatePostProcessDataUniformBuffer(
61 IRenderNodeGpuResourceManager& gpuResourceMgr, const RenderHandleReference& handle)
62 {
63 PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
64 PLUGIN_STATIC_ASSERT(
65 sizeof(LocalPostProcessStruct) == PipelineLayoutConstants::MIN_UBO_BIND_OFFSET_ALIGNMENT_BYTE_SIZE);
66 return gpuResourceMgr.Create(
67 handle, GpuBufferDesc { CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
68 (CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT | CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT),
69 CORE_ENGINE_BUFFER_CREATION_DYNAMIC_RING_BUFFER,
70 sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct) });
71 }
72
GetBindableImage(const RenderHandle & res)73 inline BindableImage GetBindableImage(const RenderHandle& res)
74 {
75 return BindableImage { res, PipelineStateConstants::GPU_IMAGE_ALL_MIP_LEVELS,
76 PipelineStateConstants::GPU_IMAGE_ALL_LAYERS, ImageLayout::CORE_IMAGE_LAYOUT_UNDEFINED, {} };
77 }
78 } // namespace
79
InitNode(IRenderNodeContextManager & renderNodeContextMgr)80 void RenderNodeMipChainPostProcess::InitNode(IRenderNodeContextManager& renderNodeContextMgr)
81 {
82 renderNodeContextMgr_ = &renderNodeContextMgr;
83
84 valid_ = true;
85 ubos_.postProcess =
86 CreatePostProcessDataUniformBuffer(renderNodeContextMgr.GetGpuResourceManager(), ubos_.postProcess);
87
88 ParseRenderNodeInputs();
89 UpdateImageData();
90 ProcessPostProcessConfiguration();
91
92 if (RenderHandleUtil::GetHandleType(pipelineData_.shader) != RenderHandleType::SHADER_STATE_OBJECT) {
93 PLUGIN_LOG_E("CORE_RN_MIP_CHAIN_POST_PROCESS needs a valid shader handle");
94 }
95
96 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
97 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
98 const RenderHandleType handleType = RenderHandleUtil::GetHandleType(pipelineData_.shader);
99 if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
100 pipelineData_.graphics = true;
101 } else if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
102 pipelineData_.graphics = false;
103 pipelineData_.threadGroupSize = shaderMgr.GetReflectionThreadGroupSize(pipelineData_.shader);
104 if (dispatchResources_.customInputBuffers.empty() && dispatchResources_.customInputImages.empty()) {
105 valid_ = false;
106 PLUGIN_LOG_W("CORE_RN_MIP_CHAIN_POST_PROCESS: dispatchResources (GPU buffer or GPU image) needed");
107 }
108 }
109
110 {
111 if (!((handleType == RenderHandleType::SHADER_STATE_OBJECT) ||
112 (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT))) {
113 PLUGIN_LOG_E("RN:%s needs a valid shader handle", renderNodeContextMgr_->GetName().data());
114 }
115 pipelineData_.pipelineLayout = shaderMgr.GetReflectionPipelineLayoutHandle(pipelineData_.shader);
116 pipelineData_.pipelineLayoutData = shaderMgr.GetPipelineLayout(pipelineData_.pipelineLayout);
117 if (pipelineData_.graphics) {
118 const RenderHandle graphicsState = shaderMgr.GetGraphicsStateHandleByShaderHandle(pipelineData_.shader);
119 pipelineData_.pso = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(pipelineData_.shader,
120 graphicsState, pipelineData_.pipelineLayoutData, {}, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) });
121 } else {
122 pipelineData_.pso = renderNodeContextMgr.GetPsoManager().GetComputePsoHandle(
123 pipelineData_.shader, pipelineData_.pipelineLayout, {});
124 }
125
126 // NOTE: cannot be compared with shaderMgr.GetCompatibilityFlags due to missing pipeline layout handle
127 const RenderHandle basePlHandle = shaderMgr.GetPipelineLayoutHandle(POST_PROCESS_BASE_PIPELINE_LAYOUT);
128 const IShaderManager::CompatibilityFlags compatibilityFlags =
129 shaderMgr.GetCompatibilityFlags(basePlHandle, pipelineData_.pipelineLayout);
130 if ((compatibilityFlags & IShaderManager::CompatibilityFlagBits::COMPATIBLE_BIT) == 0) {
131 PLUGIN_LOG_E("RN:%s uncompatible pipeline layout to %s", renderNodeContextMgr_->GetName().data(),
132 POST_PROCESS_BASE_PIPELINE_LAYOUT.data());
133 }
134 }
135
136 {
137 DescriptorCounts dc = renderNodeUtil.GetDescriptorCounts(pipelineData_.pipelineLayoutData);
138 // NOTE: hard-coded mip chain
139 dc.counts.push_back({ CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, MAX_LOCAL_BINDER_COUNT });
140 dc.counts.push_back({ CORE_DESCRIPTOR_TYPE_SAMPLER, MAX_LOCAL_BINDER_COUNT });
141 const DescriptorCounts copyDc = renderCopy_.GetDescriptorCounts();
142 for (const auto& ref : copyDc.counts) {
143 dc.counts.push_back(ref);
144 }
145 renderNodeContextMgr.GetDescriptorSetManager().ResetAndReserve(dc);
146 }
147
148 {
149 binders_.clear();
150 binders_.resize(MAX_LOCAL_BINDER_COUNT);
151
152 INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr.GetDescriptorSetManager();
153 {
154 const auto& bindings =
155 pipelineData_.pipelineLayoutData.descriptorSetLayouts[GLOBAL_POST_PROCESS_SET].bindings;
156 const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
157 globalSet0_ = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
158 }
159 const auto& bindings = pipelineData_.pipelineLayoutData.descriptorSetLayouts[LOCAL_POST_PROCESS_SET].bindings;
160 for (uint32_t idx = 0; idx < MAX_LOCAL_BINDER_COUNT; ++idx) {
161 const RenderHandle descHandle = descriptorSetMgr.CreateDescriptorSet(bindings);
162 binders_[idx] = descriptorSetMgr.CreateDescriptorSetBinder(descHandle, bindings);
163 }
164 }
165
166 renderCopy_.Init(renderNodeContextMgr, {});
167 RegisterOutputs(builtInVariables_.output);
168 }
169
PreExecuteFrame()170 void RenderNodeMipChainPostProcess::PreExecuteFrame()
171 {
172 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
173 if (jsonInputs_.hasChangeableResourceHandles) {
174 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
175 }
176 UpdateImageData();
177 ProcessPostProcessConfiguration();
178 if (pipelineData_.graphics && GetRequiresPreCopy()) {
179 RenderCopy::CopyInfo copyInfo { GetBindableImage(builtInVariables_.input),
180 GetBindableImage(builtInVariables_.output), {} };
181 renderCopy_.PreExecute(*renderNodeContextMgr_, copyInfo);
182 }
183 RegisterOutputs(builtInVariables_.output);
184 }
185
ExecuteFrame(IRenderCommandList & cmdList)186 void RenderNodeMipChainPostProcess::ExecuteFrame(IRenderCommandList& cmdList)
187 {
188 if ((!ppLocalConfig_.variables.enabled) &&
189 (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
190 return;
191 }
192
193 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
194 if (jsonInputs_.hasChangeableRenderPassHandles) {
195 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
196 }
197 if (jsonInputs_.hasChangeableResourceHandles) {
198 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
199 }
200 if (jsonInputs_.hasChangeableDispatchHandles) {
201 dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
202 }
203 if (useAutoBindSet0_) {
204 UpdateGlobalPostProcessUbo();
205 }
206
207 if (pipelineData_.graphics) {
208 RenderGraphics(cmdList);
209 } else {
210 RenderCompute(cmdList);
211 }
212 }
213
GetExecuteFlags() const214 IRenderNode::ExecuteFlags RenderNodeMipChainPostProcess::GetExecuteFlags() const
215 {
216 if ((!ppLocalConfig_.variables.enabled) &&
217 (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
218 return ExecuteFlagBits::EXECUTE_FLAG_BITS_DO_NOT_EXECUTE;
219 }
220 return ExecuteFlagBits::EXECUTE_FLAG_BITS_DEFAULT;
221 }
222
ProcessPostProcessConfiguration()223 void RenderNodeMipChainPostProcess::ProcessPostProcessConfiguration()
224 {
225 if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
226 auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
227 if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName)) {
228 if (jsonInputs_.renderDataStore.typeName == RenderDataStorePostProcess::TYPE_NAME) {
229 auto* const dataStore = static_cast<IRenderDataStorePostProcess const*>(ds);
230 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
231 }
232 }
233 if (const IRenderDataStorePod* ds =
234 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME))) {
235 auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
236 if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
237 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
238 }
239 }
240 } else if (jsonInputs_.ppName.empty()) {
241 // if trying to just use shader without post processing we enable running by default
242 ppLocalConfig_.variables.enabled = true;
243 }
244 }
245
UpdateGlobalPostProcessUbo()246 void RenderNodeMipChainPostProcess::UpdateGlobalPostProcessUbo()
247 {
248 auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
249 const RenderPostProcessConfiguration rppc =
250 renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
251 PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
252 PLUGIN_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
253 sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
254 if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
255 const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
256 // global data
257 CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
258 // local data
259 data += sizeof(GlobalPostProcessStruct);
260 CloneData(
261 data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
262 gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
263 }
264 }
265
266 // constants for RenderNodeMipChainPostProcess::RenderData
267 namespace {
268 constexpr bool USE_CUSTOM_BARRIERS = true;
269
270 constexpr ImageResourceBarrier SRC_UNDEFINED { 0, CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, CORE_IMAGE_LAYOUT_UNDEFINED };
271 constexpr ImageResourceBarrier COL_ATTACHMENT { CORE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
272 CORE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, CORE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
273 constexpr ImageResourceBarrier SHDR_READ { CORE_ACCESS_SHADER_READ_BIT, CORE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
274 CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
275 // transition the final mip level to read only as well
276 constexpr ImageResourceBarrier FINAL_SRC { CORE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
277 CORE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | CORE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
278 CORE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
279 constexpr ImageResourceBarrier FINAL_DST { CORE_ACCESS_SHADER_READ_BIT,
280 CORE_PIPELINE_STAGE_VERTEX_SHADER_BIT, // first possible shader read stage
281 CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
282 } // namespace
283
GetRequiresPreCopy() const284 bool RenderNodeMipChainPostProcess::GetRequiresPreCopy() const
285 {
286 // check for first copy from another image
287 if (builtInVariables_.input != builtInVariables_.output) {
288 return true;
289 } else {
290 return false;
291 }
292 }
293
GetBaseRenderPass()294 RenderPass RenderNodeMipChainPostProcess::GetBaseRenderPass()
295 {
296 RenderPass renderPass = renderNodeContextMgr_->GetRenderNodeUtil().CreateRenderPass(inputRenderPass_);
297 RenderHandle imageHandle = renderPass.renderPassDesc.attachmentHandles[0];
298 // find the target image if not provided with the render pass
299 if (!RenderHandleUtil::IsValid(imageHandle)) {
300 if ((!inputResources_.customOutputImages.empty()))
301 imageHandle = inputResources_.customOutputImages[0].handle;
302 }
303 renderPass.renderPassDesc.attachmentCount = 1;
304 renderPass.renderPassDesc.subpassCount = 1;
305 renderPass.renderPassDesc.attachments[0].loadOp = CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
306 renderPass.renderPassDesc.attachments[0].storeOp = CORE_ATTACHMENT_STORE_OP_STORE;
307 renderPass.renderPassDesc.attachmentHandles[0] = imageHandle;
308 renderPass.subpassStartIndex = 0;
309 auto& subpass = renderPass.subpassDesc;
310 subpass.colorAttachmentCount = 1;
311 subpass.colorAttachmentIndices[0] = 0;
312 return renderPass;
313 }
314
UpdateGlobalSet(IRenderCommandList & cmdList)315 void RenderNodeMipChainPostProcess::UpdateGlobalSet(IRenderCommandList& cmdList)
316 {
317 auto& binder = *globalSet0_;
318 binder.ClearBindings();
319 uint32_t binding = 0u;
320 binder.BindBuffer(binding++, BindableBuffer { ubos_.postProcess.GetHandle() });
321 binder.BindBuffer(binding++, BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
322 cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
323 }
324
RenderGraphics(IRenderCommandList & cmdList)325 void RenderNodeMipChainPostProcess::RenderGraphics(IRenderCommandList& cmdList)
326 {
327 RenderPass renderPass = GetBaseRenderPass();
328
329 const RenderHandle imageHandle = renderPass.renderPassDesc.attachmentHandles[0];
330 if (!RenderHandleUtil::IsValid(imageHandle)) {
331 return; // early out
332 }
333 const GpuImageDesc imageDesc = renderNodeContextMgr_->GetGpuResourceManager().GetImageDescriptor(imageHandle);
334 if (imageDesc.mipCount <= 1U) {
335 return; // early out
336 }
337 renderPass.renderPassDesc.renderArea = { 0, 0, imageDesc.width, imageDesc.height };
338 // check for first copy from another image
339 if (builtInVariables_.input != builtInVariables_.output) {
340 renderCopy_.Execute(*renderNodeContextMgr_, cmdList);
341 }
342
343 if constexpr (USE_CUSTOM_BARRIERS) {
344 cmdList.BeginDisableAutomaticBarrierPoints();
345 }
346
347 UpdateGlobalSet(cmdList);
348
349 ImageSubresourceRange imageSubresourceRange { CORE_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0,
350 PipelineStateConstants::GPU_IMAGE_ALL_LAYERS };
351 for (uint32_t idx = 1U; idx < imageDesc.mipCount; ++idx) {
352 const uint32_t renderPassMipLevel = jsonInputs_.upRamp ? (imageDesc.mipCount - idx - 1) : idx;
353 const uint32_t inputMipLevel = jsonInputs_.upRamp ? (imageDesc.mipCount - idx) : (idx - 1);
354
355 const uint32_t width = std::max(1u, imageDesc.width >> renderPassMipLevel);
356 const uint32_t height = std::max(1u, imageDesc.height >> renderPassMipLevel);
357 const float fWidth = static_cast<float>(width);
358 const float fHeight = static_cast<float>(height);
359
360 renderPass.renderPassDesc.renderArea = { 0, 0, width, height };
361 renderPass.renderPassDesc.attachments[0].mipLevel = renderPassMipLevel;
362
363 if constexpr (USE_CUSTOM_BARRIERS) {
364 imageSubresourceRange.baseMipLevel = renderPassMipLevel;
365 cmdList.CustomImageBarrier(imageHandle, SRC_UNDEFINED, COL_ATTACHMENT, imageSubresourceRange);
366
367 imageSubresourceRange.baseMipLevel = inputMipLevel;
368 if (inputMipLevel == 0) {
369 cmdList.CustomImageBarrier(imageHandle, SHDR_READ, imageSubresourceRange);
370 } else {
371 cmdList.CustomImageBarrier(imageHandle, COL_ATTACHMENT, SHDR_READ, imageSubresourceRange);
372 }
373
374 cmdList.AddCustomBarrierPoint();
375 }
376
377 // update local descriptor set
378 {
379 // hard-coded
380 auto& binder = *binders_[idx];
381 uint32_t binding = 0;
382 binder.BindSampler(binding++, BindableSampler { samplerHandle_ });
383 binder.BindImage(binding++, BindableImage { imageHandle, inputMipLevel });
384 cmdList.UpdateDescriptorSet(
385 binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
386 #if (RENDER_VALIDATION_ENABLED == 1)
387 if (!binder.GetDescriptorSetLayoutBindingValidity()) {
388 PLUGIN_LOG_W("RN: %s, bindings missing", renderNodeContextMgr_->GetName().data());
389 }
390 #endif
391 }
392
393 cmdList.BeginRenderPass(renderPass.renderPassDesc, renderPass.subpassStartIndex, renderPass.subpassDesc);
394
395 cmdList.SetDynamicStateViewport(ViewportDesc { 0.0f, 0.0f, fWidth, fHeight, 0.0f, 0.0f });
396 cmdList.SetDynamicStateScissor(ScissorDesc { 0, 0, width, height });
397
398 cmdList.BindPipeline(pipelineData_.pso);
399
400 // bind all sets
401 {
402 RenderHandle sets[2U] {};
403 sets[0U] = globalSet0_->GetDescriptorSetHandle();
404 sets[1U] = binders_[idx]->GetDescriptorSetHandle();
405 cmdList.BindDescriptorSets(0u, sets);
406 }
407
408 // push constants
409 if (pipelineData_.pipelineLayoutData.pushConstant.byteSize > 0) {
410 const LocalPostProcessPushConstantStruct pc { { fWidth, fHeight, 1.0f / fWidth, 1.0f / fHeight },
411 ppLocalConfig_.variables.factor };
412 cmdList.PushConstantData(pipelineData_.pipelineLayoutData.pushConstant, arrayviewU8(pc));
413 }
414
415 cmdList.Draw(3U, 1U, 0U, 0U);
416 cmdList.EndRenderPass();
417 }
418
419 if constexpr (USE_CUSTOM_BARRIERS) {
420 if (imageDesc.mipCount > 1U) {
421 // transition the final mip level
422 imageSubresourceRange.baseMipLevel = imageDesc.mipCount - 1;
423 cmdList.CustomImageBarrier(imageHandle, FINAL_SRC, FINAL_DST, imageSubresourceRange);
424 }
425 cmdList.AddCustomBarrierPoint();
426 cmdList.EndDisableAutomaticBarrierPoints();
427 }
428 }
429
RenderCompute(IRenderCommandList & cmdList)430 void RenderNodeMipChainPostProcess::RenderCompute(IRenderCommandList& cmdList)
431 {
432 // NOTE: not yet supported
433 }
434
BindDefaultResources(const uint32_t set,const DescriptorSetLayoutBindingResources & bindings)435 void RenderNodeMipChainPostProcess::BindDefaultResources(
436 const uint32_t set, const DescriptorSetLayoutBindingResources& bindings)
437 {
438 // NOTE: not yet supported
439 }
440
RegisterOutputs(const RenderHandle output)441 void RenderNodeMipChainPostProcess::RegisterOutputs(const RenderHandle output)
442 {
443 IRenderNodeGraphShareManager& shrMgr = renderNodeContextMgr_->GetRenderNodeGraphShareManager();
444 RenderHandle registerOutput;
445 if (ppLocalConfig_.variables.enabled) {
446 if (RenderHandleUtil::IsValid(output)) {
447 registerOutput = output;
448 }
449 }
450 if (!RenderHandleUtil::IsValid(registerOutput)) {
451 if (((jsonInputs_.defaultOutputImage == DefaultOutputImage::OUTPUT) ||
452 (jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT_OUTPUT_COPY)) &&
453 RenderHandleUtil::IsValid(output)) {
454 registerOutput = output;
455 } else if ((jsonInputs_.defaultOutputImage == DefaultOutputImage::INPUT) &&
456 RenderHandleUtil::IsValid(builtInVariables_.input)) {
457 registerOutput = builtInVariables_.input;
458 } else if (jsonInputs_.defaultOutputImage == DefaultOutputImage::WHITE) {
459 registerOutput = builtInVariables_.defWhiteImage;
460 } else {
461 registerOutput = builtInVariables_.defBlackImage;
462 }
463 }
464 shrMgr.RegisterRenderNodeOutput("output", registerOutput);
465 }
466
ParseRenderNodeInputs()467 void RenderNodeMipChainPostProcess::ParseRenderNodeInputs()
468 {
469 const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil();
470 const auto jsonVal = renderNodeContextMgr_->GetNodeJson();
471
472 const auto shaderName = parserUtil.GetStringValue(jsonVal, "shader");
473 const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr_->GetShaderManager();
474 pipelineData_.shader = shaderMgr.GetShaderHandle(shaderName);
475 jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass");
476 jsonInputs_.resources = parserUtil.GetInputResources(jsonVal, "resources");
477 jsonInputs_.dispatchResources = parserUtil.GetInputResources(jsonVal, "dispatchResources");
478 jsonInputs_.renderDataStore = parserUtil.GetRenderDataStore(jsonVal, "renderDataStore");
479 jsonInputs_.renderDataStoreSpecialization =
480 parserUtil.GetRenderDataStore(jsonVal, "renderDataStoreShaderSpecialization");
481 const auto ramp = parserUtil.GetStringValue(jsonVal, "ramp");
482 jsonInputs_.upRamp = ramp == "up";
483 jsonInputs_.ppName = parserUtil.GetStringValue(jsonVal, "postProcess");
484
485 #if (RENDER_VALIDATION_ENABLED == 1)
486 if (jsonInputs_.renderDataStore.dataStoreName.empty()) {
487 PLUGIN_LOG_W("RENDER_VALIDATION: RN %s renderDataStore::dataStoreName missing.",
488 renderNodeContextMgr_->GetName().data());
489 }
490 if (jsonInputs_.ppName.empty()) {
491 PLUGIN_LOG_W("RENDER_VALIDATION: RN %s postProcess name missing.", renderNodeContextMgr_->GetName().data());
492 }
493 #endif
494
495 const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
496 inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
497 inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
498 jsonInputs_.hasChangeableRenderPassHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.renderPass);
499 jsonInputs_.hasChangeableResourceHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.resources);
500 jsonInputs_.hasChangeableDispatchHandles = renderNodeUtil.HasChangeableResources(jsonInputs_.dispatchResources);
501
502 // process custom resources
503 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customInputImages.size()); ++idx) {
504 const auto& ref = jsonInputs_.resources.customInputImages[idx];
505 if (ref.usageName == INPUT) {
506 jsonInputs_.inputIdx = idx;
507 }
508 }
509 for (uint32_t idx = 0; idx < static_cast<uint32_t>(jsonInputs_.resources.customOutputImages.size()); ++idx) {
510 const auto& ref = jsonInputs_.resources.customOutputImages[idx];
511 if (ref.usageName == OUTPUT) {
512 jsonInputs_.outputIdx = idx;
513 }
514 }
515
516 // pick a sampler from the input resources which matches the layout location set=1, binding=0
517 if (!inputResources_.samplers.empty()) {
518 if (auto pos = std::find_if(inputResources_.samplers.cbegin(), inputResources_.samplers.cend(),
519 [](const RenderNodeResource& sampler) {
520 return (sampler.set == 1U) && (sampler.binding == 0U) &&
521 RenderHandleUtil::IsValid(sampler.handle) &&
522 RenderHandleUtil::GetHandleType(sampler.handle) == RenderHandleType::GPU_SAMPLER;
523 });
524 pos != inputResources_.samplers.cend()) {
525 samplerHandle_ = pos->handle;
526 }
527 }
528 }
529
UpdateImageData()530 void RenderNodeMipChainPostProcess::UpdateImageData()
531 {
532 const auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
533 if (!RenderHandleUtil::IsValid(builtInVariables_.defBuffer)) {
534 builtInVariables_.defBuffer = ubos_.postProcess.GetHandle();
535 }
536 if (!RenderHandleUtil::IsValid(builtInVariables_.defBlackImage)) {
537 builtInVariables_.defBlackImage =
538 gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE);
539 }
540 if (!RenderHandleUtil::IsValid(builtInVariables_.defWhiteImage)) {
541 builtInVariables_.defWhiteImage =
542 gpuResourceMgr.GetImageHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_GPU_IMAGE_WHITE);
543 }
544 if (!RenderHandleUtil::IsValid(samplerHandle_)) {
545 builtInVariables_.defSampler =
546 gpuResourceMgr.GetSamplerHandle(DefaultEngineGpuResourceConstants::CORE_DEFAULT_SAMPLER_LINEAR_CLAMP);
547 if (!RenderHandleUtil::IsValid(builtInVariables_.defSampler)) {
548 samplerHandle_ = builtInVariables_.defSampler;
549 }
550 }
551 if (jsonInputs_.inputIdx < inputResources_.customInputImages.size()) {
552 builtInVariables_.input = inputResources_.customInputImages[jsonInputs_.inputIdx].handle;
553 }
554 if (jsonInputs_.outputIdx < inputResources_.customOutputImages.size()) {
555 builtInVariables_.output = inputResources_.customOutputImages[jsonInputs_.outputIdx].handle;
556 }
557 }
558
559 // for plugin / factory interface
Create()560 IRenderNode* RenderNodeMipChainPostProcess::Create()
561 {
562 return new RenderNodeMipChainPostProcess();
563 }
564
Destroy(IRenderNode * instance)565 void RenderNodeMipChainPostProcess::Destroy(IRenderNode* instance)
566 {
567 delete static_cast<RenderNodeMipChainPostProcess*>(instance);
568 }
569 RENDER_END_NAMESPACE()
570