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 // ShaderGL.cpp: Implements the class methods for ShaderGL.
8
9 #include "libANGLE/renderer/gl/ShaderGL.h"
10
11 #include "common/debug.h"
12 #include "libANGLE/Compiler.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/renderer/ContextImpl.h"
15 #include "libANGLE/renderer/gl/FunctionsGL.h"
16 #include "libANGLE/renderer/gl/RendererGL.h"
17 #include "libANGLE/trace.h"
18 #include "platform/autogen/FeaturesGL_autogen.h"
19
20 #include <iostream>
21
22 namespace rx
23 {
24
25 using CompileAndCheckShaderInWorkerFunctor = std::function<bool(const char *source)>;
26 class TranslateTaskGL : public angle::Closure
27 {
28 public:
TranslateTaskGL(ShHandle handle,const ShCompileOptions & options,const std::string & source,CompileAndCheckShaderInWorkerFunctor && compileAndCheckShaderInWorkerFunctor)29 TranslateTaskGL(ShHandle handle,
30 const ShCompileOptions &options,
31 const std::string &source,
32 CompileAndCheckShaderInWorkerFunctor &&compileAndCheckShaderInWorkerFunctor)
33 : mHandle(handle),
34 mOptions(options),
35 mSource(source),
36 mCompileAndCheckShaderInWorkerFunctor(std::move(compileAndCheckShaderInWorkerFunctor)),
37 mResult(false),
38 mWorkerAvailable(true)
39 {}
40
operator ()()41 void operator()() override
42 {
43 ANGLE_TRACE_EVENT1("gpu.angle", "TranslateTaskGL::run", "source", mSource);
44 const char *source = mSource.c_str();
45 mResult = sh::Compile(mHandle, &source, 1, mOptions);
46 if (mResult)
47 {
48 mWorkerAvailable =
49 mCompileAndCheckShaderInWorkerFunctor(sh::GetObjectCode(mHandle).c_str());
50 }
51 }
52
getResult()53 bool getResult() { return mResult; }
54
workerAvailable()55 bool workerAvailable() { return mWorkerAvailable; }
56
getHandle()57 ShHandle getHandle() { return mHandle; }
58
59 private:
60 ShHandle mHandle;
61 ShCompileOptions mOptions;
62 std::string mSource;
63 CompileAndCheckShaderInWorkerFunctor mCompileAndCheckShaderInWorkerFunctor;
64 bool mResult;
65 bool mWorkerAvailable;
66 };
67
68 using PostTranslateFunctor = std::function<bool(std::string *infoLog)>;
69 using CompileAndCheckShaderFunctor = std::function<void(const char *source)>;
70 class WaitableCompileEventWorkerContext final : public WaitableCompileEvent
71 {
72 public:
WaitableCompileEventWorkerContext(std::shared_ptr<angle::WaitableEvent> waitableEvent,CompileAndCheckShaderFunctor && compileAndCheckShaderFunctor,PostTranslateFunctor && postTranslateFunctor,std::shared_ptr<TranslateTaskGL> translateTask)73 WaitableCompileEventWorkerContext(std::shared_ptr<angle::WaitableEvent> waitableEvent,
74 CompileAndCheckShaderFunctor &&compileAndCheckShaderFunctor,
75 PostTranslateFunctor &&postTranslateFunctor,
76 std::shared_ptr<TranslateTaskGL> translateTask)
77 : WaitableCompileEvent(waitableEvent),
78 mCompileAndCheckShaderFunctor(std::move(compileAndCheckShaderFunctor)),
79 mPostTranslateFunctor(std::move(postTranslateFunctor)),
80 mTranslateTask(translateTask)
81 {}
82
getResult()83 bool getResult() override { return mTranslateTask->getResult(); }
84
postTranslate(std::string * infoLog)85 bool postTranslate(std::string *infoLog) override
86 {
87 if (!mTranslateTask->workerAvailable())
88 {
89 ShHandle handle = mTranslateTask->getHandle();
90 mCompileAndCheckShaderFunctor(sh::GetObjectCode(handle).c_str());
91 }
92 return mPostTranslateFunctor(infoLog);
93 }
94
95 private:
96 CompileAndCheckShaderFunctor mCompileAndCheckShaderFunctor;
97 PostTranslateFunctor mPostTranslateFunctor;
98 std::shared_ptr<TranslateTaskGL> mTranslateTask;
99 };
100
101 using PeekCompletionFunctor = std::function<bool()>;
102 using CheckShaderFunctor = std::function<void()>;
103
104 class WaitableCompileEventNativeParallel final : public WaitableCompileEvent
105 {
106 public:
WaitableCompileEventNativeParallel(PostTranslateFunctor && postTranslateFunctor,bool result,CheckShaderFunctor && checkShaderFunctor,PeekCompletionFunctor && peekCompletionFunctor)107 WaitableCompileEventNativeParallel(PostTranslateFunctor &&postTranslateFunctor,
108 bool result,
109 CheckShaderFunctor &&checkShaderFunctor,
110 PeekCompletionFunctor &&peekCompletionFunctor)
111 : WaitableCompileEvent(std::shared_ptr<angle::WaitableEventDone>()),
112 mPostTranslateFunctor(std::move(postTranslateFunctor)),
113 mResult(result),
114 mCheckShaderFunctor(std::move(checkShaderFunctor)),
115 mPeekCompletionFunctor(std::move(peekCompletionFunctor))
116 {}
117
wait()118 void wait() override { mCheckShaderFunctor(); }
119
isReady()120 bool isReady() override { return mPeekCompletionFunctor(); }
121
getResult()122 bool getResult() override { return mResult; }
123
postTranslate(std::string * infoLog)124 bool postTranslate(std::string *infoLog) override { return mPostTranslateFunctor(infoLog); }
125
126 private:
127 PostTranslateFunctor mPostTranslateFunctor;
128 bool mResult;
129 CheckShaderFunctor mCheckShaderFunctor;
130 PeekCompletionFunctor mPeekCompletionFunctor;
131 };
132
133 class WaitableCompileEventDone final : public WaitableCompileEvent
134 {
135 public:
WaitableCompileEventDone(PostTranslateFunctor && postTranslateFunctor,bool result)136 WaitableCompileEventDone(PostTranslateFunctor &&postTranslateFunctor, bool result)
137 : WaitableCompileEvent(std::make_shared<angle::WaitableEventDone>()),
138 mPostTranslateFunctor(std::move(postTranslateFunctor)),
139 mResult(result)
140 {}
141
getResult()142 bool getResult() override { return mResult; }
143
postTranslate(std::string * infoLog)144 bool postTranslate(std::string *infoLog) override { return mPostTranslateFunctor(infoLog); }
145
146 private:
147 PostTranslateFunctor mPostTranslateFunctor;
148 bool mResult;
149 };
150
ShaderGL(const gl::ShaderState & data,GLuint shaderID,MultiviewImplementationTypeGL multiviewImplementationType,const std::shared_ptr<RendererGL> & renderer)151 ShaderGL::ShaderGL(const gl::ShaderState &data,
152 GLuint shaderID,
153 MultiviewImplementationTypeGL multiviewImplementationType,
154 const std::shared_ptr<RendererGL> &renderer)
155 : ShaderImpl(data),
156 mShaderID(shaderID),
157 mMultiviewImplementationType(multiviewImplementationType),
158 mRenderer(renderer),
159 mCompileStatus(GL_FALSE)
160 {}
161
~ShaderGL()162 ShaderGL::~ShaderGL()
163 {
164 ASSERT(mShaderID == 0);
165 }
166
destroy()167 void ShaderGL::destroy()
168 {
169 mRenderer->getFunctions()->deleteShader(mShaderID);
170 mShaderID = 0;
171 }
172
compileAndCheckShader(const char * source)173 void ShaderGL::compileAndCheckShader(const char *source)
174 {
175 compileShader(source);
176 checkShader();
177 }
178
compileShader(const char * source)179 void ShaderGL::compileShader(const char *source)
180 {
181 const FunctionsGL *functions = mRenderer->getFunctions();
182 functions->shaderSource(mShaderID, 1, &source, nullptr);
183 functions->compileShader(mShaderID);
184 }
185
checkShader()186 void ShaderGL::checkShader()
187 {
188 const FunctionsGL *functions = mRenderer->getFunctions();
189
190 // Check for compile errors from the native driver
191 mCompileStatus = GL_FALSE;
192 functions->getShaderiv(mShaderID, GL_COMPILE_STATUS, &mCompileStatus);
193 if (mCompileStatus == GL_FALSE)
194 {
195 // Compilation failed, put the error into the info log
196 GLint infoLogLength = 0;
197 functions->getShaderiv(mShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
198
199 // Info log length includes the null terminator, so 1 means that the info log is an empty
200 // string.
201 if (infoLogLength > 1)
202 {
203 std::vector<char> buf(infoLogLength);
204 functions->getShaderInfoLog(mShaderID, infoLogLength, nullptr, &buf[0]);
205
206 mInfoLog += &buf[0];
207 WARN() << std::endl << mInfoLog;
208 }
209 else
210 {
211 WARN() << std::endl << "Shader compilation failed with no info log.";
212 }
213 }
214 }
215
peekCompletion()216 bool ShaderGL::peekCompletion()
217 {
218 const FunctionsGL *functions = mRenderer->getFunctions();
219 GLint status = GL_FALSE;
220 functions->getShaderiv(mShaderID, GL_COMPLETION_STATUS, &status);
221 return status == GL_TRUE;
222 }
223
compileAndCheckShaderInWorker(const char * source)224 bool ShaderGL::compileAndCheckShaderInWorker(const char *source)
225 {
226 std::string workerInfoLog;
227 ScopedWorkerContextGL worker(mRenderer.get(), &workerInfoLog);
228 if (worker())
229 {
230 compileAndCheckShader(source);
231 return true;
232 }
233 else
234 {
235 #if !defined(NDEBUG)
236 mInfoLog += "bindWorkerContext failed.\n" + workerInfoLog;
237 #endif
238 return false;
239 }
240 }
241
compile(const gl::Context * context,gl::ShCompilerInstance * compilerInstance,ShCompileOptions * options)242 std::shared_ptr<WaitableCompileEvent> ShaderGL::compile(const gl::Context *context,
243 gl::ShCompilerInstance *compilerInstance,
244 ShCompileOptions *options)
245 {
246 mInfoLog.clear();
247
248 options->initGLPosition = true;
249
250 bool isWebGL = context->isWebGL();
251 if (isWebGL && mState.getShaderType() != gl::ShaderType::Compute)
252 {
253 options->initOutputVariables = true;
254 }
255
256 if (isWebGL && !context->getState().getEnableFeature(GL_TEXTURE_RECTANGLE_ANGLE))
257 {
258 options->disableARBTextureRectangle = true;
259 }
260
261 const angle::FeaturesGL &features = GetFeaturesGL(context);
262
263 if (features.initFragmentOutputVariables.enabled)
264 {
265 options->initFragmentOutputVariables = true;
266 }
267
268 if (features.doWhileGLSLCausesGPUHang.enabled)
269 {
270 options->rewriteDoWhileLoops = true;
271 }
272
273 if (features.emulateAbsIntFunction.enabled)
274 {
275 options->emulateAbsIntFunction = true;
276 }
277
278 if (features.addAndTrueToLoopCondition.enabled)
279 {
280 options->addAndTrueToLoopCondition = true;
281 }
282
283 if (features.emulateIsnanFloat.enabled)
284 {
285 options->emulateIsnanFloatFunction = true;
286 }
287
288 if (features.emulateAtan2Float.enabled)
289 {
290 options->emulateAtan2FloatFunction = true;
291 }
292
293 if (features.useUnusedBlocksWithStandardOrSharedLayout.enabled)
294 {
295 options->useUnusedStandardSharedBlocks = true;
296 }
297
298 if (features.removeInvariantAndCentroidForESSL3.enabled)
299 {
300 options->removeInvariantAndCentroidForESSL3 = true;
301 }
302
303 if (features.rewriteFloatUnaryMinusOperator.enabled)
304 {
305 options->rewriteFloatUnaryMinusOperator = true;
306 }
307
308 if (!features.dontInitializeUninitializedLocals.enabled)
309 {
310 options->initializeUninitializedLocals = true;
311 }
312
313 if (features.clampPointSize.enabled)
314 {
315 options->clampPointSize = true;
316 }
317
318 if (features.dontUseLoopsToInitializeVariables.enabled)
319 {
320 options->dontUseLoopsToInitializeVariables = true;
321 }
322
323 if (features.clampFragDepth.enabled)
324 {
325 options->clampFragDepth = true;
326 }
327
328 if (features.rewriteRepeatedAssignToSwizzled.enabled)
329 {
330 options->rewriteRepeatedAssignToSwizzled = true;
331 }
332
333 if (mMultiviewImplementationType == MultiviewImplementationTypeGL::NV_VIEWPORT_ARRAY2)
334 {
335 options->initializeBuiltinsForInstancedMultiview = true;
336 options->selectViewInNvGLSLVertexShader = true;
337 }
338
339 if (features.clampArrayAccess.enabled || isWebGL)
340 {
341 options->clampIndirectArrayBounds = true;
342 }
343
344 if (features.vertexIDDoesNotIncludeBaseVertex.enabled)
345 {
346 options->addBaseVertexToVertexID = true;
347 }
348
349 if (features.unfoldShortCircuits.enabled)
350 {
351 options->unfoldShortCircuit = true;
352 }
353
354 if (features.removeDynamicIndexingOfSwizzledVector.enabled)
355 {
356 options->removeDynamicIndexingOfSwizzledVector = true;
357 }
358
359 if (features.preAddTexelFetchOffsets.enabled)
360 {
361 options->rewriteTexelFetchOffsetToTexelFetch = true;
362 }
363
364 if (features.regenerateStructNames.enabled)
365 {
366 options->regenerateStructNames = true;
367 }
368
369 if (features.rewriteRowMajorMatrices.enabled)
370 {
371 options->rewriteRowMajorMatrices = true;
372 }
373
374 if (features.passHighpToPackUnormSnormBuiltins.enabled)
375 {
376 options->passHighpToPackUnormSnormBuiltins = true;
377 }
378
379 if (features.emulateClipDistanceState.enabled)
380 {
381 options->emulateClipDistanceState = true;
382 }
383
384 if (features.scalarizeVecAndMatConstructorArgs.enabled)
385 {
386 options->scalarizeVecAndMatConstructorArgs = true;
387 }
388
389 if (mRenderer->getNativeExtensions().shaderPixelLocalStorageANGLE)
390 {
391 options->pls = mRenderer->getNativePixelLocalStorageOptions();
392 }
393
394 auto workerThreadPool = context->getShaderCompileThreadPool();
395
396 const std::string &source = mState.getSource();
397
398 auto postTranslateFunctor = [this](std::string *infoLog) {
399 if (mCompileStatus == GL_FALSE)
400 {
401 *infoLog = mInfoLog;
402 return false;
403 }
404 return true;
405 };
406
407 if (mRenderer->hasNativeParallelCompile())
408 {
409 ShHandle handle = compilerInstance->getHandle();
410 const char *str = source.c_str();
411 bool result = sh::Compile(handle, &str, 1, *options);
412 if (result)
413 {
414 compileShader(sh::GetObjectCode(handle).c_str());
415 auto checkShaderFunctor = [this]() { checkShader(); };
416 auto peekCompletionFunctor = [this]() { return peekCompletion(); };
417 return std::make_shared<WaitableCompileEventNativeParallel>(
418 std::move(postTranslateFunctor), result, std::move(checkShaderFunctor),
419 std::move(peekCompletionFunctor));
420 }
421 else
422 {
423 return std::make_shared<WaitableCompileEventDone>([](std::string *) { return true; },
424 result);
425 }
426 }
427 else if (workerThreadPool->isAsync())
428 {
429 auto compileAndCheckShaderInWorkerFunctor = [this](const char *source) {
430 return compileAndCheckShaderInWorker(source);
431 };
432 auto translateTask =
433 std::make_shared<TranslateTaskGL>(compilerInstance->getHandle(), *options, source,
434 std::move(compileAndCheckShaderInWorkerFunctor));
435
436 auto compileAndCheckShaderFunctor = [this](const char *source) {
437 compileAndCheckShader(source);
438 };
439 return std::make_shared<WaitableCompileEventWorkerContext>(
440 workerThreadPool->postWorkerTask(translateTask),
441 std::move(compileAndCheckShaderFunctor), std::move(postTranslateFunctor),
442 translateTask);
443 }
444 else
445 {
446 ShHandle handle = compilerInstance->getHandle();
447 const char *str = source.c_str();
448 bool result = sh::Compile(handle, &str, 1, *options);
449 if (result)
450 {
451 compileAndCheckShader(sh::GetObjectCode(handle).c_str());
452 }
453 return std::make_shared<WaitableCompileEventDone>(std::move(postTranslateFunctor), result);
454 }
455 }
456
getDebugInfo() const457 std::string ShaderGL::getDebugInfo() const
458 {
459 return mState.getTranslatedSource();
460 }
461
getShaderID() const462 GLuint ShaderGL::getShaderID() const
463 {
464 return mShaderID;
465 }
466
467 } // namespace rx
468