Overte C++ Documentation
VKPipelineCache.h
1 // Created by dr Karol Suprynowicz on 2024/12/27.
2 // Based on work by by Bradley Austin Davis
3 // Copyright 2018 High Fidelity, Inc.
4 // Copyright 2023-2025 Overte e.V.
5 //
6 // Distributed under the Apache License, Version 2.0.
7 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
8 // SPDX-License-Identifier: Apache-2.0
9 //
10 
11 #pragma once
12 
13 // For hash_combine
14 #include <RegisteredMetaTypes.h>
15 
16 #include <gpu/Forward.h>
17 #include <gpu/Context.h>
18 
19 #include <vk/Config.h>
20 #include <vk/Context.h>
21 #include <vk/VulkanDebug.h>
22 #include <vulkan/vulkan_core.h>
23 
24 #include "VKForward.h"
25 
26 //define OVERTE_VK_PIPELINE_DEBUG
27 
28 namespace std {
29 template <>
30 struct hash<gpu::Element> {
31  size_t operator()(const gpu::Element& a) const { return std::hash<uint32_t>()(a.getRaw()); }
32 };
33 
34 template <>
35 struct hash<::VkImageLayout> {
36  size_t operator()(const VkImageLayout& a) const { return std::hash<uint32_t>()((uint32_t)a); }
37 };
38 
39 
40 
41 } // namespace std
42 namespace gpu { namespace vk {
43 
44 inline size_t hashRenderPassPair(const std::pair<VkFormat,VkImageLayout>& a) {
45  size_t seed = 0;
46  std::hash_combine(seed, a.first);
47  std::hash_combine(seed, a.second);
48  return seed;
49 }
50 
51 template <typename Container>
52 struct RenderPassHash {
53  std::size_t operator()(const Container& c) const {
54  size_t seed = 0;
55  for (const auto& e : c) {
56  std::hash_combine(seed, hashRenderPassPair(e));
57  }
58  return seed;
59  }
60 };
61 
62 struct Cache {
63  struct PipelineLayout {
64  VkPipeline pipeline;
65  VkPipelineLayout pipelineLayout;
66  VkDescriptorSetLayout uniformLayout;
67  VkDescriptorSetLayout textureLayout;
68  VkDescriptorSetLayout storageLayout;
69 #ifdef OVERTE_VK_PIPELINE_DEBUG
70  std::string vertexShader;
71  std::string fragmentShader;
72 #endif
73  };
74  std::unordered_map<uint32_t, VkShaderModule> moduleMap;
75  std::unordered_map<std::string, PipelineLayout> pipelineMap;
76 
77  struct Pipeline {
78  using RenderpassKey = std::vector<std::pair<VkFormat, VkImageLayout>>;
79  using BindingMap = std::unordered_map<uint32_t, VkShaderStageFlags>;
80  using LocationMap = shader::Reflection::LocationMap;
81 
82  gpu::PipelineReference pipeline{ GPU_REFERENCE_INIT_VALUE };
83  std::shared_ptr<Shader> program;
84  shader::Reflection vertexReflection;
85  shader::Reflection fragmentReflection;
86  gpu::FormatReference format{ GPU_REFERENCE_INIT_VALUE };
87  gpu::FramebufferReference framebuffer{ GPU_REFERENCE_INIT_VALUE };
88  gpu::Primitive primitiveTopology;
89 
90 
91  // VKTODO: maybe these should be moved from here to cache object?
92  std::unordered_map<RenderpassKey, VkRenderPass, RenderPassHash<std::vector<std::pair<VkFormat, VkImageLayout>>>> _renderPassMap; // VKTODO: make sure render passes are retrieved from here
93 
94  // These get set when stride gets set by setInputBuffer
95  std::array<Offset, MAX_NUM_INPUT_BUFFERS> _bufferStrides{ 0 };
96  std::bitset<MAX_NUM_INPUT_BUFFERS> _bufferStrideSet;
97 
98  void clearStrides() { _bufferStrideSet.reset(); }
99 
100  void setPipeline(const gpu::PipelinePointer& pipeline);
101 
102  void setVertexFormat(const gpu::Stream::FormatPointer& format);
103 
104  void setFramebuffer(const gpu::FramebufferPointer& framebuffer);
105 
106  static void updateBindingMap(BindingMap& bindingMap,
107  const LocationMap& locationMap,
108  VkShaderStageFlagBits shaderStage);
109 
110  static void setBindingMap(BindingMap& bindingMap, const LocationMap& vertexMap, const LocationMap& fragmentMap);
111 
112  static BindingMap getBindingMap(const LocationMap& vertexMap, const LocationMap& fragmentMap);
113 
114  // VKTODO: This needs to be used instead of getPipeline
115  // Returns structure containing pipeline layout and descriptor set layouts
116  PipelineLayout getPipelineAndDescriptorLayout(const vks::Context& context);
117 
118  RenderpassKey getRenderPassKey(gpu::Framebuffer* framebuffer, const vks::Context &context) const;
119 
120  VkRenderPass getRenderPass(const vks::Context& context);
121  static std::string getRenderpassKeyString(const RenderpassKey& renderpassKey);
122  std::string getStridesKey() const;
123  std::string getKey(const vks::Context& context) const;
124  } pipelineState;
125 
126  static VkStencilOpState getStencilOp(const gpu::State::StencilTest& stencil);
127 
128  VkShaderModule getShaderModule(const vks::Context& context, const shader::Source& source);
129 
130  PipelineLayout getPipeline(const vks::Context& context);
131 };
132 
133 } }