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