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