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 // 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::Error(EGL_BAD_ACCESS);
128 }
129 }
130
generateExtensions(egl::DeviceExtensions * outExtensions) const131 void DeviceVk::generateExtensions(egl::DeviceExtensions *outExtensions) const
132 {
133 outExtensions->deviceVulkan = true;
134 }
135
136 // static
137 VKAPI_ATTR VkResult VKAPI_CALL
WrappedCreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)138 DeviceVk::WrappedCreateInstance(const VkInstanceCreateInfo *pCreateInfo,
139 const VkAllocationCallbacks *pAllocator,
140 VkInstance *pInstance)
141 {
142 ScopedEnv scopedEnv;
143 return vkCreateInstance(pCreateInfo, pAllocator, pInstance);
144 }
145
146 // static
147 VKAPI_ATTR VkResult VKAPI_CALL
WrappedEnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)148 DeviceVk::WrappedEnumerateInstanceExtensionProperties(const char *pLayerName,
149 uint32_t *pPropertyCount,
150 VkExtensionProperties *pProperties)
151 {
152 ScopedEnv scopedEnv;
153 return vkEnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
154 }
155
156 // static
157 VKAPI_ATTR VkResult VKAPI_CALL
WrappedEnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)158 DeviceVk::WrappedEnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
159 VkLayerProperties *pProperties)
160 {
161 ScopedEnv scopedEnv;
162 return vkEnumerateInstanceLayerProperties(pPropertyCount, pProperties);
163 }
164
165 // static
WrappedEnumerateInstanceVersion(uint32_t * pApiVersion)166 VKAPI_ATTR VkResult VKAPI_CALL DeviceVk::WrappedEnumerateInstanceVersion(uint32_t *pApiVersion)
167 {
168 ScopedEnv scopedEnv;
169 return vkEnumerateInstanceVersion(pApiVersion);
170 }
171
172 // static
WrappedGetInstanceProcAddr(VkInstance instance,const char * pName)173 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL DeviceVk::WrappedGetInstanceProcAddr(VkInstance instance,
174 const char *pName)
175 {
176 if (!pName || pName[0] != 'v' || pName[1] != 'k')
177 {
178 return nullptr;
179 }
180
181 if (instance != VK_NULL_HANDLE)
182 {
183 return vkGetInstanceProcAddr(instance, pName);
184 }
185
186 if (!strcmp(pName, "vkCreateInstance"))
187 {
188 return reinterpret_cast<PFN_vkVoidFunction>(DeviceVk::WrappedCreateInstance);
189 }
190 if (!strcmp(pName, "vkEnumerateInstanceExtensionProperties"))
191 {
192 return reinterpret_cast<PFN_vkVoidFunction>(
193 DeviceVk::WrappedEnumerateInstanceExtensionProperties);
194 }
195 if (!strcmp(pName, "vkEnumerateInstanceLayerProperties"))
196 {
197 return reinterpret_cast<PFN_vkVoidFunction>(
198 DeviceVk::WrappedEnumerateInstanceLayerProperties);
199 }
200 if (!strcmp(pName, "vkEnumerateInstanceVersion"))
201 {
202 if (!vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"))
203 {
204 // Vulkan 1.0 doesn't have vkEnumerateInstanceVersion.
205 return nullptr;
206 }
207 return reinterpret_cast<PFN_vkVoidFunction>(DeviceVk::WrappedEnumerateInstanceVersion);
208 }
209 if (!strcmp(pName, "vkGetInstanceProcAddr"))
210 {
211 return reinterpret_cast<PFN_vkVoidFunction>(DeviceVk::WrappedGetInstanceProcAddr);
212 }
213
214 return vkGetInstanceProcAddr(instance, pName);
215 }
216
217 } // namespace rx
218