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