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/ProgramGL.h"
31 #include "libANGLE/renderer/gl/QueryGL.h"
32 #include "libANGLE/renderer/gl/RenderbufferGL.h"
33 #include "libANGLE/renderer/gl/SamplerGL.h"
34 #include "libANGLE/renderer/gl/ShaderGL.h"
35 #include "libANGLE/renderer/gl/StateManagerGL.h"
36 #include "libANGLE/renderer/gl/SurfaceGL.h"
37 #include "libANGLE/renderer/gl/SyncGL.h"
38 #include "libANGLE/renderer/gl/TextureGL.h"
39 #include "libANGLE/renderer/gl/TransformFeedbackGL.h"
40 #include "libANGLE/renderer/gl/VertexArrayGL.h"
41 #include "libANGLE/renderer/gl/renderergl_utils.h"
42 #include "libANGLE/renderer/renderer_utils.h"
43
44 namespace
45 {
46
SetMaxShaderCompilerThreads(const rx::FunctionsGL * functions,GLuint count)47 void SetMaxShaderCompilerThreads(const rx::FunctionsGL *functions, GLuint count)
48 {
49 if (functions->maxShaderCompilerThreadsKHR != nullptr)
50 {
51 functions->maxShaderCompilerThreadsKHR(count);
52 }
53 else
54 {
55 ASSERT(functions->maxShaderCompilerThreadsARB != nullptr);
56 functions->maxShaderCompilerThreadsARB(count);
57 }
58 }
59
60 #if defined(ANGLE_PLATFORM_ANDROID)
61 const char *kIgnoredErrors[] = {
62 // Wrong error message on Android Q Pixel 2. http://anglebug.com/42262155
63 "FreeAllocationOnTimestamp - Reference to buffer created from "
64 "different context without a share list. Application failed to pass "
65 "share_context to eglCreateContext. Results are undefined.",
66 // http://crbug.com/1348684
67 "UpdateTimestamp - Reference to buffer created from different context without a share list. "
68 "Application failed to pass share_context to eglCreateContext. Results are undefined.",
69 "Attempt to use resource over contexts without enabling context sharing. App must pass a "
70 "share_context to eglCreateContext() to share resources.",
71 };
72 #endif // defined(ANGLE_PLATFORM_ANDROID)
73
74 const char *kIgnoredWarnings[] = {
75 // We always request GL_ARB_gpu_shader5 and GL_EXT_gpu_shader5 when compiling shaders but some
76 // drivers warn when it is not present. This ends up spamming the console on every shader
77 // compile.
78 "extension `GL_ARB_gpu_shader5' unsupported in",
79 "extension `GL_EXT_gpu_shader5' unsupported in",
80 };
81
82 } // namespace
83
LogGLDebugMessage(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar * message,const void * userParam)84 static void INTERNAL_GL_APIENTRY LogGLDebugMessage(GLenum source,
85 GLenum type,
86 GLuint id,
87 GLenum severity,
88 GLsizei length,
89 const GLchar *message,
90 const void *userParam)
91 {
92 std::string sourceText = gl::GetDebugMessageSourceString(source);
93 std::string typeText = gl::GetDebugMessageTypeString(type);
94 std::string severityText = gl::GetDebugMessageSeverityString(severity);
95
96 #if defined(ANGLE_PLATFORM_ANDROID)
97 if (type == GL_DEBUG_TYPE_ERROR)
98 {
99 for (const char *&err : kIgnoredErrors)
100 {
101 if (strncmp(err, message, length) == 0)
102 {
103 // There is only one ignored message right now and it is quite spammy, around 3MB
104 // for a complete end2end tests run, so don't print it even as a warning.
105 return;
106 }
107 }
108 }
109 #endif // defined(ANGLE_PLATFORM_ANDROID)
110
111 if (type == GL_DEBUG_TYPE_ERROR)
112 {
113 ERR() << std::endl
114 << "\tSource: " << sourceText << std::endl
115 << "\tType: " << typeText << std::endl
116 << "\tID: " << gl::FmtHex(id) << std::endl
117 << "\tSeverity: " << severityText << std::endl
118 << "\tMessage: " << message;
119 }
120 else if (type != GL_DEBUG_TYPE_PERFORMANCE)
121 {
122 // Don't print performance warnings. They tend to be very spammy in the dEQP test suite and
123 // there is very little we can do about them.
124
125 for (const char *&warn : kIgnoredWarnings)
126 {
127 if (strstr(message, warn) != nullptr)
128 {
129 return;
130 }
131 }
132
133 // TODO(ynovikov): filter into WARN and INFO if INFO is ever implemented
134 WARN() << std::endl
135 << "\tSource: " << sourceText << std::endl
136 << "\tType: " << typeText << std::endl
137 << "\tID: " << gl::FmtHex(id) << std::endl
138 << "\tSeverity: " << severityText << std::endl
139 << "\tMessage: " << message;
140 }
141 }
142
143 namespace rx
144 {
145
RendererGL(std::unique_ptr<FunctionsGL> functions,const egl::AttributeMap & attribMap,DisplayGL * display)146 RendererGL::RendererGL(std::unique_ptr<FunctionsGL> functions,
147 const egl::AttributeMap &attribMap,
148 DisplayGL *display)
149 : mMaxSupportedESVersion(0, 0),
150 mFunctions(std::move(functions)),
151 mStateManager(nullptr),
152 mBlitter(nullptr),
153 mMultiviewClearer(nullptr),
154 mUseDebugOutput(false),
155 mCapsInitialized(false),
156 mMultiviewImplementationType(MultiviewImplementationTypeGL::UNSPECIFIED),
157 mNativeParallelCompileEnabled(false),
158 mNeedsFlushBeforeDeleteTextures(false)
159 {
160 ASSERT(mFunctions);
161 ApplyFeatureOverrides(&mFeatures, display->getState().featureOverrides);
162 if (!display->getState().featureOverrides.allDisabled)
163 {
164 nativegl_gl::InitializeFeatures(mFunctions.get(), &mFeatures);
165 }
166 mStateManager =
167 new StateManagerGL(mFunctions.get(), getNativeCaps(), getNativeExtensions(), mFeatures);
168 mBlitter = new BlitGL(mFunctions.get(), mFeatures, mStateManager);
169 mMultiviewClearer = new ClearMultiviewGL(mFunctions.get(), mStateManager);
170
171 bool hasDebugOutput = mFunctions->isAtLeastGL(gl::Version(4, 3)) ||
172 mFunctions->hasGLExtension("GL_KHR_debug") ||
173 mFunctions->isAtLeastGLES(gl::Version(3, 2)) ||
174 mFunctions->hasGLESExtension("GL_KHR_debug");
175
176 mUseDebugOutput = hasDebugOutput && ShouldUseDebugLayers(attribMap);
177
178 if (mUseDebugOutput)
179 {
180 mFunctions->enable(GL_DEBUG_OUTPUT);
181 mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
182 mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0,
183 nullptr, GL_TRUE);
184 mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0,
185 nullptr, GL_TRUE);
186 mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW, 0,
187 nullptr, GL_FALSE);
188 mFunctions->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION,
189 0, nullptr, GL_FALSE);
190 mFunctions->debugMessageCallback(&LogGLDebugMessage, nullptr);
191 }
192
193 if (mFeatures.initializeCurrentVertexAttributes.enabled)
194 {
195 GLint maxVertexAttribs = 0;
196 mFunctions->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs);
197
198 for (GLint i = 0; i < maxVertexAttribs; ++i)
199 {
200 mFunctions->vertexAttrib4f(i, 0.0f, 0.0f, 0.0f, 1.0f);
201 }
202 }
203
204 if (hasNativeParallelCompile() && !mNativeParallelCompileEnabled)
205 {
206 SetMaxShaderCompilerThreads(mFunctions.get(), 0xffffffff);
207 mNativeParallelCompileEnabled = true;
208 }
209 }
210
~RendererGL()211 RendererGL::~RendererGL()
212 {
213 SafeDelete(mBlitter);
214 SafeDelete(mMultiviewClearer);
215 SafeDelete(mStateManager);
216 }
217
flush()218 angle::Result RendererGL::flush()
219 {
220 if (!mWorkDoneSinceLastFlush && !mNeedsFlushBeforeDeleteTextures)
221 {
222 return angle::Result::Continue;
223 }
224
225 mFunctions->flush();
226 mNeedsFlushBeforeDeleteTextures = false;
227 mWorkDoneSinceLastFlush = false;
228 return angle::Result::Continue;
229 }
230
finish()231 angle::Result RendererGL::finish()
232 {
233 if (mFeatures.finishDoesNotCauseQueriesToBeAvailable.enabled && mUseDebugOutput)
234 {
235 mFunctions->enable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
236 }
237
238 mFunctions->finish();
239 mNeedsFlushBeforeDeleteTextures = false;
240 mWorkDoneSinceLastFlush = false;
241
242 if (mFeatures.finishDoesNotCauseQueriesToBeAvailable.enabled && mUseDebugOutput)
243 {
244 mFunctions->disable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
245 }
246
247 return angle::Result::Continue;
248 }
249
getResetStatus()250 gl::GraphicsResetStatus RendererGL::getResetStatus()
251 {
252 return gl::FromGLenum<gl::GraphicsResetStatus>(mFunctions->getGraphicsResetStatus());
253 }
254
insertEventMarker(GLsizei length,const char * marker)255 void RendererGL::insertEventMarker(GLsizei length, const char *marker) {}
256
pushGroupMarker(GLsizei length,const char * marker)257 void RendererGL::pushGroupMarker(GLsizei length, const char *marker) {}
258
popGroupMarker()259 void RendererGL::popGroupMarker() {}
260
pushDebugGroup(GLenum source,GLuint id,const std::string & message)261 void RendererGL::pushDebugGroup(GLenum source, GLuint id, const std::string &message) {}
262
popDebugGroup()263 void RendererGL::popDebugGroup() {}
264
getMaxSupportedESVersion() const265 const gl::Version &RendererGL::getMaxSupportedESVersion() const
266 {
267 // Force generation of caps
268 getNativeCaps();
269
270 return mMaxSupportedESVersion;
271 }
272
generateCaps(gl::Caps * outCaps,gl::TextureCapsMap * outTextureCaps,gl::Extensions * outExtensions,gl::Limitations * outLimitations) const273 void RendererGL::generateCaps(gl::Caps *outCaps,
274 gl::TextureCapsMap *outTextureCaps,
275 gl::Extensions *outExtensions,
276 gl::Limitations *outLimitations) const
277 {
278 nativegl_gl::GenerateCaps(mFunctions.get(), mFeatures, outCaps, outTextureCaps, outExtensions,
279 outLimitations, &mMaxSupportedESVersion,
280 &mMultiviewImplementationType, &mNativePLSOptions);
281 }
282
getGPUDisjoint()283 GLint RendererGL::getGPUDisjoint()
284 {
285 // TODO(ewell): On GLES backends we should find a way to reliably query disjoint events
286 return 0;
287 }
288
getTimestamp()289 GLint64 RendererGL::getTimestamp()
290 {
291 GLint64 result = 0;
292 mFunctions->getInteger64v(GL_TIMESTAMP, &result);
293 return result;
294 }
295
ensureCapsInitialized() const296 void RendererGL::ensureCapsInitialized() const
297 {
298 if (!mCapsInitialized)
299 {
300 generateCaps(&mNativeCaps, &mNativeTextureCaps, &mNativeExtensions, &mNativeLimitations);
301 mCapsInitialized = true;
302 }
303 }
304
getNativeCaps() const305 const gl::Caps &RendererGL::getNativeCaps() const
306 {
307 ensureCapsInitialized();
308 return mNativeCaps;
309 }
310
getNativeTextureCaps() const311 const gl::TextureCapsMap &RendererGL::getNativeTextureCaps() const
312 {
313 ensureCapsInitialized();
314 return mNativeTextureCaps;
315 }
316
getNativeExtensions() const317 const gl::Extensions &RendererGL::getNativeExtensions() const
318 {
319 ensureCapsInitialized();
320 return mNativeExtensions;
321 }
322
getNativeLimitations() const323 const gl::Limitations &RendererGL::getNativeLimitations() const
324 {
325 ensureCapsInitialized();
326 return mNativeLimitations;
327 }
328
getNativePixelLocalStorageOptions() const329 const ShPixelLocalStorageOptions &RendererGL::getNativePixelLocalStorageOptions() const
330 {
331 return mNativePLSOptions;
332 }
333
getMultiviewImplementationType() const334 MultiviewImplementationTypeGL RendererGL::getMultiviewImplementationType() const
335 {
336 ensureCapsInitialized();
337 return mMultiviewImplementationType;
338 }
339
initializeFrontendFeatures(angle::FrontendFeatures * features) const340 void RendererGL::initializeFrontendFeatures(angle::FrontendFeatures *features) const
341 {
342 ensureCapsInitialized();
343 nativegl_gl::InitializeFrontendFeatures(mFunctions.get(), features);
344 }
345
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)346 angle::Result RendererGL::dispatchCompute(const gl::Context *context,
347 GLuint numGroupsX,
348 GLuint numGroupsY,
349 GLuint numGroupsZ)
350 {
351 mFunctions->dispatchCompute(numGroupsX, numGroupsY, numGroupsZ);
352 mWorkDoneSinceLastFlush = true;
353 return angle::Result::Continue;
354 }
355
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)356 angle::Result RendererGL::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
357 {
358 mFunctions->dispatchComputeIndirect(indirect);
359 mWorkDoneSinceLastFlush = true;
360 return angle::Result::Continue;
361 }
362
memoryBarrier(GLbitfield barriers)363 angle::Result RendererGL::memoryBarrier(GLbitfield barriers)
364 {
365 mFunctions->memoryBarrier(barriers);
366 mWorkDoneSinceLastFlush = true;
367 return angle::Result::Continue;
368 }
memoryBarrierByRegion(GLbitfield barriers)369 angle::Result RendererGL::memoryBarrierByRegion(GLbitfield barriers)
370 {
371 mFunctions->memoryBarrierByRegion(barriers);
372 mWorkDoneSinceLastFlush = true;
373 return angle::Result::Continue;
374 }
375
framebufferFetchBarrier()376 void RendererGL::framebufferFetchBarrier()
377 {
378 mFunctions->framebufferFetchBarrierEXT();
379 mWorkDoneSinceLastFlush = true;
380 }
381
hasNativeParallelCompile()382 bool RendererGL::hasNativeParallelCompile()
383 {
384 if (mFeatures.disableNativeParallelCompile.enabled)
385 {
386 return false;
387 }
388 return mFunctions->maxShaderCompilerThreadsKHR != nullptr ||
389 mFunctions->maxShaderCompilerThreadsARB != nullptr;
390 }
391
setMaxShaderCompilerThreads(GLuint count)392 void RendererGL::setMaxShaderCompilerThreads(GLuint count)
393 {
394 if (hasNativeParallelCompile())
395 {
396 SetMaxShaderCompilerThreads(mFunctions.get(), count);
397 }
398 }
399
setNeedsFlushBeforeDeleteTextures()400 void RendererGL::setNeedsFlushBeforeDeleteTextures()
401 {
402 mNeedsFlushBeforeDeleteTextures = true;
403 }
404
markWorkSubmitted()405 void RendererGL::markWorkSubmitted()
406 {
407 mWorkDoneSinceLastFlush = true;
408 }
409
flushIfNecessaryBeforeDeleteTextures()410 void RendererGL::flushIfNecessaryBeforeDeleteTextures()
411 {
412 if (mNeedsFlushBeforeDeleteTextures)
413 {
414 (void)flush();
415 }
416 }
417
handleGPUSwitch()418 void RendererGL::handleGPUSwitch()
419 {
420 nativegl_gl::ReInitializeFeaturesAtGPUSwitch(mFunctions.get(), &mFeatures);
421 }
422
423 } // namespace rx
424