• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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