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/RendererVk.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 RendererVk *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 // egl::ContextPriority::Medium is the default context priority.
91 *outValue = mRenderer->getQueue(egl::ContextPriority::Medium);
92 return egl::NoError();
93 }
94 case EGL_VULKAN_QUEUE_FAMILIY_INDEX_ANGLE:
95 {
96 intptr_t index = static_cast<intptr_t>(mRenderer->getQueueFamilyIndex());
97 *outValue = reinterpret_cast<void *>(index);
98 return egl::NoError();
99 }
100 case EGL_VULKAN_DEVICE_EXTENSIONS_ANGLE:
101 {
102 char **extensions = const_cast<char **>(mRenderer->getEnabledDeviceExtensions().data());
103 *outValue = reinterpret_cast<void *>(extensions);
104 return egl::NoError();
105 }
106 case EGL_VULKAN_INSTANCE_EXTENSIONS_ANGLE:
107 {
108 char **extensions =
109 const_cast<char **>(mRenderer->getEnabledInstanceExtensions().data());
110 *outValue = reinterpret_cast<void *>(extensions);
111 return egl::NoError();
112 }
113 case EGL_VULKAN_FEATURES_ANGLE:
114 {
115 const auto *features = &mRenderer->getEnabledFeatures();
116 *outValue = const_cast<void *>(reinterpret_cast<const void *>(features));
117 return egl::NoError();
118 }
119 case EGL_VULKAN_GET_INSTANCE_PROC_ADDR:
120 {
121 *outValue = reinterpret_cast<void *>(DeviceVk::WrappedGetInstanceProcAddr);
122 ASSERT(!gDevice || gDevice == this);
123 gDevice = this;
124 return egl::NoError();
125 }
126 default:
127 return egl::EglBadAccess();
128 }
129 }
130
getType()131 EGLint DeviceVk::getType()
132 {
133 return EGL_VULKAN_DEVICE_ANGLE;
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