1 //
2 // Copyright 2015 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
7 // RendererGL.cpp: Implements the class methods for RendererGL.
8
9 #include "libANGLE/renderer/gl/RendererGL.h"
10
11 #include <EGL/eglext.h>
12 #include <thread>
13
14 #include "common/debug.h"
15 #include "common/system_utils.h"
16 #include "libANGLE/AttributeMap.h"
17 #include "libANGLE/Context.h"
18 #include "libANGLE/Display.h"
19 #include "libANGLE/State.h"
20 #include "libANGLE/Surface.h"
21 #include "libANGLE/renderer/gl/BlitGL.h"
22 #include "libANGLE/renderer/gl/BufferGL.h"
23 #include "libANGLE/renderer/gl/ClearMultiviewGL.h"
24 #include "libANGLE/renderer/gl/CompilerGL.h"
25 #include "libANGLE/renderer/gl/ContextGL.h"
26 #include "libANGLE/renderer/gl/DisplayGL.h"
27 #include "libANGLE/renderer/gl/FenceNVGL.h"
28 #include "libANGLE/renderer/gl/FramebufferGL.h"
29 #include "libANGLE/renderer/gl/FunctionsGL.h"
30 #include "libANGLE/renderer/gl/PLSProgramCache.h"
31 #include "libANGLE/renderer/gl/ProgramGL.h"
32 #include "libANGLE/renderer/gl/QueryGL.h"
33 #include "libANGLE/renderer/gl/RenderbufferGL.h"
34 #include "libANGLE/renderer/gl/SamplerGL.h"
35 #include "libANGLE/renderer/gl/ShaderGL.h"
36 #include "libANGLE/renderer/gl/StateManagerGL.h"
37 #include "libANGLE/renderer/gl/SurfaceGL.h"
38 #include "libANGLE/renderer/gl/SyncGL.h"
39 #include "libANGLE/renderer/gl/TextureGL.h"
40 #include "libANGLE/renderer/gl/TransformFeedbackGL.h"
41 #include "libANGLE/renderer/gl/VertexArrayGL.h"
42 #include "libANGLE/renderer/gl/renderergl_utils.h"
43 #include "libANGLE/renderer/renderer_utils.h"
44
45 namespace
46 {
47
SetMaxShaderCompilerThreads(const rx::FunctionsGL * functions,GLuint count)48 void SetMaxShaderCompilerThreads(const rx::FunctionsGL *functions, GLuint count)
49 {
50 if (functions->maxShaderCompilerThreadsKHR != nullptr)
51 {
52 functions->maxShaderCompilerThreadsKHR(count);
53 }
54 else
55 {
56 ASSERT(functions->maxShaderCompilerThreadsARB != nullptr);
57 functions->maxShaderCompilerThreadsARB(count);
58 }
59 }
60
61 #if defined(ANGLE_PLATFORM_ANDROID)
62 const char *kIgnoredErrors[] = {
63 // Wrong error message on Android Q Pixel 2. http://anglebug.com/3491
64 "FreeAllocationOnTimestamp - Reference to buffer created from "
65 "different context without a share list. Application failed to pass "
66 "share_context to eglCreateContext. Results are undefined.",
67 // http://crbug.com/1348684
68 "UpdateTimestamp - Reference to buffer created from different context without a share list. "
69 "Application failed to pass share_context to eglCreateContext. Results are undefined.",
70 "Attempt to use resource over contexts without enabling context sharing. App must pass a "
71 "share_context to eglCreateContext() to share resources.",
72 };
73 #endif // defined(ANGLE_PLATFORM_ANDROID)
74
75 const char *kIgnoredWarnings[] = {
76 // We always request GL_ARB_gpu_shader5 and GL_EXT_gpu_shader5 when compiling shaders but some
77 // drivers warn when it is not present. This ends up spamming the console on every shader
78 // compile.
79 "extension `GL_ARB_gpu_shader5' unsupported in",
80 "extension `GL_EXT_gpu_shader5' unsupported in",
81 };
82
83 } // namespace
84
LogGLDebugMessage(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const void * userParam)85 static void INTERNAL_GL_APIENTRY LogGLDebugMessage(GLenum source,
86 GLenum type,
87 GLuint id,
88 GLenum severity,
89 GLsizei length,
90 const GLchar *message,
91 const void *userParam)
92 {
93 std::string sourceText = gl::GetDebugMessageSourceString(source);
94 std::string typeText = gl::GetDebugMessageTypeString(type);
95 std::string severityText = gl::GetDebugMessageSeverityString(severity);
96
97 #if defined(ANGLE_PLATFORM_ANDROID)
98 if (type == GL_DEBUG_TYPE_ERROR)
99 {
100 for (const char *&err : kIgnoredErrors)
101 {
102 if (strncmp(err, message, length) == 0)
103 {
104 // There is only one ignored message right now and it is quite spammy, around 3MB
105 // for a complete end2end tests run, so don't print it even as a warning.
106 return;
107 }
108 }
109 }
110 #endif // defined(ANGLE_PLATFORM_ANDROID)
111
112 if (type == GL_DEBUG_TYPE_ERROR)
113 {
114 ERR() << std::endl
115 << "\tSource: " << sourceText << std::endl
116 << "\tType: " << typeText << std::endl
117 << "\tID: " << gl::FmtHex(id) << std::endl
118 << "\tSeverity: " << severityText << std::endl
119 << "\tMessage: " << message;
120 }
121 else if (type != GL_DEBUG_TYPE_PERFORMANCE)
122 {
123 // Don't print performance warnings. They tend to be very spammy in the dEQP test suite and
124 // there is very little we can do about them.
125
126 for (const char *&warn : kIgnoredWarnings)
127 {
128 if (strstr(message, warn) != nullptr)
129 {
130 return;
131 }
132 }
133
134 // TODO(ynovikov): filter into WARN and INFO if INFO is ever implemented
135 WARN() << std::endl
136 << "\tSource: " << sourceText << std::endl
137 << "\tType: " << typeText << std::endl
138 << "\tID: " << gl::FmtHex(id) << std::endl
139 << "\tSeverity: " << severityText << std::endl
140 << "\tMessage: " << message;
141 }
142 }
143
144 namespace rx
145 {
146
RendererGL(std::unique_ptr<FunctionsGL> functions,const egl::AttributeMap & attribMap,DisplayGL * display)147 RendererGL::RendererGL(std::unique_ptr<FunctionsGL> functions,
148 const egl::AttributeMap &attribMap,
149 DisplayGL *display)
150 : mMaxSupportedESVersion(0, 0),
151 mFunctions(std::move(functions)),
152 mStateManager(nullptr),
153 mBlitter(nullptr),
154 mMultiviewClearer(nullptr),
155 mUseDebugOutput(false),
156 mCapsInitialized(false),
157 mMultiviewImplementationType(MultiviewImplementationTypeGL::UNSPECIFIED),
158 mNativeParallelCompileEnabled(false),
159 mNeedsFlushBeforeDeleteTextures(false)
160 {
161 ASSERT(mFunctions);
162 if (!display->getState().featuresAllDisabled)
163 {
164 nativegl_gl::InitializeFeatures(mFunctions.get(), &mFeatures);
165 }
166 ApplyFeatureOverrides(&mFeatures, display->getState());
167 mStateManager =
168 new StateManagerGL(mFunctions.get(), getNativeCaps(), getNativeExtensions(), mFeatures);
169 mBlitter = new BlitGL(mFunctions.get(), mFeatures, mStateManager);
170 mMultiviewClearer = new ClearMultiviewGL(mFunctions.get(), mStateManager);
171
172 bool hasDebugOutput = mFunctions->isAtLeastGL(gl::Version(4, 3)) ||
173 mFunctions->hasGLExtension("GL_KHR_debug") ||
174 mFunctions->isAtLeastGLES(gl::Version(3, 2)) ||
175 mFunctions->hasGLESExtension("GL_KHR_debug");
176
177 mUseDebugOutput = hasDebugOutput && ShouldUseDebugLayers(attribMap);
178
179 if (mUseDebugOutput)
180 {
181 mFunctions->enable(GL_DEBUG_OUTPUT);
182 mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
183 mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0,
184 nullptr, GL_TRUE);
185 mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0,
186 nullptr, GL_TRUE);
187 mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0,
188 nullptr, GL_FALSE);
189 mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION,
190 0, nullptr, GL_FALSE);
191 mFunctions->debugMessageCallback(&LogGLDebugMessage, nullptr);
192 }
193
194 if (mFeatures.initializeCurrentVertexAttributes.enabled)
195 {
196 GLint maxVertexAttribs = 0;
197 mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
198
199 for (GLint i = 0; i < maxVertexAttribs; ++i)
200 {
201 mFunctions->vertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 1.0f);
202 }
203 }
204
205 if (hasNativeParallelCompile() && !mNativeParallelCompileEnabled)
206 {
207 SetMaxShaderCompilerThreads(mFunctions.get(), 0xffffffff);
208 mNativeParallelCompileEnabled = true;
209 }
210 }
211
~RendererGL()212 RendererGL::~RendererGL()
213 {
214 SafeDelete(mBlitter);
215 SafeDelete(mMultiviewClearer);
216 SafeDelete(mStateManager);
217 SafeDelete(mPLSProgramCache);
218
219 std::lock_guard<std::mutex> lock(mWorkerMutex);
220
221 ASSERT(mCurrentWorkerContexts.empty());
222 mWorkerContextPool.clear();
223 }
224
flush()225 angle::Result RendererGL::flush()
226 {
227 if (!mWorkDoneSinceLastFlush && !mNeedsFlushBeforeDeleteTextures)
228 {
229 return angle::Result::Continue;
230 }
231
232 mFunctions->flush();
233 mNeedsFlushBeforeDeleteTextures = false;
234 mWorkDoneSinceLastFlush = false;
235 return angle::Result::Continue;
236 }
237
finish()238 angle::Result RendererGL::finish()
239 {
240 if (mFeatures.finishDoesNotCauseQueriesToBeAvailable.enabled && mUseDebugOutput)
241 {
242 mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
243 }
244
245 mFunctions->finish();
246 mNeedsFlushBeforeDeleteTextures = false;
247 mWorkDoneSinceLastFlush = false;
248
249 if (mFeatures.finishDoesNotCauseQueriesToBeAvailable.enabled && mUseDebugOutput)
250 {
251 mFunctions->disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
252 }
253
254 return angle::Result::Continue;
255 }
256
getResetStatus()257 gl::GraphicsResetStatus RendererGL::getResetStatus()
258 {
259 return gl::FromGLenum<gl::GraphicsResetStatus>(mFunctions->getGraphicsResetStatus());
260 }
261
insertEventMarker(GLsizei length,const char * marker)262 void RendererGL::insertEventMarker(GLsizei length, const char *marker) {}
263
pushGroupMarker(GLsizei length,const char * marker)264 void RendererGL::pushGroupMarker(GLsizei length, const char *marker) {}
265
popGroupMarker()266 void RendererGL::popGroupMarker() {}
267
pushDebugGroup(GLenum source,GLuint id,const std::string & message)268 void RendererGL::pushDebugGroup(GLenum source, GLuint id, const std::string &message) {}
269
popDebugGroup()270 void RendererGL::popDebugGroup() {}
271
getMaxSupportedESVersion() const272 const gl::Version &RendererGL::getMaxSupportedESVersion() const
273 {
274 // Force generation of caps
275 getNativeCaps();
276
277 return mMaxSupportedESVersion;
278 }
279
generateCaps(gl::Caps * outCaps,gl::TextureCapsMap * outTextureCaps,gl::Extensions * outExtensions,gl::Limitations * outLimitations) const280 void RendererGL::generateCaps(gl::Caps *outCaps,
281 gl::TextureCapsMap *outTextureCaps,
282 gl::Extensions *outExtensions,
283 gl::Limitations *outLimitations) const
284 {
285 nativegl_gl::GenerateCaps(mFunctions.get(), mFeatures, outCaps, outTextureCaps, outExtensions,
286 outLimitations, &mMaxSupportedESVersion,
287 &mMultiviewImplementationType, &mNativePLSOptions);
288 }
289
getGPUDisjoint()290 GLint RendererGL::getGPUDisjoint()
291 {
292 // TODO(ewell): On GLES backends we should find a way to reliably query disjoint events
293 return 0;
294 }
295
getTimestamp()296 GLint64 RendererGL::getTimestamp()
297 {
298 GLint64 result = 0;
299 mFunctions->getInteger64v(GL_TIMESTAMP, &result);
300 return result;
301 }
302
ensureCapsInitialized() const303 void RendererGL::ensureCapsInitialized() const
304 {
305 if (!mCapsInitialized)
306 {
307 generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
308 mCapsInitialized = true;
309 }
310 }
311
getNativeCaps() const312 const gl::Caps &RendererGL::getNativeCaps() const
313 {
314 ensureCapsInitialized();
315 return mNativeCaps;
316 }
317
getNativeTextureCaps() const318 const gl::TextureCapsMap &RendererGL::getNativeTextureCaps() const
319 {
320 ensureCapsInitialized();
321 return mNativeTextureCaps;
322 }
323
getNativeExtensions() const324 const gl::Extensions &RendererGL::getNativeExtensions() const
325 {
326 ensureCapsInitialized();
327 return mNativeExtensions;
328 }
329
getNativeLimitations() const330 const gl::Limitations &RendererGL::getNativeLimitations() const
331 {
332 ensureCapsInitialized();
333 return mNativeLimitations;
334 }
335
getNativePixelLocalStorageOptions() const336 const ShPixelLocalStorageOptions &RendererGL::getNativePixelLocalStorageOptions() const
337 {
338 return mNativePLSOptions;
339 }
340
getPLSProgramCache()341 PLSProgramCache *RendererGL::getPLSProgramCache()
342 {
343 if (!mPLSProgramCache)
344 {
345 mPLSProgramCache = new PLSProgramCache(mFunctions.get(), mNativeCaps);
346 }
347 return mPLSProgramCache;
348 }
349
getMultiviewImplementationType() const350 MultiviewImplementationTypeGL RendererGL::getMultiviewImplementationType() const
351 {
352 ensureCapsInitialized();
353 return mMultiviewImplementationType;
354 }
355
initializeFrontendFeatures(angle::FrontendFeatures * features) const356 void RendererGL::initializeFrontendFeatures(angle::FrontendFeatures *features) const
357 {
358 ensureCapsInitialized();
359 nativegl_gl::InitializeFrontendFeatures(mFunctions.get(), features);
360 }
361
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)362 angle::Result RendererGL::dispatchCompute(const gl::Context *context,
363 GLuint numGroupsX,
364 GLuint numGroupsY,
365 GLuint numGroupsZ)
366 {
367 mFunctions->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
368 mWorkDoneSinceLastFlush = true;
369 return angle::Result::Continue;
370 }
371
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)372 angle::Result RendererGL::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
373 {
374 mFunctions->dispatchComputeIndirect(indirect);
375 mWorkDoneSinceLastFlush = true;
376 return angle::Result::Continue;
377 }
378
memoryBarrier(GLbitfield barriers)379 angle::Result RendererGL::memoryBarrier(GLbitfield barriers)
380 {
381 mFunctions->memoryBarrier(barriers);
382 mWorkDoneSinceLastFlush = true;
383 return angle::Result::Continue;
384 }
memoryBarrierByRegion(GLbitfield barriers)385 angle::Result RendererGL::memoryBarrierByRegion(GLbitfield barriers)
386 {
387 mFunctions->memoryBarrierByRegion(barriers);
388 mWorkDoneSinceLastFlush = true;
389 return angle::Result::Continue;
390 }
391
framebufferFetchBarrier()392 void RendererGL::framebufferFetchBarrier()
393 {
394 mFunctions->framebufferFetchBarrierEXT();
395 mWorkDoneSinceLastFlush = true;
396 }
397
bindWorkerContext(std::string * infoLog)398 bool RendererGL::bindWorkerContext(std::string *infoLog)
399 {
400 if (mFeatures.disableWorkerContexts.enabled)
401 {
402 return false;
403 }
404
405 std::lock_guard<std::mutex> lock(mWorkerMutex);
406 std::unique_ptr<WorkerContext> workerContext;
407 if (!mWorkerContextPool.empty())
408 {
409 auto it = mWorkerContextPool.begin();
410 workerContext = std::move(*it);
411 mWorkerContextPool.erase(it);
412 }
413 else
414 {
415 WorkerContext *newContext = createWorkerContext(infoLog);
416 if (newContext == nullptr)
417 {
418 return false;
419 }
420 workerContext.reset(newContext);
421 }
422
423 if (!workerContext->makeCurrent())
424 {
425 mWorkerContextPool.push_back(std::move(workerContext));
426 return false;
427 }
428 mCurrentWorkerContexts[angle::GetCurrentThreadUniqueId()] = std::move(workerContext);
429 return true;
430 }
431
unbindWorkerContext()432 void RendererGL::unbindWorkerContext()
433 {
434 std::lock_guard<std::mutex> lock(mWorkerMutex);
435
436 auto it = mCurrentWorkerContexts.find(angle::GetCurrentThreadUniqueId());
437 ASSERT(it != mCurrentWorkerContexts.end());
438 (*it).second->unmakeCurrent();
439 mWorkerContextPool.push_back(std::move((*it).second));
440 mCurrentWorkerContexts.erase(it);
441 }
442
getMaxWorkerContexts()443 unsigned int RendererGL::getMaxWorkerContexts()
444 {
445 // No more than 16 worker contexts.
446 return std::min(16u, std::thread::hardware_concurrency());
447 }
448
hasNativeParallelCompile()449 bool RendererGL::hasNativeParallelCompile()
450 {
451 if (mFeatures.disableNativeParallelCompile.enabled)
452 {
453 return false;
454 }
455 return mFunctions->maxShaderCompilerThreadsKHR != nullptr ||
456 mFunctions->maxShaderCompilerThreadsARB != nullptr;
457 }
458
setMaxShaderCompilerThreads(GLuint count)459 void RendererGL::setMaxShaderCompilerThreads(GLuint count)
460 {
461 if (hasNativeParallelCompile())
462 {
463 SetMaxShaderCompilerThreads(mFunctions.get(), count);
464 }
465 }
466
setNeedsFlushBeforeDeleteTextures()467 void RendererGL::setNeedsFlushBeforeDeleteTextures()
468 {
469 mNeedsFlushBeforeDeleteTextures = true;
470 }
471
markWorkSubmitted()472 void RendererGL::markWorkSubmitted()
473 {
474 mWorkDoneSinceLastFlush = true;
475 }
476
flushIfNecessaryBeforeDeleteTextures()477 void RendererGL::flushIfNecessaryBeforeDeleteTextures()
478 {
479 if (mNeedsFlushBeforeDeleteTextures)
480 {
481 (void)flush();
482 }
483 }
484
ScopedWorkerContextGL(RendererGL * renderer,std::string * infoLog)485 ScopedWorkerContextGL::ScopedWorkerContextGL(RendererGL *renderer, std::string *infoLog)
486 : mRenderer(renderer)
487 {
488 mValid = mRenderer->bindWorkerContext(infoLog);
489 }
490
~ScopedWorkerContextGL()491 ScopedWorkerContextGL::~ScopedWorkerContextGL()
492 {
493 if (mValid)
494 {
495 mRenderer->unbindWorkerContext();
496 }
497 }
498
operator ()() const499 bool ScopedWorkerContextGL::operator()() const
500 {
501 return mValid;
502 }
503
handleGPUSwitch()504 void RendererGL::handleGPUSwitch()
505 {
506 nativegl_gl::ReInitializeFeaturesAtGPUSwitch(mFunctions.get(), &mFeatures);
507 }
508
509 } // namespace rx
510