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 #ifndef RENDER_NODECONTEXT_NODE_CONTEXT_PSO_MANAGER_H 17 #define RENDER_NODECONTEXT_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 RenderHandle GetComputePsoHandle(const IShaderManager::ShaderData& shaderData, 66 const ShaderSpecializationConstantDataView& shaderSpecialization) override; 67 68 RenderHandle GetGraphicsPsoHandle(const RenderHandle shader, const RenderHandle graphicsState, 69 const RenderHandle pipelineLayout, const RenderHandle vertexInputDeclaration, 70 const ShaderSpecializationConstantDataView& shaderSpecialization, 71 const BASE_NS::array_view<const DynamicStateEnum> dynamicStates) override; 72 RenderHandle GetGraphicsPsoHandle(const RenderHandle shader, const RenderHandle graphicsState, 73 const PipelineLayout& pipelineLayout, const VertexInputDeclarationView& vertexInputDeclarationView, 74 const ShaderSpecializationConstantDataView& shaderSpecialization, 75 const BASE_NS::array_view<const DynamicStateEnum> dynamicStates) override; 76 RenderHandle GetGraphicsPsoHandle(const RenderHandle shader, const GraphicsState& graphicsState, 77 const PipelineLayout& pipelineLayout, const VertexInputDeclarationView& vertexInputDeclarationView, 78 const ShaderSpecializationConstantDataView& shaderSpecialization, 79 const BASE_NS::array_view<const DynamicStateEnum> dynamicStates) override; 80 RenderHandle GetGraphicsPsoHandle(const IShaderManager::GraphicsShaderData& shaderData, 81 const ShaderSpecializationConstantDataView& shaderSpecialization, 82 const BASE_NS::array_view<const DynamicStateEnum> dynamicStates) override; 83 84 const ComputePipelineStateObject* GetComputePso( 85 const RenderHandle handle, const LowLevelPipelineLayoutData* pipelineLayoutData); 86 // with GL(ES) psoStateHash is 0 and renderPassData, and pipelineLayoutData are nullptr 87 // with vulkan psoStateHash has renderpass compatibility hash and additional descriptor set hash 88 const GraphicsPipelineStateObject* GetGraphicsPso(const RenderHandle handle, const RenderPassDesc& renderPassDesc, 89 const BASE_NS::array_view<const RenderPassSubpassDesc> renderPassSubpassDescs, const uint32_t subpassIndex, 90 const uint64_t psoStateHash, const LowLevelRenderPassData* renderPassData, 91 const LowLevelPipelineLayoutData* pipelineLayoutData); 92 93 // only used for validation (just copy pipeline layout) 94 #if (RENDER_VALIDATION_ENABLED == 1) 95 const PipelineLayout& GetComputePsoPipelineLayout(const RenderHandle handle) const; 96 const PipelineLayout& GetGraphicsPsoPipelineLayout(const RenderHandle handle) const; 97 #endif 98 99 private: 100 Device& device_; 101 ShaderManager& shaderMgr_; 102 103 // graphics state handle should be invalid if custom graphics state is given 104 RenderHandle GetGraphicsPsoHandleImpl(const RenderHandle shaderHandle, const RenderHandle graphicsStateHandle, 105 const PipelineLayout& pipelineLayout, const VertexInputDeclarationView& vertexInputDeclarationView, 106 const ShaderSpecializationConstantDataView& shaderSpecialization, 107 const BASE_NS::array_view<const DynamicStateEnum> dynamicStates, const GraphicsState* graphicsState); 108 void ProcessReloadedShaders(); 109 110 struct ComputePipelineStateCreationData { 111 RenderHandle shaderHandle; 112 PipelineLayout pipelineLayout; 113 ShaderSpecializationConstantDataWrapper shaderSpecialization; 114 }; 115 struct ComputePipelineStateCache { 116 BASE_NS::vector<ComputePipelineStateCreationData> psoCreationData; 117 BASE_NS::vector<BASE_NS::unique_ptr<ComputePipelineStateObject>> pipelineStateObjects; 118 // hash (shader hash), resource handle 119 BASE_NS::unordered_map<uint64_t, RenderHandle> hashToHandle; 120 121 struct DestroyData { 122 BASE_NS::unique_ptr<ComputePipelineStateObject> pso; 123 uint64_t frameIndex { 0 }; 124 }; 125 BASE_NS::vector<DestroyData> pendingPsoDestroys; 126 127 #if (RENDER_VALIDATION_ENABLED == 1) 128 BASE_NS::unordered_map<RenderHandle, PipelineLayout> handleToPipelineLayout; 129 #endif 130 }; 131 ComputePipelineStateCache computePipelineStateCache_; 132 133 struct GraphicsPipelineStateCreationData { 134 RenderHandle shaderHandle; 135 RenderHandle graphicsStateHandle; 136 PipelineLayout pipelineLayout; 137 138 VertexInputDeclarationDataWrapper vertexInputDeclaration; 139 ShaderSpecializationConstantDataWrapper shaderSpecialization; 140 BASE_NS::unique_ptr<GraphicsState> customGraphicsState; 141 BASE_NS::vector<DynamicStateEnum> dynamicStates; 142 }; 143 struct GraphicsPipelineStateCache { 144 BASE_NS::vector<GraphicsPipelineStateCreationData> psoCreationData; 145 // (handle.id (+ vk renderpass compatibility hash) 146 // vulkan needs pso per every render pass configuration (for GL array would be enough, but we use 147 // renderhandle.id) 148 struct PsoData { 149 BASE_NS::unique_ptr<GraphicsPipelineStateObject> pso; 150 RenderHandle shaderHandle; 151 }; 152 BASE_NS::unordered_map<uint64_t, PsoData> pipelineStateObjects; 153 // hash (shader hash), resource handle 154 BASE_NS::unordered_map<uint64_t, RenderHandle> hashToHandle; 155 156 struct DestroyData { 157 BASE_NS::unique_ptr<GraphicsPipelineStateObject> pso; 158 uint64_t frameIndex { 0 }; 159 }; 160 BASE_NS::vector<DestroyData> pendingPsoDestroys; 161 162 #if (RENDER_VALIDATION_ENABLED == 1) 163 BASE_NS::unordered_map<RenderHandle, PipelineLayout> handleToPipelineLayout; 164 #endif 165 }; 166 GraphicsPipelineStateCache graphicsPipelineStateCache_; 167 168 // pso re-creation based on reloaded shaders 169 uint64_t lastReloadedShadersFrameIndex_ { 0 }; 170 }; 171 RENDER_END_NAMESPACE() 172 173 #endif // CORE__RENDER__NODE_CONTEXT_PSO_MANAGER_H 174