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 #ifndef RENDER_RENDER__NODE_CONTEXT_PSO_MANAGER_H 17 #define RENDER_RENDER__NODE_CONTEXT_PSO_MANAGER_H 18 19 #include <cstddef> 20 #include <cstdint> 21 22 #include <base/containers/unique_ptr.h> 23 #include <base/containers/unordered_map.h> 24 #include <base/containers/vector.h> 25 #include <render/namespace.h> 26 #include <render/nodecontext/intf_node_context_pso_manager.h> 27 #include <render/render_data_structures.h> 28 #include <render/resource_handle.h> 29 30 #include "device/gpu_resource_handle_util.h" 31 #include "device/pipeline_state_object.h" 32 33 RENDER_BEGIN_NAMESPACE() 34 class Device; 35 class ShaderManager; 36 struct PipelineLayout; 37 struct ViewportDesc; 38 struct ScissorDesc; 39 struct LowLevelRenderPassData; 40 struct LowLevelPipelineLayoutData; 41 42 struct ShaderSpecializationConstantDataWrapper { 43 BASE_NS::vector<ShaderSpecialization::Constant> constants; 44 BASE_NS::vector<uint32_t> data; 45 }; 46 struct VertexInputDeclarationDataWrapper { 47 BASE_NS::vector<VertexInputDeclaration::VertexInputBindingDescription> bindingDescriptions; 48 BASE_NS::vector<VertexInputDeclaration::VertexInputAttributeDescription> attributeDescriptions; 49 }; 50 51 /** 52 NodeContextPsoManager implementation. 53 */ 54 class NodeContextPsoManager final : public INodeContextPsoManager { 55 public: 56 NodeContextPsoManager(Device& device, ShaderManager& shaderManager); 57 ~NodeContextPsoManager() = default; 58 59 void BeginBackendFrame(); 60 61 RenderHandle GetComputePsoHandle(const RenderHandle shader, const RenderHandle pipelineLayout, 62 const ShaderSpecializationConstantDataView& shaderSpecialization) override; 63 RenderHandle GetComputePsoHandle(const RenderHandle shader, const PipelineLayout& pipelineLayout, 64 const ShaderSpecializationConstantDataView& shaderSpecialization) override; 65 66 RenderHandle GetGraphicsPsoHandle(const RenderHandle shader, const RenderHandle graphicsState, 67 const RenderHandle pipelineLayout, const RenderHandle vertexInputDeclaration, 68 const ShaderSpecializationConstantDataView& shaderSpecialization, 69 const BASE_NS::array_view<const DynamicStateEnum> dynamicStates) override; 70 RenderHandle GetGraphicsPsoHandle(const RenderHandle shader, const RenderHandle graphicsState, 71 const PipelineLayout& pipelineLayout, const VertexInputDeclarationView& vertexInputDeclarationView, 72 const ShaderSpecializationConstantDataView& shaderSpecialization, 73 const BASE_NS::array_view<const DynamicStateEnum> dynamicStates) override; 74 RenderHandle GetGraphicsPsoHandle(const RenderHandle shader, const GraphicsState& graphicsState, 75 const PipelineLayout& pipelineLayout, const VertexInputDeclarationView& vertexInputDeclarationView, 76 const ShaderSpecializationConstantDataView& shaderSpecialization, 77 const BASE_NS::array_view<const DynamicStateEnum> dynamicStates) override; 78 79 const ComputePipelineStateObject* GetComputePso( 80 const RenderHandle handle, const LowLevelPipelineLayoutData* pipelineLayoutData); 81 // with GL(ES) psoStateHash is 0 and renderPassData, and pipelineLayoutData are nullptr 82 // with vulkan psoStateHash has renderpass compatibility hash and additional descriptor set hash 83 const GraphicsPipelineStateObject* GetGraphicsPso(const RenderHandle handle, const RenderPassDesc& renderPassDesc, 84 const BASE_NS::array_view<const RenderPassSubpassDesc> renderPassSubpassDescs, const uint32_t subpassIndex, 85 const uint64_t psoStateHash, const LowLevelRenderPassData* renderPassData, 86 const LowLevelPipelineLayoutData* pipelineLayoutData); 87 88 // only used for validation (just copy pipeline layout) 89 #if (RENDER_VALIDATION_ENABLED == 1) 90 const PipelineLayout& GetComputePsoPipelineLayout(const RenderHandle handle) const; 91 const PipelineLayout& GetGraphicsPsoPipelineLayout(const RenderHandle handle) const; 92 #endif 93 94 private: 95 Device& device_; 96 ShaderManager& shaderMgr_; 97 98 // graphics state handle should be invalid if custom graphics state is given 99 RenderHandle GetGraphicsPsoHandleImpl(const RenderHandle shaderHandle, const RenderHandle graphicsStateHandle, 100 const PipelineLayout& pipelineLayout, const VertexInputDeclarationView& vertexInputDeclarationView, 101 const ShaderSpecializationConstantDataView& shaderSpecialization, 102 const BASE_NS::array_view<const DynamicStateEnum> dynamicStates, const GraphicsState* graphicsState); 103 104 struct ComputePipelineStateCreationData { 105 RenderHandle shaderHandle; 106 PipelineLayout pipelineLayout; 107 ShaderSpecializationConstantDataWrapper shaderSpecialization; 108 }; 109 struct ComputePipelineStateCache { 110 BASE_NS::vector<ComputePipelineStateCreationData> psoCreationData; 111 BASE_NS::vector<BASE_NS::unique_ptr<ComputePipelineStateObject>> pipelineStateObjects; 112 // hash (shader hash), resource handle 113 BASE_NS::unordered_map<uint64_t, RenderHandle> hashToHandle; 114 115 struct DestroyData { 116 BASE_NS::unique_ptr<ComputePipelineStateObject> pso; 117 uint64_t frameIndex { 0 }; 118 }; 119 BASE_NS::vector<DestroyData> pendingPsoDestroys; 120 121 #if (RENDER_VALIDATION_ENABLED == 1) 122 BASE_NS::unordered_map<RenderHandle, PipelineLayout> handleToPipelineLayout; 123 #endif 124 }; 125 ComputePipelineStateCache computePipelineStateCache_; 126 127 struct GraphicsPipelineStateCreationData { 128 RenderHandle shaderHandle; 129 RenderHandle graphicsStateHandle; 130 PipelineLayout pipelineLayout; 131 132 VertexInputDeclarationDataWrapper vertexInputDeclaration; 133 ShaderSpecializationConstantDataWrapper shaderSpecialization; 134 BASE_NS::unique_ptr<GraphicsState> customGraphicsState; 135 BASE_NS::vector<DynamicStateEnum> dynamicStates; 136 }; 137 struct GraphicsPipelineStateCache { 138 BASE_NS::vector<GraphicsPipelineStateCreationData> psoCreationData; 139 // (handle.id (+ vk renderpass compatibility hash) 140 // vulkan needs pso per every render pass configuration (for GL array would be enough, but we use 141 // renderhandle.id) 142 struct PsoData { 143 BASE_NS::unique_ptr<GraphicsPipelineStateObject> pso; 144 RenderHandle shaderHandle; 145 }; 146 BASE_NS::unordered_map<uint64_t, PsoData> pipelineStateObjects; 147 // hash (shader hash), resource handle 148 BASE_NS::unordered_map<uint64_t, RenderHandle> hashToHandle; 149 150 struct DestroyData { 151 BASE_NS::unique_ptr<GraphicsPipelineStateObject> pso; 152 uint64_t frameIndex { 0 }; 153 }; 154 BASE_NS::vector<DestroyData> pendingPsoDestroys; 155 156 #if (RENDER_VALIDATION_ENABLED == 1) 157 BASE_NS::unordered_map<RenderHandle, PipelineLayout> handleToPipelineLayout; 158 #endif 159 }; 160 GraphicsPipelineStateCache graphicsPipelineStateCache_; 161 }; 162 RENDER_END_NAMESPACE() 163 164 #endif // CORE__RENDER__NODE_CONTEXT_PSO_MANAGER_H 165