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