• 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     ApplyFeatureOverrides(&mFeatures, display->getState().featureOverrides);
163     if (!display->getState().featureOverrides.allDisabled)
164     {
165         nativegl_gl::InitializeFeatures(mFunctions.get(), &mFeatures);
166     }
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 
flush()220 angle::Result RendererGL::flush()
221 {
222     if (!mWorkDoneSinceLastFlush && !mNeedsFlushBeforeDeleteTextures)
223     {
224         return angle::Result::Continue;
225     }
226 
227     mFunctions->flush();
228     mNeedsFlushBeforeDeleteTextures = false;
229     mWorkDoneSinceLastFlush         = false;
230     return angle::Result::Continue;
231 }
232 
finish()233 angle::Result RendererGL::finish()
234 {
235     if (mFeatures.finishDoesNotCauseQueriesToBeAvailable.enabled && mUseDebugOutput)
236     {
237         mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
238     }
239 
240     mFunctions->finish();
241     mNeedsFlushBeforeDeleteTextures = false;
242     mWorkDoneSinceLastFlush         = false;
243 
244     if (mFeatures.finishDoesNotCauseQueriesToBeAvailable.enabled && mUseDebugOutput)
245     {
246         mFunctions->disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
247     }
248 
249     return angle::Result::Continue;
250 }
251 
getResetStatus()252 gl::GraphicsResetStatus RendererGL::getResetStatus()
253 {
254     return gl::FromGLenum<gl::GraphicsResetStatus>(mFunctions->getGraphicsResetStatus());
255 }
256 
insertEventMarker(GLsizei length,const char * marker)257 void RendererGL::insertEventMarker(GLsizei length, const char *marker) {}
258 
pushGroupMarker(GLsizei length,const char * marker)259 void RendererGL::pushGroupMarker(GLsizei length, const char *marker) {}
260 
popGroupMarker()261 void RendererGL::popGroupMarker() {}
262 
pushDebugGroup(GLenum source,GLuint id,const std::string & message)263 void RendererGL::pushDebugGroup(GLenum source, GLuint id, const std::string &message) {}
264 
popDebugGroup()265 void RendererGL::popDebugGroup() {}
266 
getMaxSupportedESVersion() const267 const gl::Version &RendererGL::getMaxSupportedESVersion() const
268 {
269     // Force generation of caps
270     getNativeCaps();
271 
272     return mMaxSupportedESVersion;
273 }
274 
generateCaps(gl::Caps * outCaps,gl::TextureCapsMap * outTextureCaps,gl::Extensions * outExtensions,gl::Limitations * outLimitations) const275 void RendererGL::generateCaps(gl::Caps *outCaps,
276                               gl::TextureCapsMap *outTextureCaps,
277                               gl::Extensions *outExtensions,
278                               gl::Limitations *outLimitations) const
279 {
280     nativegl_gl::GenerateCaps(mFunctions.get(), mFeatures, outCaps, outTextureCaps, outExtensions,
281                               outLimitations, &mMaxSupportedESVersion,
282                               &mMultiviewImplementationType, &mNativePLSOptions);
283 }
284 
getGPUDisjoint()285 GLint RendererGL::getGPUDisjoint()
286 {
287     // TODO(ewell): On GLES backends we should find a way to reliably query disjoint events
288     return 0;
289 }
290 
getTimestamp()291 GLint64 RendererGL::getTimestamp()
292 {
293     GLint64 result = 0;
294     mFunctions->getInteger64v(GL_TIMESTAMP, &result);
295     return result;
296 }
297 
ensureCapsInitialized() const298 void RendererGL::ensureCapsInitialized() const
299 {
300     if (!mCapsInitialized)
301     {
302         generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
303         mCapsInitialized = true;
304     }
305 }
306 
getNativeCaps() const307 const gl::Caps &RendererGL::getNativeCaps() const
308 {
309     ensureCapsInitialized();
310     return mNativeCaps;
311 }
312 
getNativeTextureCaps() const313 const gl::TextureCapsMap &RendererGL::getNativeTextureCaps() const
314 {
315     ensureCapsInitialized();
316     return mNativeTextureCaps;
317 }
318 
getNativeExtensions() const319 const gl::Extensions &RendererGL::getNativeExtensions() const
320 {
321     ensureCapsInitialized();
322     return mNativeExtensions;
323 }
324 
getNativeLimitations() const325 const gl::Limitations &RendererGL::getNativeLimitations() const
326 {
327     ensureCapsInitialized();
328     return mNativeLimitations;
329 }
330 
getNativePixelLocalStorageOptions() const331 const ShPixelLocalStorageOptions &RendererGL::getNativePixelLocalStorageOptions() const
332 {
333     return mNativePLSOptions;
334 }
335 
getPLSProgramCache()336 PLSProgramCache *RendererGL::getPLSProgramCache()
337 {
338     if (!mPLSProgramCache)
339     {
340         mPLSProgramCache = new PLSProgramCache(mFunctions.get(), mNativeCaps);
341     }
342     return mPLSProgramCache;
343 }
344 
getMultiviewImplementationType() const345 MultiviewImplementationTypeGL RendererGL::getMultiviewImplementationType() const
346 {
347     ensureCapsInitialized();
348     return mMultiviewImplementationType;
349 }
350 
initializeFrontendFeatures(angle::FrontendFeatures * features) const351 void RendererGL::initializeFrontendFeatures(angle::FrontendFeatures *features) const
352 {
353     ensureCapsInitialized();
354     nativegl_gl::InitializeFrontendFeatures(mFunctions.get(), features);
355 }
356 
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)357 angle::Result RendererGL::dispatchCompute(const gl::Context *context,
358                                           GLuint numGroupsX,
359                                           GLuint numGroupsY,
360                                           GLuint numGroupsZ)
361 {
362     mFunctions->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
363     mWorkDoneSinceLastFlush = true;
364     return angle::Result::Continue;
365 }
366 
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)367 angle::Result RendererGL::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
368 {
369     mFunctions->dispatchComputeIndirect(indirect);
370     mWorkDoneSinceLastFlush = true;
371     return angle::Result::Continue;
372 }
373 
memoryBarrier(GLbitfield barriers)374 angle::Result RendererGL::memoryBarrier(GLbitfield barriers)
375 {
376     mFunctions->memoryBarrier(barriers);
377     mWorkDoneSinceLastFlush = true;
378     return angle::Result::Continue;
379 }
memoryBarrierByRegion(GLbitfield barriers)380 angle::Result RendererGL::memoryBarrierByRegion(GLbitfield barriers)
381 {
382     mFunctions->memoryBarrierByRegion(barriers);
383     mWorkDoneSinceLastFlush = true;
384     return angle::Result::Continue;
385 }
386 
framebufferFetchBarrier()387 void RendererGL::framebufferFetchBarrier()
388 {
389     mFunctions->framebufferFetchBarrierEXT();
390     mWorkDoneSinceLastFlush = true;
391 }
392 
hasNativeParallelCompile()393 bool RendererGL::hasNativeParallelCompile()
394 {
395     if (mFeatures.disableNativeParallelCompile.enabled)
396     {
397         return false;
398     }
399     return mFunctions->maxShaderCompilerThreadsKHR != nullptr ||
400            mFunctions->maxShaderCompilerThreadsARB != nullptr;
401 }
402 
setMaxShaderCompilerThreads(GLuint count)403 void RendererGL::setMaxShaderCompilerThreads(GLuint count)
404 {
405     if (hasNativeParallelCompile())
406     {
407         SetMaxShaderCompilerThreads(mFunctions.get(), count);
408     }
409 }
410 
setNeedsFlushBeforeDeleteTextures()411 void RendererGL::setNeedsFlushBeforeDeleteTextures()
412 {
413     mNeedsFlushBeforeDeleteTextures = true;
414 }
415 
markWorkSubmitted()416 void RendererGL::markWorkSubmitted()
417 {
418     mWorkDoneSinceLastFlush = true;
419 }
420 
flushIfNecessaryBeforeDeleteTextures()421 void RendererGL::flushIfNecessaryBeforeDeleteTextures()
422 {
423     if (mNeedsFlushBeforeDeleteTextures)
424     {
425         (void)flush();
426     }
427 }
428 
handleGPUSwitch()429 void RendererGL::handleGPUSwitch()
430 {
431     nativegl_gl::ReInitializeFeaturesAtGPUSwitch(mFunctions.get(), &mFeatures);
432 }
433 
434 }  // namespace rx
435