• 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 // DisplayVk.cpp:
7 //    Implements the class methods for DisplayVk.
8 //
9 
10 #include "libANGLE/renderer/vulkan/DisplayVk.h"
11 
12 #include "common/debug.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/Display.h"
15 #include "libANGLE/renderer/vulkan/ContextVk.h"
16 #include "libANGLE/renderer/vulkan/ImageVk.h"
17 #include "libANGLE/renderer/vulkan/RendererVk.h"
18 #include "libANGLE/renderer/vulkan/SurfaceVk.h"
19 #include "libANGLE/renderer/vulkan/SyncVk.h"
20 #include "libANGLE/trace.h"
21 
22 namespace rx
23 {
24 
DisplayVk(const egl::DisplayState & state)25 DisplayVk::DisplayVk(const egl::DisplayState &state)
26     : DisplayImpl(state),
27       vk::Context(new RendererVk()),
28       mScratchBuffer(1000u),
29       mSavedError({VK_SUCCESS, "", "", 0})
30 {}
31 
~DisplayVk()32 DisplayVk::~DisplayVk()
33 {
34     delete mRenderer;
35 }
36 
initialize(egl::Display * display)37 egl::Error DisplayVk::initialize(egl::Display *display)
38 {
39     ASSERT(mRenderer != nullptr && display != nullptr);
40     angle::Result result = mRenderer->initialize(this, display, getWSIExtension(), getWSILayer());
41     ANGLE_TRY(angle::ToEGL(result, this, EGL_NOT_INITIALIZED));
42     return egl::NoError();
43 }
44 
terminate()45 void DisplayVk::terminate()
46 {
47     mRenderer->reloadVolkIfNeeded();
48 
49     ASSERT(mRenderer);
50     mRenderer->onDestroy(this);
51 }
52 
makeCurrent(egl::Display *,egl::Surface *,egl::Surface *,gl::Context *)53 egl::Error DisplayVk::makeCurrent(egl::Display * /*display*/,
54                                   egl::Surface * /*drawSurface*/,
55                                   egl::Surface * /*readSurface*/,
56                                   gl::Context * /*context*/)
57 {
58     // Ensure the appropriate global DebugAnnotator is used
59     ASSERT(mRenderer);
60     mRenderer->setGlobalDebugAnnotator();
61 
62     return egl::NoError();
63 }
64 
testDeviceLost()65 bool DisplayVk::testDeviceLost()
66 {
67     return mRenderer->isDeviceLost();
68 }
69 
restoreLostDevice(const egl::Display * display)70 egl::Error DisplayVk::restoreLostDevice(const egl::Display *display)
71 {
72     // A vulkan device cannot be restored, the entire renderer would have to be re-created along
73     // with any other EGL objects that reference it.
74     return egl::EglBadDisplay();
75 }
76 
getRendererDescription()77 std::string DisplayVk::getRendererDescription()
78 {
79     if (mRenderer)
80     {
81         return mRenderer->getRendererDescription();
82     }
83     return std::string();
84 }
85 
getVendorString()86 std::string DisplayVk::getVendorString()
87 {
88     if (mRenderer)
89     {
90         return mRenderer->getVendorString();
91     }
92     return std::string();
93 }
94 
getVersionString()95 std::string DisplayVk::getVersionString()
96 {
97     if (mRenderer)
98     {
99         return mRenderer->getVersionString();
100     }
101     return std::string();
102 }
103 
waitClient(const gl::Context * context)104 egl::Error DisplayVk::waitClient(const gl::Context *context)
105 {
106     ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitClient");
107     ContextVk *contextVk = vk::GetImpl(context);
108     return angle::ToEGL(contextVk->finishImpl(), this, EGL_BAD_ACCESS);
109 }
110 
waitNative(const gl::Context * context,EGLint engine)111 egl::Error DisplayVk::waitNative(const gl::Context *context, EGLint engine)
112 {
113     ANGLE_TRACE_EVENT0("gpu.angle", "DisplayVk::waitNative");
114     return angle::ResultToEGL(waitNativeImpl());
115 }
116 
waitNativeImpl()117 angle::Result DisplayVk::waitNativeImpl()
118 {
119     return angle::Result::Continue;
120 }
121 
createWindowSurface(const egl::SurfaceState & state,EGLNativeWindowType window,const egl::AttributeMap & attribs)122 SurfaceImpl *DisplayVk::createWindowSurface(const egl::SurfaceState &state,
123                                             EGLNativeWindowType window,
124                                             const egl::AttributeMap &attribs)
125 {
126     return createWindowSurfaceVk(state, window);
127 }
128 
createPbufferSurface(const egl::SurfaceState & state,const egl::AttributeMap & attribs)129 SurfaceImpl *DisplayVk::createPbufferSurface(const egl::SurfaceState &state,
130                                              const egl::AttributeMap &attribs)
131 {
132     ASSERT(mRenderer);
133     return new OffscreenSurfaceVk(state, mRenderer);
134 }
135 
createPbufferFromClientBuffer(const egl::SurfaceState & state,EGLenum buftype,EGLClientBuffer clientBuffer,const egl::AttributeMap & attribs)136 SurfaceImpl *DisplayVk::createPbufferFromClientBuffer(const egl::SurfaceState &state,
137                                                       EGLenum buftype,
138                                                       EGLClientBuffer clientBuffer,
139                                                       const egl::AttributeMap &attribs)
140 {
141     UNIMPLEMENTED();
142     return static_cast<SurfaceImpl *>(0);
143 }
144 
createPixmapSurface(const egl::SurfaceState & state,NativePixmapType nativePixmap,const egl::AttributeMap & attribs)145 SurfaceImpl *DisplayVk::createPixmapSurface(const egl::SurfaceState &state,
146                                             NativePixmapType nativePixmap,
147                                             const egl::AttributeMap &attribs)
148 {
149     UNIMPLEMENTED();
150     return static_cast<SurfaceImpl *>(0);
151 }
152 
createImage(const egl::ImageState & state,const gl::Context * context,EGLenum target,const egl::AttributeMap & attribs)153 ImageImpl *DisplayVk::createImage(const egl::ImageState &state,
154                                   const gl::Context *context,
155                                   EGLenum target,
156                                   const egl::AttributeMap &attribs)
157 {
158     return new ImageVk(state, context);
159 }
160 
createShareGroup()161 ShareGroupImpl *DisplayVk::createShareGroup()
162 {
163     return new ShareGroupVk();
164 }
165 
createContext(const gl::State & state,gl::ErrorSet * errorSet,const egl::Config * configuration,const gl::Context * shareContext,const egl::AttributeMap & attribs)166 ContextImpl *DisplayVk::createContext(const gl::State &state,
167                                       gl::ErrorSet *errorSet,
168                                       const egl::Config *configuration,
169                                       const gl::Context *shareContext,
170                                       const egl::AttributeMap &attribs)
171 {
172     return new ContextVk(state, errorSet, mRenderer);
173 }
174 
createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,const egl::AttributeMap & attribs)175 StreamProducerImpl *DisplayVk::createStreamProducerD3DTexture(
176     egl::Stream::ConsumerType consumerType,
177     const egl::AttributeMap &attribs)
178 {
179     UNIMPLEMENTED();
180     return static_cast<StreamProducerImpl *>(0);
181 }
182 
createSync(const egl::AttributeMap & attribs)183 EGLSyncImpl *DisplayVk::createSync(const egl::AttributeMap &attribs)
184 {
185     return new EGLSyncVk(attribs);
186 }
187 
getMaxSupportedESVersion() const188 gl::Version DisplayVk::getMaxSupportedESVersion() const
189 {
190     return mRenderer->getMaxSupportedESVersion();
191 }
192 
getMaxConformantESVersion() const193 gl::Version DisplayVk::getMaxConformantESVersion() const
194 {
195     return mRenderer->getMaxConformantESVersion();
196 }
197 
generateExtensions(egl::DisplayExtensions * outExtensions) const198 void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
199 {
200     outExtensions->createContextRobustness      = getRenderer()->getNativeExtensions().robustness;
201     outExtensions->surfaceOrientation           = true;
202     outExtensions->displayTextureShareGroup     = true;
203     outExtensions->displaySemaphoreShareGroup   = true;
204     outExtensions->robustResourceInitialization = true;
205 
206     // The Vulkan implementation will always say that EGL_KHR_swap_buffers_with_damage is supported.
207     // When the Vulkan driver supports VK_KHR_incremental_present, it will use it.  Otherwise, it
208     // will ignore the hint and do a regular swap.
209     outExtensions->swapBuffersWithDamage = true;
210 
211     outExtensions->fenceSync = true;
212     outExtensions->waitSync  = true;
213 
214     outExtensions->image                 = true;
215     outExtensions->imageBase             = true;
216     outExtensions->imagePixmap           = false;  // ANGLE does not support pixmaps
217     outExtensions->glTexture2DImage      = true;
218     outExtensions->glTextureCubemapImage = true;
219     outExtensions->glTexture3DImage      = false;
220     outExtensions->glRenderbufferImage   = true;
221     outExtensions->imageNativeBuffer =
222         getRenderer()->getFeatures().supportsAndroidHardwareBuffer.enabled;
223     outExtensions->surfacelessContext = true;
224     outExtensions->glColorspace = getRenderer()->getFeatures().supportsSwapchainColorspace.enabled;
225     outExtensions->imageGlColorspace =
226         outExtensions->glColorspace && getRenderer()->getFeatures().supportsImageFormatList.enabled;
227 
228 #if defined(ANGLE_PLATFORM_ANDROID)
229     outExtensions->getNativeClientBufferANDROID = true;
230     outExtensions->framebufferTargetANDROID     = true;
231 #endif  // defined(ANGLE_PLATFORM_ANDROID)
232 
233     // Disable context priority when non-zero memory init is enabled. This enforces a queue order.
234     outExtensions->contextPriority = !getRenderer()->getFeatures().allocateNonZeroMemory.enabled;
235     outExtensions->noConfigContext = true;
236 
237 #if defined(ANGLE_PLATFORM_ANDROID)
238     outExtensions->nativeFenceSyncANDROID =
239         getRenderer()->getFeatures().supportsAndroidNativeFenceSync.enabled;
240 #endif  // defined(ANGLE_PLATFORM_ANDROID)
241 
242 #if defined(ANGLE_PLATFORM_GGP)
243     outExtensions->ggpStreamDescriptor = true;
244     outExtensions->swapWithFrameToken  = getRenderer()->getFeatures().supportsGGPFrameToken.enabled;
245 #endif  // defined(ANGLE_PLATFORM_GGP)
246 
247     outExtensions->bufferAgeEXT = true;
248 
249     outExtensions->protectedContentEXT =
250         (getRenderer()->getFeatures().supportsProtectedMemory.enabled &&
251          getRenderer()->getFeatures().supportsSurfaceProtectedSwapchains.enabled);
252 }
253 
generateCaps(egl::Caps * outCaps) const254 void DisplayVk::generateCaps(egl::Caps *outCaps) const
255 {
256     outCaps->textureNPOT = true;
257     outCaps->stencil8    = getRenderer()->getNativeExtensions().stencilIndex8;
258 }
259 
getWSILayer() const260 const char *DisplayVk::getWSILayer() const
261 {
262     return nullptr;
263 }
264 
isUsingSwapchain() const265 bool DisplayVk::isUsingSwapchain() const
266 {
267     return true;
268 }
269 
getScratchBuffer(size_t requstedSizeBytes,angle::MemoryBuffer ** scratchBufferOut) const270 bool DisplayVk::getScratchBuffer(size_t requstedSizeBytes,
271                                  angle::MemoryBuffer **scratchBufferOut) const
272 {
273     return mScratchBuffer.get(requstedSizeBytes, scratchBufferOut);
274 }
275 
handleError(VkResult result,const char * file,const char * function,unsigned int line)276 void DisplayVk::handleError(VkResult result,
277                             const char *file,
278                             const char *function,
279                             unsigned int line)
280 {
281     ASSERT(result != VK_SUCCESS);
282 
283     mSavedError.errorCode = result;
284     mSavedError.file      = file;
285     mSavedError.function  = function;
286     mSavedError.line      = line;
287 
288     if (result == VK_ERROR_DEVICE_LOST)
289     {
290         WARN() << "Internal Vulkan error (" << result << "): " << VulkanResultString(result)
291                << ", in " << file << ", " << function << ":" << line << ".";
292         mRenderer->notifyDeviceLost();
293     }
294 }
295 
296 // TODO(jmadill): Remove this. http://anglebug.com/3041
getEGLError(EGLint errorCode)297 egl::Error DisplayVk::getEGLError(EGLint errorCode)
298 {
299     std::stringstream errorStream;
300     errorStream << "Internal Vulkan error (" << mSavedError.errorCode
301                 << "): " << VulkanResultString(mSavedError.errorCode) << ", in " << mSavedError.file
302                 << ", " << mSavedError.function << ":" << mSavedError.line << ".";
303     std::string errorString = errorStream.str();
304 
305     return egl::Error(errorCode, 0, std::move(errorString));
306 }
307 
populateFeatureList(angle::FeatureList * features)308 void DisplayVk::populateFeatureList(angle::FeatureList *features)
309 {
310     mRenderer->getFeatures().populateFeatureList(features);
311 }
312 
ShareGroupVk()313 ShareGroupVk::ShareGroupVk() : mSyncObjectPendingFlush(false) {}
314 
onDestroy(const egl::Display * display)315 void ShareGroupVk::onDestroy(const egl::Display *display)
316 {
317     DisplayVk *displayVk = vk::GetImpl(display);
318 
319     mPipelineLayoutCache.destroy(displayVk->getRenderer());
320     mDescriptorSetLayoutCache.destroy(displayVk->getRenderer());
321 
322     ASSERT(mResourceUseLists.empty());
323 }
324 }  // namespace rx
325