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