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