• 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 // 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