layer: improve how layer handles Vulkan extensions
[platform/core/uifw/vulkan-wsi-tizen.git] / layer / private_data.hpp
1 /*
2  * Copyright (c) 2018-2021 Arm Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 #pragma once
26
27 #include "util/platform_set.hpp"
28
29 #include <vulkan/vulkan.h>
30 #include <vulkan/vk_layer.h>
31 #include <vulkan/vk_icd.h>
32
33 #include <memory>
34 #include <unordered_set>
35 #include <cassert>
36 #include <mutex>
37
38 using scoped_mutex = std::lock_guard<std::mutex>;
39
40 namespace layer
41 {
42
43 /* List of device entrypoints in the layer's instance dispatch table.
44  * Note that the Vulkan loader implements some of these entrypoints so the fact that these are non-null doesn't
45  * guarantee than we can safely call them. We still mark the entrypoints with REQUIRED() and OPTIONAL(). The layer
46  * fails if vkGetInstanceProcAddr returns null for entrypoints that are REQUIRED().
47  */
48 #define INSTANCE_ENTRYPOINTS_LIST(REQUIRED, OPTIONAL) \
49    REQUIRED(GetInstanceProcAddr)                      \
50    REQUIRED(DestroyInstance)                          \
51    REQUIRED(GetPhysicalDeviceProperties)              \
52    REQUIRED(GetPhysicalDeviceImageFormatProperties)   \
53    REQUIRED(EnumerateDeviceExtensionProperties)       \
54    OPTIONAL(GetPhysicalDeviceSurfaceCapabilitiesKHR)  \
55    OPTIONAL(GetPhysicalDeviceSurfaceFormatsKHR)       \
56    OPTIONAL(GetPhysicalDeviceSurfacePresentModesKHR)  \
57    OPTIONAL(GetPhysicalDeviceSurfaceSupportKHR)
58
59 struct instance_dispatch_table
60 {
61    VkResult populate(VkInstance instance, PFN_vkGetInstanceProcAddr get_proc);
62
63 #define DISPATCH_TABLE_ENTRY(x) PFN_vk##x x{};
64    INSTANCE_ENTRYPOINTS_LIST(DISPATCH_TABLE_ENTRY, DISPATCH_TABLE_ENTRY)
65 #undef DISPATCH_TABLE_ENTRY
66 };
67
68 /* List of device entrypoints in the layer's device dispatch table.
69  * The layer fails initializing a device instance when entrypoints marked with REQUIRED() are retrieved as null.
70  * The layer will instead tolerate retrieving a null for entrypoints marked as OPTIONAL(). Code in the layer needs to
71  * check these entrypoints are non-null before calling them.
72  *
73  * Note that we cannot rely on checking whether the physical device supports a particular extension as the Vulkan
74  * loader currently aggregates all extensions advertised by all implicit layers (in their JSON manifests) and adds
75  * them automatically to the output of vkEnumeratePhysicalDeviceProperties.
76  */
77 #define DEVICE_ENTRYPOINTS_LIST(REQUIRED, OPTIONAL) \
78    REQUIRED(GetDeviceProcAddr)                      \
79    REQUIRED(GetDeviceQueue)                         \
80    REQUIRED(QueueSubmit)                            \
81    REQUIRED(QueueWaitIdle)                          \
82    REQUIRED(CreateCommandPool)                      \
83    REQUIRED(DestroyCommandPool)                     \
84    REQUIRED(AllocateCommandBuffers)                 \
85    REQUIRED(FreeCommandBuffers)                     \
86    REQUIRED(ResetCommandBuffer)                     \
87    REQUIRED(BeginCommandBuffer)                     \
88    REQUIRED(EndCommandBuffer)                       \
89    REQUIRED(CreateImage)                            \
90    REQUIRED(DestroyImage)                           \
91    REQUIRED(GetImageMemoryRequirements)             \
92    REQUIRED(BindImageMemory)                        \
93    REQUIRED(AllocateMemory)                         \
94    REQUIRED(FreeMemory)                             \
95    REQUIRED(CreateFence)                            \
96    REQUIRED(DestroyFence)                           \
97    REQUIRED(ResetFences)                            \
98    REQUIRED(WaitForFences)                          \
99    OPTIONAL(CreateSwapchainKHR)                     \
100    OPTIONAL(DestroySwapchainKHR)                    \
101    OPTIONAL(GetSwapchainImagesKHR)                  \
102    OPTIONAL(AcquireNextImageKHR)                    \
103    OPTIONAL(QueuePresentKHR)
104
105 struct device_dispatch_table
106 {
107    VkResult populate(VkDevice dev, PFN_vkGetDeviceProcAddr get_proc);
108
109 #define DISPATCH_TABLE_ENTRY(x) PFN_vk##x x{};
110    DEVICE_ENTRYPOINTS_LIST(DISPATCH_TABLE_ENTRY, DISPATCH_TABLE_ENTRY)
111 #undef DISPATCH_TABLE_ENTRY
112 };
113
114 /**
115  * @brief Layer "mirror object" for VkInstance.
116  */
117 class instance_private_data
118 {
119 public:
120    instance_private_data() = delete;
121    instance_private_data(const instance_private_data &) = delete;
122    instance_private_data &operator=(const instance_private_data &) = delete;
123
124    instance_private_data(const instance_dispatch_table& table,
125                          PFN_vkSetInstanceLoaderData set_loader_data,
126                          util::wsi_platform_set enabled_layer_platforms);
127    static void set(VkInstance inst, std::unique_ptr<instance_private_data> inst_data);
128
129    /**
130     * @brief Get the mirror object that the layer associates to a given Vulkan instance.
131     */
132    static instance_private_data &get(VkInstance instance);
133
134    /**
135     * @brief Get the layer instance object associated to the VkInstance owning the specified VkPhysicalDevice.
136     */
137    static instance_private_data &get(VkPhysicalDevice phys_dev);
138
139    /**
140     * @brief Get the set of enabled platforms that are also supported by the layer.
141     */
142    const util::wsi_platform_set &get_enabled_platforms()
143    {
144       return enabled_layer_platforms;
145    }
146
147    /**
148     * @brief Check whether a surface command should be handled by the WSI layer.
149     *
150     * @param phys_dev Physical device involved in the Vulkan command.
151     * @param surface The surface involved in the Vulkan command.
152     *
153     * @retval @c true if the layer should handle commands for the specified surface, which may mean returning an error
154     * if the layer does not support @p surface 's platform.
155     *
156     * @retval @c false if the layer should call down to the layers and ICDs below to handle the surface commands.
157     */
158    bool should_layer_handle_surface(VkPhysicalDevice phys_dev, VkSurfaceKHR surface);
159
160    /**
161     * @brief Check whether the given surface is supported for presentation via the layer.
162     *
163     * @param surface A VK_KHR_surface surface.
164     *
165     * @return Whether the WSI layer supports this surface.
166     */
167    bool does_layer_support_surface(VkSurfaceKHR surface);
168
169    static void destroy(VkInstance inst);
170
171    const instance_dispatch_table disp;
172
173 private:
174    /**
175     * @brief Check whether the given surface is already supported for presentation without the layer.
176     */
177    bool do_icds_support_surface(VkPhysicalDevice phys_dev, VkSurfaceKHR surface);
178
179    const PFN_vkSetInstanceLoaderData SetInstanceLoaderData;
180    const util::wsi_platform_set enabled_layer_platforms;
181 };
182
183 class device_private_data
184 {
185 public:
186    device_private_data() = delete;
187    device_private_data(const device_private_data &) = delete;
188    device_private_data &operator=(const device_private_data &) = delete;
189
190    device_private_data(instance_private_data &inst_data, VkPhysicalDevice phys_dev, VkDevice dev,
191                        const device_dispatch_table &table, PFN_vkSetDeviceLoaderData set_loader_data);
192    static void set(VkDevice dev, std::unique_ptr<device_private_data> dev_data);
193
194    /**
195     * @brief Get the mirror object that the layer associates to a given Vulkan device.
196     */
197    static device_private_data &get(VkDevice device);
198
199    /**
200     * @brief Get the layer device object associated to the VkDevice owning the specified VkQueue.
201     */
202    static device_private_data &get(VkQueue queue);
203
204    void add_layer_swapchain(VkSwapchainKHR swapchain);
205
206    /**
207     * @brief Return whether all the provided swapchains are owned by us (the WSI Layer).
208     */
209    bool layer_owns_all_swapchains(const VkSwapchainKHR *swapchain, uint32_t swapchain_count) const;
210
211    /**
212     * @brief Check whether the given swapchain is owned by us (the WSI Layer).
213     */
214    bool layer_owns_swapchain(VkSwapchainKHR swapchain) const {
215       return layer_owns_all_swapchains(&swapchain, 1);
216    }
217
218    /**
219     * @brief Check whether the layer can create a swapchain for the given surface.
220     */
221    bool should_layer_create_swapchain(VkSurfaceKHR vk_surface);
222
223    /**
224     * @brief Check whether the ICDs or layers below support VK_KHR_swapchain.
225     */
226    bool can_icds_create_swapchain(VkSurfaceKHR vk_surface);
227
228    static void destroy(VkDevice dev);
229
230    const device_dispatch_table disp;
231    instance_private_data &instance_data;
232    const PFN_vkSetDeviceLoaderData SetDeviceLoaderData;
233    const VkPhysicalDevice physical_device;
234    const VkDevice device;
235
236 private:
237    std::unordered_set<VkSwapchainKHR> swapchains;
238    mutable std::mutex swapchains_lock;
239 };
240
241 } /* namespace layer */