Overte C++ Documentation
vk/src/vk/Context.h
1 //
2 // Created by Bradley Austin Davis on 2018/10/29
3 // Adapted for Vulkan in 2021-2025 by dr Karol Suprynowicz.
4 // Copyright 2018 High Fidelity, Inc.
5 // Copyright 2023-2025 Overte e.V.
6 //
7 // Distributed under the Apache License, Version 2.0.
8 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
9 // SPDX-License-Identifier: Apache-2.0
10 //
11 
12 // Contains code from Vulkan Samples by Sascha Willems (int nthe namespace `vks`):
13 // Copyright (C) 2016-2018 by Sascha Willems - www.saschawillems.de
14 //
15 // This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
16 //
17 
18 #pragma once
19 
20 #include "Config.h"
21 
22 #include <unordered_set>
23 #include <mutex>
24 #include <memory>
25 
26 #include "Debug.h"
27 #include "Helpers.h"
28 #include "VulkanDevice.h"
29 #include "VulkanDebug.h"
30 #include "VulkanTools.h"
31 
32 namespace gpu::vk {
33  class VKFramebuffer;
34  class VKBuffer;
35  class VKTexture;
36  class VKQuery;
37  class VKBackend;
38 
39  // Extension for sharing memory with OpenGL, needed by QML UI and Web entities.
40  extern PFN_vkGetMemoryFdKHR vkGetMemoryFdKHR;
41 }
42 
43 class VKWindow;
44 class VKWidget;
45 
46 namespace vks {
47 
48 // Start of VKS code
49 
50 using StringList = std::list<std::string>;
51 using CStringVector = std::vector<const char*>;
52 
53 struct Context {
54  friend class ::VKWindow;
55  friend class ::VKWidget;
56 private:
57  static CStringVector filterLayers(const StringList& desiredLayers);
58 
59  Context() {};
60 public:
61  static Context& get();
62 
63  // Create application wide Vulkan instance
64  static std::set<std::string> getAvailableLayers();
65 
66  static std::vector<VkExtensionProperties> getExtensions();
67 
68  static std::set<std::string> getExtensionNames();
69 
70  static bool isExtensionPresent(const std::string& extensionName) { return getExtensionNames().count(extensionName) != 0; }
71 
72  static std::vector<VkExtensionProperties> getDeviceExtensions(const VkPhysicalDevice& physicalDevice);
73 
74  static std::set<std::string> getDeviceExtensionNames(const VkPhysicalDevice& physicalDevice);
75 
76  void requireExtensions(const std::set<std::string>& requestedExtensions) {
77  requiredExtensions.insert(requestedExtensions.begin(), requestedExtensions.end());
78  }
79 
80  void requireDeviceExtensions(const std::set<std::string>& requestedExtensions) {
81  requiredDeviceExtensions.insert(requestedExtensions.begin(), requestedExtensions.end());
82  }
83 
84  void setValidationEnabled(bool enable);
85 
86  void createInstance();
87 
88  void destroyContext();
89 
90  void createDevice();
91 
92 protected:
93  void pickDevice();
94 
95  void buildDevice();
96 
97 public:
98  // Vulkan instance, stores all per-application states
99  VkInstance instance;
100 
101  std::vector<VkPhysicalDevice> physicalDevices;
102  // Physical device (GPU) that Vulkan will use
103  VkPhysicalDevice physicalDevice;
104  // TODO: this needs to be filled in
105  VkPhysicalDeviceFeatures enabledFeatures{};
106 
107  std::shared_ptr<vks::VulkanDevice> device;
108 
109  VkQueue graphicsQueue;
110  VkQueue transferQueue;
111 
112  VkCommandBuffer createCommandBuffer(VkCommandPool commandPool, VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY) const;
113 
114 private:
115  // Set to true when example is created with enabled validation layers
116  bool enableValidation = false;
117  // Set to true when the debug marker extension is detected
118  bool enableDebugMarkers = false;
119 
120  std::set<std::string> requiredExtensions;
121  std::set<std::string> requiredDeviceExtensions;
122 
123  // End of VKS code
124 
125  VkFormat initBestDepthStencilFormat() const;
126 
127 public:
128 
129  // Not all GPUs support D24 S8 format, so we need to check what formats are supported.
130  VkFormat getBestDepthStencilFormat() const { return _bestDepthStencilFormat; };
131 
132  void registerWindow(VKWindow *window); // Every Vulkan window registers itself here.
133 
134  void unregisterWindow(VKWindow *window); // When window closes before backend was shut down, it removes itself from the list.
135 
136  void shutdownWindows(); // When backend shuts down, it cleans up after all windows and removes them from the list.
137 
138  // Contains objects that need to be deleted on Vulkan backend thread after frame is rendered.
139  // It's filled by destructors of objects like gpu::Texture and gpu::Buffer, since these destroy
140  // backend counterpart of their objects.
141  class Recycler {
142  public:
143  // This means that for every GPU object mutex will be locked and unlocked several times.
144  // VKTODO: It would be good to do profiling and check if it impacts performance or not.
145  void trashVkFence(VkFence& fence);
146  void trashVkSampler(VkSampler &sampler);
147  void trashVkFramebuffer(VkFramebuffer &framebuffer);
148  void trashVkImageView(VkImageView &imageView);
149  void trashVkImage(VkImage &image);
150  void trashVkBuffer(VkBuffer &buffer);
151  void trashVkRenderPass(VkRenderPass &renderPass);
152  void trashVkDescriptorSetLayout(VkDescriptorSetLayout& descriptorSetLayout);
153  void trashVkPipelineLayout(VkPipelineLayout& pipelineLayout);
154  void trashVkPipeline(VkPipeline &pipeline);
155  void trashVkShaderModule(VkShaderModule &module);
156  void trashVkSwapchainKHR(VkSwapchainKHR &swapchain);
157  void trashVKSurfaceKHR(VkSurfaceKHR &surface);
158  void trashVkSemaphore(VkSemaphore &semaphore);
159  void trashVkDeviceMemory(VkDeviceMemory &memory);
160  void trashVmaAllocation(VmaAllocation &allocation);
161 
162  void framebufferDeleted(gpu::vk::VKFramebuffer *framebuffer);
163  void bufferDeleted(gpu::vk::VKBuffer *buffer);
164  void textureDeleted(gpu::vk::VKTexture *texture);
165  void queryDeleted(gpu::vk::VKQuery *query);
166 
167  private:
168  std::recursive_mutex recyclerMutex;
169 
170  std::vector<VkFence> vkFences;
171  std::vector<VkFramebuffer> vkFramebuffers;
172  std::vector<VkSampler> vkSamplers;
173  std::vector<VkImageView> vkImageViews;
174  std::vector<VkImage> vkImages;
175  std::vector<VkBuffer> vkBuffers;
176  std::vector<VkRenderPass> vkRenderPasses;
177  std::vector<VkDescriptorSetLayout> vkDescriptorSetLayouts;
178  std::vector<VkPipelineLayout > vkPipelineLayouts;
179  std::vector<VkPipeline> vkPipelines;
180  std::vector<VkShaderModule> vkShaderModules;
181  std::vector<VkSwapchainKHR> vkSwapchainsKHR;
182  std::vector<VkSurfaceKHR> vkSurfacesKHR;
183  std::vector<VkSemaphore> vkSemaphores;
184  std::vector<VkDeviceMemory> vkDeviceMemories;
185  std::vector<VmaAllocation> vmaAllocations;
186 
187  // List of pointers to objects that were deleted and need to be removed from backend object sets.
188  std::vector<gpu::vk::VKFramebuffer*> deletedFramebuffers;
189  std::vector<gpu::vk::VKBuffer*> deletedBuffers;
190  std::vector<gpu::vk::VKTexture*> deletedTextures;
191  std::vector<gpu::vk::VKQuery*> deletedQueries;
192  friend class gpu::vk::VKBackend;
193  } recycler;
194 
195 private:
196  std::recursive_mutex vulkanWindowsMutex;
197  std::list<VKWindow*> vulkanWindows;
198  VkFormat _bestDepthStencilFormat{ VK_FORMAT_UNDEFINED };
199 };
200 
201 } // namespace vks
202 
customized canvas that simply forwards requests/events to the singleton application
Definition: VKWidget.h:31