• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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