• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_.GetRenderDescriptorCounts();
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_.PreExecute();
180     }
181     RegisterOutputs(builtInVariables_.output);
182 }
183 
ExecuteFrame(IRenderCommandList & cmdList)184 void RenderNodeMipChainPostProcess::ExecuteFrame(IRenderCommandList& cmdList)
185 {
186     if ((!ppLocalConfig_.variables.enabled) &&
187         (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
188         return;
189     }
190 
191     const auto& renderNodeUtil = renderNodeContextMgr_->GetRenderNodeUtil();
192     if (jsonInputs_.hasChangeableRenderPassHandles) {
193         inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass);
194     }
195     if (jsonInputs_.hasChangeableResourceHandles) {
196         inputResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.resources);
197     }
198     if (jsonInputs_.hasChangeableDispatchHandles) {
199         dispatchResources_ = renderNodeUtil.CreateInputResources(jsonInputs_.dispatchResources);
200     }
201     if (useAutoBindSet0_) {
202         UpdateGlobalPostProcessUbo();
203     }
204 
205     if (pipelineData_.graphics) {
206         RenderGraphics(cmdList);
207     } else {
208         RenderCompute(cmdList);
209     }
210 }
211 
GetExecuteFlags() const212 IRenderNode::ExecuteFlags RenderNodeMipChainPostProcess::GetExecuteFlags() const
213 {
214     if ((!ppLocalConfig_.variables.enabled) &&
215         (jsonInputs_.defaultOutputImage != DefaultOutputImage::INPUT_OUTPUT_COPY)) {
216         return ExecuteFlagBits::EXECUTE_FLAG_BITS_DO_NOT_EXECUTE;
217     }
218     return ExecuteFlagBits::EXECUTE_FLAG_BITS_DEFAULT;
219 }
220 
ProcessPostProcessConfiguration()221 void RenderNodeMipChainPostProcess::ProcessPostProcessConfiguration()
222 {
223     if (!jsonInputs_.renderDataStore.dataStoreName.empty()) {
224         auto& dsMgr = renderNodeContextMgr_->GetRenderDataStoreManager();
225         if (const IRenderDataStore* ds = dsMgr.GetRenderDataStore(jsonInputs_.renderDataStore.dataStoreName)) {
226             if (jsonInputs_.renderDataStore.typeName == RenderDataStorePostProcess::TYPE_NAME) {
227                 auto* const dataStore = static_cast<const IRenderDataStorePostProcess*>(ds);
228                 ppLocalConfig_ = dataStore->Get(jsonInputs_.renderDataStore.configurationName, jsonInputs_.ppName);
229             }
230         }
231         if (const auto* ds =
232                 static_cast<const IRenderDataStorePod*>(dsMgr.GetRenderDataStore(RENDER_DATA_STORE_POD_NAME))) {
233             auto const dataView = ds->Get(jsonInputs_.renderDataStore.configurationName);
234             if (dataView.data() && (dataView.size_bytes() == sizeof(PostProcessConfiguration))) {
235                 ppGlobalConfig_ = *((const PostProcessConfiguration*)dataView.data());
236             }
237         }
238     } else if (jsonInputs_.ppName.empty()) {
239         // if trying to just use shader without post processing we enable running by default
240         ppLocalConfig_.variables.enabled = true;
241     }
242 }
243 
UpdateGlobalPostProcessUbo()244 void RenderNodeMipChainPostProcess::UpdateGlobalPostProcessUbo()
245 {
246     auto& gpuResourceMgr = renderNodeContextMgr_->GetGpuResourceManager();
247     const RenderPostProcessConfiguration rppc =
248         renderNodeContextMgr_->GetRenderNodeUtil().GetRenderPostProcessConfiguration(ppGlobalConfig_);
249     PLUGIN_STATIC_ASSERT(sizeof(GlobalPostProcessStruct) == sizeof(RenderPostProcessConfiguration));
250     PLUGIN_STATIC_ASSERT(sizeof(LocalPostProcessStruct) ==
251                          sizeof(IRenderDataStorePostProcess::PostProcess::Variables::customPropertyData));
252     if (auto data = reinterpret_cast<uint8_t*>(gpuResourceMgr.MapBuffer(ubos_.postProcess.GetHandle())); data) {
253         const auto* dataEnd = data + sizeof(GlobalPostProcessStruct) + sizeof(LocalPostProcessStruct);
254         // global data
255         CloneData(data, size_t(dataEnd - data), &rppc, sizeof(GlobalPostProcessStruct));
256         // local data
257         data += sizeof(GlobalPostProcessStruct);
258         CloneData(
259             data, size_t(dataEnd - data), ppLocalConfig_.variables.customPropertyData, sizeof(LocalPostProcessStruct));
260         gpuResourceMgr.UnmapBuffer(ubos_.postProcess.GetHandle());
261     }
262 }
263 
264 // constants for RenderNodeMipChainPostProcess::RenderData
265 namespace {
266 constexpr bool USE_CUSTOM_BARRIERS = true;
267 
268 constexpr ImageResourceBarrier SRC_UNDEFINED { 0, CORE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, CORE_IMAGE_LAYOUT_UNDEFINED };
269 constexpr ImageResourceBarrier COL_ATTACHMENT { CORE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
270     CORE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, CORE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
271 constexpr ImageResourceBarrier SHDR_READ { CORE_ACCESS_SHADER_READ_BIT, CORE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
272     CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
273 // transition the final mip level to read only as well
274 constexpr ImageResourceBarrier FINAL_SRC { CORE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
275     CORE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | CORE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
276     CORE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
277 constexpr ImageResourceBarrier FINAL_DST { CORE_ACCESS_SHADER_READ_BIT,
278     CORE_PIPELINE_STAGE_VERTEX_SHADER_BIT, // first possible shader read stage
279     CORE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL };
280 } // namespace
281 
GetRequiresPreCopy() const282 bool RenderNodeMipChainPostProcess::GetRequiresPreCopy() const
283 {
284     // check for first copy from another image
285     if (builtInVariables_.input != builtInVariables_.output) {
286         return true;
287     } else {
288         return false;
289     }
290 }
291 
GetBaseRenderPass()292 RenderPass RenderNodeMipChainPostProcess::GetBaseRenderPass()
293 {
294     RenderPass renderPass = renderNodeContextMgr_->GetRenderNodeUtil().CreateRenderPass(inputRenderPass_);
295     RenderHandle imageHandle = renderPass.renderPassDesc.attachmentHandles[0];
296     // find the target image if not provided with the render pass
297     if (!RenderHandleUtil::IsValid(imageHandle)) {
298         if ((!inputResources_.customOutputImages.empty()))
299             imageHandle = inputResources_.customOutputImages[0].handle;
300     }
301     renderPass.renderPassDesc.attachmentCount = 1;
302     renderPass.renderPassDesc.subpassCount = 1;
303     renderPass.renderPassDesc.attachments[0].loadOp = CORE_ATTACHMENT_LOAD_OP_DONT_CARE;
304     renderPass.renderPassDesc.attachments[0].storeOp = CORE_ATTACHMENT_STORE_OP_STORE;
305     renderPass.renderPassDesc.attachmentHandles[0] = imageHandle;
306     renderPass.subpassStartIndex = 0;
307     auto& subpass = renderPass.subpassDesc;
308     subpass.colorAttachmentCount = 1;
309     subpass.colorAttachmentIndices[0] = 0;
310     return renderPass;
311 }
312 
UpdateGlobalSet(IRenderCommandList & cmdList)313 void RenderNodeMipChainPostProcess::UpdateGlobalSet(IRenderCommandList& cmdList)
314 {
315     auto& binder = *globalSet0_;
316     binder.ClearBindings();
317     uint32_t binding = 0u;
318     binder.BindBuffer(binding++, BindableBuffer { ubos_.postProcess.GetHandle() });
319     binder.BindBuffer(binding++, BindableBuffer { ubos_.postProcess.GetHandle(), sizeof(GlobalPostProcessStruct) });
320     cmdList.UpdateDescriptorSet(binder.GetDescriptorSetHandle(), binder.GetDescriptorSetLayoutBindingResources());
321 }
322 
RenderGraphics(IRenderCommandList & cmdList)323 void RenderNodeMipChainPostProcess::RenderGraphics(IRenderCommandList& cmdList)
324 {
325     RenderPass renderPass = GetBaseRenderPass();
326 
327     const RenderHandle imageHandle = renderPass.renderPassDesc.attachmentHandles[0];
328     if (!RenderHandleUtil::IsValid(imageHandle)) {
329         return; // early out
330     }
331     const GpuImageDesc imageDesc = renderNodeContextMgr_->GetGpuResourceManager().GetImageDescriptor(imageHandle);
332     if (imageDesc.mipCount <= 1U) {
333         return; // early out
334     }
335     renderPass.renderPassDesc.renderArea = { 0, 0, imageDesc.width, imageDesc.height };
336     // check for first copy from another image
337     if (builtInVariables_.input != builtInVariables_.output) {
338         IRenderNodeCopyUtil::CopyInfo copyInfo { GetBindableImage(builtInVariables_.input),
339             GetBindableImage(builtInVariables_.output), {} };
340         renderCopy_.Execute(cmdList, copyInfo);
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 auto fWidth = static_cast<float>(width);
358         const auto 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