xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/DeviceVk.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // DeviceVk.cpp:
7 //    Implements the class methods for DeviceVk.
8 //
9 
10 #include "libANGLE/renderer/vulkan/DeviceVk.h"
11 
12 #include <stdint.h>
13 
14 #include "common/debug.h"
15 #include "common/vulkan/vulkan_icd.h"
16 #include "libANGLE/Display.h"
17 #include "libANGLE/renderer/vulkan/DisplayVk.h"
18 #include "libANGLE/renderer/vulkan/vk_renderer.h"
19 
20 namespace rx
21 {
22 namespace
23 {
24 
25 DeviceVk *gDevice = nullptr;
26 
27 class [[nodiscard]] ScopedEnv : public angle::vk::ScopedVkLoaderEnvironment
28 {
29   public:
ScopedEnv()30     ScopedEnv()
31         : angle::vk::ScopedVkLoaderEnvironment(
32               gDevice ? gDevice->getRenderer()->getEnableValidationLayers() : false,
33               gDevice ? gDevice->getRenderer()->getEnabledICD() : angle::vk::ICD::Default)
34     {
35         if (!gDevice)
36         {
37             WARN() << "No DeviceVk instance.";
38         }
39     }
40 };
41 
42 }  // namespace
43 
44 DeviceVk::DeviceVk() = default;
45 
~DeviceVk()46 DeviceVk::~DeviceVk()
47 {
48     if (gDevice == this)
49     {
50         gDevice = nullptr;
51     }
52 }
53 
initialize()54 egl::Error DeviceVk::initialize()
55 {
56     return egl::NoError();
57 }
58 
getAttribute(const egl::Display * display,EGLint attribute,void ** outValue)59 egl::Error DeviceVk::getAttribute(const egl::Display *display, EGLint attribute, void **outValue)
60 {
61     vk::Renderer *renderer =
62         static_cast<rx::DisplayVk *>(display->getImplementation())->getRenderer();
63     ASSERT(mRenderer == nullptr || mRenderer == renderer);
64     mRenderer = renderer;
65     switch (attribute)
66     {
67         case EGL_VULKAN_VERSION_ANGLE:
68         {
69             auto version = static_cast<intptr_t>(mRenderer->getDeviceVersion());
70             *outValue    = reinterpret_cast<void *>(version);
71             return egl::NoError();
72         }
73         case EGL_VULKAN_INSTANCE_ANGLE:
74         {
75             *outValue = mRenderer->getInstance();
76             return egl::NoError();
77         }
78         case EGL_VULKAN_DEVICE_ANGLE:
79         {
80             *outValue = mRenderer->getDevice();
81             return egl::NoError();
82         }
83         case EGL_VULKAN_PHYSICAL_DEVICE_ANGLE:
84         {
85             *outValue = mRenderer->getPhysicalDevice();
86             return egl::NoError();
87         }
88         case EGL_VULKAN_QUEUE_ANGLE:
89         {
90             // Usage of the Vulkan queue by the application is incompatible with the
91             // asyncCommandQueue feature; there is no way for the application to synchronize with
92             // the async thread's usage of the queue.
93             ASSERT(!mRenderer->getFeatures().asyncCommandQueue.enabled);
94 
95             // egl::ContextPriority::Medium is the default context priority.
96             *outValue = mRenderer->getQueue(egl::ContextPriority::Medium);
97             return egl::NoError();
98         }
99         case EGL_VULKAN_QUEUE_FAMILIY_INDEX_ANGLE:
100         {
101             intptr_t index = static_cast<intptr_t>(mRenderer->getQueueFamilyIndex());
102             *outValue      = reinterpret_cast<void *>(index);
103             return egl::NoError();
104         }
105         case EGL_VULKAN_DEVICE_EXTENSIONS_ANGLE:
106         {
107             char **extensions = const_cast<char **>(mRenderer->getEnabledDeviceExtensions().data());
108             *outValue         = reinterpret_cast<void *>(extensions);
109             return egl::NoError();
110         }
111         case EGL_VULKAN_INSTANCE_EXTENSIONS_ANGLE:
112         {
113             char **extensions =
114                 const_cast<char **>(mRenderer->getEnabledInstanceExtensions().data());
115             *outValue = reinterpret_cast<void *>(extensions);
116             return egl::NoError();
117         }
118         case EGL_VULKAN_FEATURES_ANGLE:
119         {
120             const auto *features = &mRenderer->getEnabledFeatures();
121             *outValue            = const_cast<void *>(reinterpret_cast<const void *>(features));
122             return egl::NoError();
123         }
124         case EGL_VULKAN_GET_INSTANCE_PROC_ADDR:
125         {
126             *outValue = reinterpret_cast<void *>(DeviceVk::WrappedGetInstanceProcAddr);
127             ASSERT(!gDevice || gDevice == this);
128             gDevice = this;
129             return egl::NoError();
130         }
131         default:
132             return egl::EglBadAccess();
133     }
134 }
135 
generateExtensions(egl::DeviceExtensions * outExtensions) const136 void DeviceVk::generateExtensions(egl::DeviceExtensions *outExtensions) const
137 {
138     outExtensions->deviceVulkan = true;
139 }
140 
141 // static
142 VKAPI_ATTR VkResult VKAPI_CALL
WrappedCreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)143 DeviceVk::WrappedCreateInstance(const VkInstanceCreateInfo *pCreateInfo,
144                                 const VkAllocationCallbacks *pAllocator,
145                                 VkInstance *pInstance)
146 {
147     ScopedEnv scopedEnv;
148     return vkCreateInstance(pCreateInfo, pAllocator, pInstance);
149 }
150 
151 // static
152 VKAPI_ATTR VkResult VKAPI_CALL
WrappedEnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)153 DeviceVk::WrappedEnumerateInstanceExtensionProperties(const char *pLayerName,
154                                                       uint32_t *pPropertyCount,
155                                                       VkExtensionProperties *pProperties)
156 {
157     ScopedEnv scopedEnv;
158     return vkEnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
159 }
160 
161 // static
162 VKAPI_ATTR VkResult VKAPI_CALL
WrappedEnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)163 DeviceVk::WrappedEnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
164                                                   VkLayerProperties *pProperties)
165 {
166     ScopedEnv scopedEnv;
167     return vkEnumerateInstanceLayerProperties(pPropertyCount, pProperties);
168 }
169 
170 // static
WrappedEnumerateInstanceVersion(uint32_t * pApiVersion)171 VKAPI_ATTR VkResult VKAPI_CALL DeviceVk::WrappedEnumerateInstanceVersion(uint32_t *pApiVersion)
172 {
173     ScopedEnv scopedEnv;
174     return vkEnumerateInstanceVersion(pApiVersion);
175 }
176 
177 // static
WrappedGetInstanceProcAddr(VkInstance instance,const char * pName)178 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL DeviceVk::WrappedGetInstanceProcAddr(VkInstance instance,
179                                                                               const char *pName)
180 {
181     if (!pName || pName[0] != 'v' || pName[1] != 'k')
182     {
183         return nullptr;
184     }
185 
186     if (instance != VK_NULL_HANDLE)
187     {
188         return vkGetInstanceProcAddr(instance, pName);
189     }
190 
191     if (!strcmp(pName, "vkCreateInstance"))
192     {
193         return reinterpret_cast<PFN_vkVoidFunction>(DeviceVk::WrappedCreateInstance);
194     }
195     if (!strcmp(pName, "vkEnumerateInstanceExtensionProperties"))
196     {
197         return reinterpret_cast<PFN_vkVoidFunction>(
198             DeviceVk::WrappedEnumerateInstanceExtensionProperties);
199     }
200     if (!strcmp(pName, "vkEnumerateInstanceLayerProperties"))
201     {
202         return reinterpret_cast<PFN_vkVoidFunction>(
203             DeviceVk::WrappedEnumerateInstanceLayerProperties);
204     }
205     if (!strcmp(pName, "vkEnumerateInstanceVersion"))
206     {
207         if (!vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"))
208         {
209             // Vulkan 1.0 doesn't have vkEnumerateInstanceVersion.
210             return nullptr;
211         }
212         return reinterpret_cast<PFN_vkVoidFunction>(DeviceVk::WrappedEnumerateInstanceVersion);
213     }
214     if (!strcmp(pName, "vkGetInstanceProcAddr"))
215     {
216         return reinterpret_cast<PFN_vkVoidFunction>(DeviceVk::WrappedGetInstanceProcAddr);
217     }
218 
219     return vkGetInstanceProcAddr(instance, pName);
220 }
221 
222 }  // namespace rx
223