/* * Copyright (c) 2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "render_node_dotfield_render.h" #include <3d/implementation_uids.h> #include <3d/namespace.h> #include <3d/render/default_material_constants.h> #include <3d/render/intf_render_data_store_default_scene.h> #include <3d/render/intf_render_node_scene_util.h> #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "render_data_store_default_dotfield.h" namespace { #include "app/shaders/common/dotfield_common.h" #include "app/shaders/common/dotfield_struct_common.h" } // namespace #include using namespace BASE_NS; using namespace CORE_NS; using namespace RENDER_NS; using namespace CORE3D_NS; namespace Dotfield { namespace { constexpr DynamicStateEnum DYNAMIC_STATES[] = { CORE_DYNAMIC_STATE_ENUM_VIEWPORT, CORE_DYNAMIC_STATE_ENUM_SCISSOR }; constexpr string_view DEFAULT_DOTFIELD_RENDER_DATA_STORE_NAME_POST_FIX = "RenderDataStoreDefaultDotfield"; } // namespace void RenderNodeDotfieldRender::InitNode(IRenderNodeContextManager& renderNodeContextMgr) { renderNodeContextMgr_ = &renderNodeContextMgr; ParseRenderNodeInputs(); shaderToPsoData_.clear(); const auto& renderNodeUtil = renderNodeContextMgr.GetRenderNodeUtil(); inputRenderPass_ = renderNodeUtil.CreateInputRenderPass(jsonInputs_.renderPass); renderPass_ = renderNodeUtil.CreateRenderPass(inputRenderPass_); if (auto* renderNodeSceneUtil = CORE_NS::GetInstance( *(renderNodeContextMgr_->GetRenderContext().GetInterface()), CORE3D_NS::UID_RENDER_NODE_SCENE_UTIL); renderNodeSceneUtil) { const auto& renderNodeGraphData = renderNodeContextMgr_->GetRenderNodeGraphData(); stores_ = renderNodeSceneUtil->GetSceneRenderDataStores( renderNodeContextMgr, renderNodeGraphData.renderNodeGraphDataStoreName); } cameraUniformBufferHandle_ = renderNodeContextMgr.GetGpuResourceManager().GetBufferHandle( stores_.dataStoreNameScene + DefaultMaterialCameraConstants::CAMERA_DATA_BUFFER_NAME); INodeContextDescriptorSetManager& descriptorSetMgr = renderNodeContextMgr.GetDescriptorSetManager(); { const DescriptorCounts dc { { { CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u }, } }; descriptorSetMgr.ResetAndReserve(dc); } { const IRenderNodeShaderManager& shaderMgr = renderNodeContextMgr.GetShaderManager(); shaderHandle_ = shaderMgr.GetShaderHandle("dotfieldshaders://shader/default_material_dotfield.shader"); const RenderHandle plHandle = shaderMgr.GetPipelineLayoutHandle("dotfieldpipelinelayouts://default_material_dotfield.shaderpl"); const PipelineLayout pipelineLayout = shaderMgr.GetPipelineLayout(plHandle); CORE_ASSERT(pipelineLayout.pushConstant.byteSize == sizeof(DotfieldMaterialPushConstantStruct)); const uint32_t set = 0; const RenderHandle descriptorSetHandle = descriptorSetMgr.CreateDescriptorSet(set, pipelineLayout); binders_.set0 = descriptorSetMgr.CreateDescriptorSetBinder( descriptorSetHandle, pipelineLayout.descriptorSetLayouts[set].bindings); } } void RenderNodeDotfieldRender::ParseRenderNodeInputs() { const IRenderNodeParserUtil& parserUtil = renderNodeContextMgr_->GetRenderNodeParserUtil(); const auto jsonVal = renderNodeContextMgr_->GetNodeJson(); jsonInputs_.renderPass = parserUtil.GetInputRenderPass(jsonVal, "renderPass"); } void RenderNodeDotfieldRender::PreExecuteFrame(){} void RenderNodeDotfieldRender::ExecuteFrame(IRenderCommandList& cmdList) { cmdList.BeginRenderPass(renderPass_.renderPassDesc, renderPass_.subpassStartIndex, renderPass_.subpassDesc); RenderData(*renderNodeContextMgr_, cmdList); cmdList.EndRenderPass(); } void RenderNodeDotfieldRender::RenderData(IRenderNodeContextManager& renderNodeContextMgr, IRenderCommandList& cmdList) { const RenderDataStoreDefaultDotfield* dataStore = static_cast( renderNodeContextMgr.GetRenderDataStoreManager().GetRenderDataStore( stores_.dataStoreNamePrefix + DEFAULT_DOTFIELD_RENDER_DATA_STORE_NAME_POST_FIX.data())); if (!dataStore) { return; } const auto& dotfieldPrimitives = dataStore->GetDotfieldPrimitives(); if (dotfieldPrimitives.empty()) { return; } const auto& bufferData = dataStore->GetBufferData(); const ViewportDesc viewportDesc = renderNodeContextMgr.GetRenderNodeUtil().CreateDefaultViewport(renderPass_); cmdList.SetDynamicStateViewport(viewportDesc); const ScissorDesc scissorDesc = renderNodeContextMgr.GetRenderNodeUtil().CreateDefaultScissor(renderPass_); cmdList.SetDynamicStateScissor(scissorDesc); auto& binder0 = *binders_.set0; binder0.BindBuffer(0, cameraUniformBufferHandle_, 0); cmdList.UpdateDescriptorSet(binder0.GetDescriptorSetHandle(), binder0.GetDescriptorSetLayoutBindingResources()); const uint32_t primitiveCount = static_cast(dotfieldPrimitives.size()); const uint32_t currFrameIndex = bufferData.currFrameIndex; for (uint32_t idx = 0; idx < primitiveCount; ++idx) { const auto& dotfieldPrimitive = dotfieldPrimitives[idx]; const auto& currEffect = bufferData.buffers[idx]; const PsoData psoData = GetPsoData(renderNodeContextMgr, shaderHandle_); cmdList.BindPipeline(psoData.psoHandle); if (idx == 0) { cmdList.BindDescriptorSet(0, binder0.GetDescriptorSetHandle()); } float time = dataStore->GetTime(); const DotfieldMaterialPushConstantStruct pc = { { dotfieldPrimitive.size.x, dotfieldPrimitive.size.y, idx, 0 }, { time, dotfieldPrimitive.pointScale, 0, 0 }, dotfieldPrimitive.colors, dotfieldPrimitive.matrix }; cmdList.PushConstant(psoData.pushConstant, reinterpret_cast(&pc)); const VertexBuffer vb[] = { { currEffect.dataBuffer[currFrameIndex].GetHandle(), 0 }, }; cmdList.BindVertexBuffers(array_view(vb)); cmdList.Draw(1, dotfieldPrimitive.size.x * dotfieldPrimitive.size.y, 0, 0); } } RenderNodeDotfieldRender::PsoData RenderNodeDotfieldRender::GetPsoData( IRenderNodeContextManager& renderNodeContextMgr, const RenderHandle& shaderHandle) { if (const auto iter = shaderToPsoData_.find(shaderHandle.id); iter != shaderToPsoData_.cend()) { return iter->second; } else { // new const auto& shaderMgr = renderNodeContextMgr.GetShaderManager(); const RenderHandle plHandle = shaderMgr.GetPipelineLayoutHandleByShaderHandle(shaderHandle); const PipelineLayout pipelineLayout = shaderMgr.GetPipelineLayout(plHandle); const RenderHandle vidHandle = shaderMgr.GetVertexInputDeclarationHandleByShaderHandle(shaderHandle); const VertexInputDeclarationView vertexInputDeclaration = shaderMgr.GetVertexInputDeclarationView(vidHandle); const PipelineLayout& reflPipelineLayout = shaderMgr.GetReflectionPipelineLayout(shaderHandle); const RenderHandle graphicsStateHandle = shaderMgr.GetGraphicsStateHandleByShaderHandle(shaderHandle); const RenderHandle psoHandle = renderNodeContextMgr.GetPsoManager().GetGraphicsPsoHandle(shaderHandle, graphicsStateHandle, pipelineLayout, vertexInputDeclaration, {}, { DYNAMIC_STATES, countof(DYNAMIC_STATES) }); const PsoData psoData = { psoHandle, reflPipelineLayout.pushConstant }; shaderToPsoData_[shaderHandle.id] = psoData; return psoData; } } IRenderNode* RenderNodeDotfieldRender::Create() { return new RenderNodeDotfieldRender(); } void RenderNodeDotfieldRender::Destroy(IRenderNode* instance) { delete (RenderNodeDotfieldRender*)instance; } } // namespace Dotfield