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