xref: /aosp_15_r20/external/angle/src/libANGLE/Shader.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker // Shader.cpp: Implements the gl::Shader class and its  derived classes
8*8975f5c5SAndroid Build Coastguard Worker // VertexShader and FragmentShader. Implements GL shader objects and related
9*8975f5c5SAndroid Build Coastguard Worker // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Shader.h"
12*8975f5c5SAndroid Build Coastguard Worker 
13*8975f5c5SAndroid Build Coastguard Worker #include <functional>
14*8975f5c5SAndroid Build Coastguard Worker #include <sstream>
15*8975f5c5SAndroid Build Coastguard Worker 
16*8975f5c5SAndroid Build Coastguard Worker #include "GLSLANG/ShaderLang.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "common/angle_version_info.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "common/string_utils.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "common/system_utils.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Caps.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Compiler.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Constants.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
25*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Display.h"
26*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/MemoryShaderCache.h"
27*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Program.h"
28*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ResourceManager.h"
29*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/GLImplFactory.h"
30*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ShaderImpl.h"
31*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/trace.h"
32*8975f5c5SAndroid Build Coastguard Worker #include "platform/autogen/FrontendFeatures_autogen.h"
33*8975f5c5SAndroid Build Coastguard Worker 
34*8975f5c5SAndroid Build Coastguard Worker namespace gl
35*8975f5c5SAndroid Build Coastguard Worker {
36*8975f5c5SAndroid Build Coastguard Worker 
37*8975f5c5SAndroid Build Coastguard Worker namespace
38*8975f5c5SAndroid Build Coastguard Worker {
39*8975f5c5SAndroid Build Coastguard Worker constexpr uint32_t kShaderCacheIdentifier = 0x12345678;
40*8975f5c5SAndroid Build Coastguard Worker 
41*8975f5c5SAndroid Build Coastguard Worker // Environment variable (and associated Android property) for the path to read and write shader
42*8975f5c5SAndroid Build Coastguard Worker // dumps
43*8975f5c5SAndroid Build Coastguard Worker constexpr char kShaderDumpPathVarName[]       = "ANGLE_SHADER_DUMP_PATH";
44*8975f5c5SAndroid Build Coastguard Worker constexpr char kEShaderDumpPathPropertyName[] = "debug.angle.shader_dump_path";
45*8975f5c5SAndroid Build Coastguard Worker 
ComputeShaderHash(const std::string & mergedSource)46*8975f5c5SAndroid Build Coastguard Worker size_t ComputeShaderHash(const std::string &mergedSource)
47*8975f5c5SAndroid Build Coastguard Worker {
48*8975f5c5SAndroid Build Coastguard Worker     return std::hash<std::string>{}(mergedSource);
49*8975f5c5SAndroid Build Coastguard Worker }
50*8975f5c5SAndroid Build Coastguard Worker 
GetShaderDumpFilePath(size_t shaderHash,const char * suffix)51*8975f5c5SAndroid Build Coastguard Worker std::string GetShaderDumpFilePath(size_t shaderHash, const char *suffix)
52*8975f5c5SAndroid Build Coastguard Worker {
53*8975f5c5SAndroid Build Coastguard Worker     std::stringstream path;
54*8975f5c5SAndroid Build Coastguard Worker     std::string shaderDumpDir = GetShaderDumpFileDirectory();
55*8975f5c5SAndroid Build Coastguard Worker     if (!shaderDumpDir.empty())
56*8975f5c5SAndroid Build Coastguard Worker     {
57*8975f5c5SAndroid Build Coastguard Worker         path << shaderDumpDir << "/";
58*8975f5c5SAndroid Build Coastguard Worker     }
59*8975f5c5SAndroid Build Coastguard Worker     path << shaderHash << "." << suffix;
60*8975f5c5SAndroid Build Coastguard Worker 
61*8975f5c5SAndroid Build Coastguard Worker     return path.str();
62*8975f5c5SAndroid Build Coastguard Worker }
63*8975f5c5SAndroid Build Coastguard Worker 
64*8975f5c5SAndroid Build Coastguard Worker class CompileTask final : public angle::Closure
65*8975f5c5SAndroid Build Coastguard Worker {
66*8975f5c5SAndroid Build Coastguard Worker   public:
67*8975f5c5SAndroid Build Coastguard Worker     // Translate and compile
CompileTask(const angle::FrontendFeatures & frontendFeatures,ShHandle compilerHandle,ShShaderOutput outputType,const ShCompileOptions & options,const std::string & source,size_t sourceHash,const SharedCompiledShaderState & compiledState,size_t maxComputeWorkGroupInvocations,size_t maxComputeSharedMemory,std::shared_ptr<rx::ShaderTranslateTask> && translateTask)68*8975f5c5SAndroid Build Coastguard Worker     CompileTask(const angle::FrontendFeatures &frontendFeatures,
69*8975f5c5SAndroid Build Coastguard Worker                 ShHandle compilerHandle,
70*8975f5c5SAndroid Build Coastguard Worker                 ShShaderOutput outputType,
71*8975f5c5SAndroid Build Coastguard Worker                 const ShCompileOptions &options,
72*8975f5c5SAndroid Build Coastguard Worker                 const std::string &source,
73*8975f5c5SAndroid Build Coastguard Worker                 size_t sourceHash,
74*8975f5c5SAndroid Build Coastguard Worker                 const SharedCompiledShaderState &compiledState,
75*8975f5c5SAndroid Build Coastguard Worker                 size_t maxComputeWorkGroupInvocations,
76*8975f5c5SAndroid Build Coastguard Worker                 size_t maxComputeSharedMemory,
77*8975f5c5SAndroid Build Coastguard Worker                 std::shared_ptr<rx::ShaderTranslateTask> &&translateTask)
78*8975f5c5SAndroid Build Coastguard Worker         : mFrontendFeatures(frontendFeatures),
79*8975f5c5SAndroid Build Coastguard Worker           mMaxComputeWorkGroupInvocations(maxComputeWorkGroupInvocations),
80*8975f5c5SAndroid Build Coastguard Worker           mMaxComputeSharedMemory(maxComputeSharedMemory),
81*8975f5c5SAndroid Build Coastguard Worker           mCompilerHandle(compilerHandle),
82*8975f5c5SAndroid Build Coastguard Worker           mOutputType(outputType),
83*8975f5c5SAndroid Build Coastguard Worker           mOptions(options),
84*8975f5c5SAndroid Build Coastguard Worker           mSource(source),
85*8975f5c5SAndroid Build Coastguard Worker           mSourceHash(sourceHash),
86*8975f5c5SAndroid Build Coastguard Worker           mCompiledState(compiledState),
87*8975f5c5SAndroid Build Coastguard Worker           mTranslateTask(std::move(translateTask))
88*8975f5c5SAndroid Build Coastguard Worker     {}
89*8975f5c5SAndroid Build Coastguard Worker 
90*8975f5c5SAndroid Build Coastguard Worker     // Load from binary
CompileTask(const angle::FrontendFeatures & frontendFeatures,const SharedCompiledShaderState & compiledState,std::shared_ptr<rx::ShaderTranslateTask> && translateTask)91*8975f5c5SAndroid Build Coastguard Worker     CompileTask(const angle::FrontendFeatures &frontendFeatures,
92*8975f5c5SAndroid Build Coastguard Worker                 const SharedCompiledShaderState &compiledState,
93*8975f5c5SAndroid Build Coastguard Worker                 std::shared_ptr<rx::ShaderTranslateTask> &&translateTask)
94*8975f5c5SAndroid Build Coastguard Worker         : mFrontendFeatures(frontendFeatures),
95*8975f5c5SAndroid Build Coastguard Worker           mCompiledState(compiledState),
96*8975f5c5SAndroid Build Coastguard Worker           mTranslateTask(std::move(translateTask))
97*8975f5c5SAndroid Build Coastguard Worker     {}
98*8975f5c5SAndroid Build Coastguard Worker     ~CompileTask() override = default;
99*8975f5c5SAndroid Build Coastguard Worker 
operator ()()100*8975f5c5SAndroid Build Coastguard Worker     void operator()() override { mResult = compileImpl(); }
101*8975f5c5SAndroid Build Coastguard Worker 
getResult()102*8975f5c5SAndroid Build Coastguard Worker     angle::Result getResult()
103*8975f5c5SAndroid Build Coastguard Worker     {
104*8975f5c5SAndroid Build Coastguard Worker         // Note: this function is called from WaitCompileJobUnlocked(), and must therefore be
105*8975f5c5SAndroid Build Coastguard Worker         // thread-safe if the linkJobIsThreadSafe feature is enabled.  Without linkJobIsThreadSafe,
106*8975f5c5SAndroid Build Coastguard Worker         // the call will end up done in the main thread, which is the case for the GL backend (which
107*8975f5c5SAndroid Build Coastguard Worker         // happens to be the only backend that actually does anything in getResult).
108*8975f5c5SAndroid Build Coastguard Worker         //
109*8975f5c5SAndroid Build Coastguard Worker         // Consequently, this function must not _write_ to anything, e.g. by trying to cache the
110*8975f5c5SAndroid Build Coastguard Worker         // result of |mTranslateTask->getResult()|.
111*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mResult);
112*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRY(mTranslateTask->getResult(mInfoLog));
113*8975f5c5SAndroid Build Coastguard Worker 
114*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
115*8975f5c5SAndroid Build Coastguard Worker     }
116*8975f5c5SAndroid Build Coastguard Worker 
isCompilingInternally()117*8975f5c5SAndroid Build Coastguard Worker     bool isCompilingInternally() { return mTranslateTask->isCompilingInternally(); }
118*8975f5c5SAndroid Build Coastguard Worker 
getInfoLog()119*8975f5c5SAndroid Build Coastguard Worker     std::string &&getInfoLog() { return std::move(mInfoLog); }
120*8975f5c5SAndroid Build Coastguard Worker 
121*8975f5c5SAndroid Build Coastguard Worker   private:
122*8975f5c5SAndroid Build Coastguard Worker     angle::Result compileImpl();
123*8975f5c5SAndroid Build Coastguard Worker     angle::Result postTranslate();
124*8975f5c5SAndroid Build Coastguard Worker 
125*8975f5c5SAndroid Build Coastguard Worker     // Global constants that are safe to access by the worker thread
126*8975f5c5SAndroid Build Coastguard Worker     const angle::FrontendFeatures &mFrontendFeatures;
127*8975f5c5SAndroid Build Coastguard Worker     size_t mMaxComputeWorkGroupInvocations = 0;
128*8975f5c5SAndroid Build Coastguard Worker     size_t mMaxComputeSharedMemory         = 0;
129*8975f5c5SAndroid Build Coastguard Worker 
130*8975f5c5SAndroid Build Coastguard Worker     // Access to the compile information.  Note that the compiler instance is kept alive until
131*8975f5c5SAndroid Build Coastguard Worker     // resolveCompile.
132*8975f5c5SAndroid Build Coastguard Worker     ShHandle mCompilerHandle = 0;
133*8975f5c5SAndroid Build Coastguard Worker     ShShaderOutput mOutputType;
134*8975f5c5SAndroid Build Coastguard Worker     ShCompileOptions mOptions;
135*8975f5c5SAndroid Build Coastguard Worker     const std::string mSource;
136*8975f5c5SAndroid Build Coastguard Worker     size_t mSourceHash = 0;
137*8975f5c5SAndroid Build Coastguard Worker     SharedCompiledShaderState mCompiledState;
138*8975f5c5SAndroid Build Coastguard Worker 
139*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<rx::ShaderTranslateTask> mTranslateTask;
140*8975f5c5SAndroid Build Coastguard Worker     angle::Result mResult;
141*8975f5c5SAndroid Build Coastguard Worker     std::string mInfoLog;
142*8975f5c5SAndroid Build Coastguard Worker };
143*8975f5c5SAndroid Build Coastguard Worker 
144*8975f5c5SAndroid Build Coastguard Worker class CompileEvent final
145*8975f5c5SAndroid Build Coastguard Worker {
146*8975f5c5SAndroid Build Coastguard Worker   public:
CompileEvent(const std::shared_ptr<CompileTask> & compileTask,const std::shared_ptr<angle::WaitableEvent> & waitEvent)147*8975f5c5SAndroid Build Coastguard Worker     CompileEvent(const std::shared_ptr<CompileTask> &compileTask,
148*8975f5c5SAndroid Build Coastguard Worker                  const std::shared_ptr<angle::WaitableEvent> &waitEvent)
149*8975f5c5SAndroid Build Coastguard Worker         : mCompileTask(compileTask), mWaitableEvent(waitEvent)
150*8975f5c5SAndroid Build Coastguard Worker     {}
151*8975f5c5SAndroid Build Coastguard Worker     ~CompileEvent() = default;
152*8975f5c5SAndroid Build Coastguard Worker 
wait()153*8975f5c5SAndroid Build Coastguard Worker     angle::Result wait()
154*8975f5c5SAndroid Build Coastguard Worker     {
155*8975f5c5SAndroid Build Coastguard Worker         ANGLE_TRACE_EVENT0("gpu.angle", "CompileEvent::wait");
156*8975f5c5SAndroid Build Coastguard Worker 
157*8975f5c5SAndroid Build Coastguard Worker         mWaitableEvent->wait();
158*8975f5c5SAndroid Build Coastguard Worker 
159*8975f5c5SAndroid Build Coastguard Worker         return mCompileTask->getResult();
160*8975f5c5SAndroid Build Coastguard Worker     }
isCompiling()161*8975f5c5SAndroid Build Coastguard Worker     bool isCompiling()
162*8975f5c5SAndroid Build Coastguard Worker     {
163*8975f5c5SAndroid Build Coastguard Worker         return !mWaitableEvent->isReady() || mCompileTask->isCompilingInternally();
164*8975f5c5SAndroid Build Coastguard Worker     }
165*8975f5c5SAndroid Build Coastguard Worker 
getInfoLog()166*8975f5c5SAndroid Build Coastguard Worker     std::string &&getInfoLog() { return std::move(mCompileTask->getInfoLog()); }
167*8975f5c5SAndroid Build Coastguard Worker 
168*8975f5c5SAndroid Build Coastguard Worker   private:
169*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<CompileTask> mCompileTask;
170*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<angle::WaitableEvent> mWaitableEvent;
171*8975f5c5SAndroid Build Coastguard Worker };
172*8975f5c5SAndroid Build Coastguard Worker 
compileImpl()173*8975f5c5SAndroid Build Coastguard Worker angle::Result CompileTask::compileImpl()
174*8975f5c5SAndroid Build Coastguard Worker {
175*8975f5c5SAndroid Build Coastguard Worker     if (mCompilerHandle)
176*8975f5c5SAndroid Build Coastguard Worker     {
177*8975f5c5SAndroid Build Coastguard Worker         // Compiling from source
178*8975f5c5SAndroid Build Coastguard Worker 
179*8975f5c5SAndroid Build Coastguard Worker         // Call the translator and get the info log
180*8975f5c5SAndroid Build Coastguard Worker         bool result = mTranslateTask->translate(mCompilerHandle, mOptions, mSource);
181*8975f5c5SAndroid Build Coastguard Worker         mInfoLog    = sh::GetInfoLog(mCompilerHandle);
182*8975f5c5SAndroid Build Coastguard Worker         if (!result)
183*8975f5c5SAndroid Build Coastguard Worker         {
184*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
185*8975f5c5SAndroid Build Coastguard Worker         }
186*8975f5c5SAndroid Build Coastguard Worker 
187*8975f5c5SAndroid Build Coastguard Worker         // Process the translation results itself; gather compilation info, substitute the shader if
188*8975f5c5SAndroid Build Coastguard Worker         // being overriden, etc.
189*8975f5c5SAndroid Build Coastguard Worker         return postTranslate();
190*8975f5c5SAndroid Build Coastguard Worker     }
191*8975f5c5SAndroid Build Coastguard Worker     else
192*8975f5c5SAndroid Build Coastguard Worker     {
193*8975f5c5SAndroid Build Coastguard Worker         // Loading from binary
194*8975f5c5SAndroid Build Coastguard Worker         mTranslateTask->load(*mCompiledState.get());
195*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
196*8975f5c5SAndroid Build Coastguard Worker     }
197*8975f5c5SAndroid Build Coastguard Worker }
198*8975f5c5SAndroid Build Coastguard Worker 
postTranslate()199*8975f5c5SAndroid Build Coastguard Worker angle::Result CompileTask::postTranslate()
200*8975f5c5SAndroid Build Coastguard Worker {
201*8975f5c5SAndroid Build Coastguard Worker     const bool isBinaryOutput = mOutputType == SH_SPIRV_VULKAN_OUTPUT;
202*8975f5c5SAndroid Build Coastguard Worker     mCompiledState->buildCompiledShaderState(mCompilerHandle, isBinaryOutput);
203*8975f5c5SAndroid Build Coastguard Worker 
204*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mCompiledState->translatedSource.empty() || !mCompiledState->compiledBinary.empty());
205*8975f5c5SAndroid Build Coastguard Worker 
206*8975f5c5SAndroid Build Coastguard Worker     // Validation checks for compute shaders
207*8975f5c5SAndroid Build Coastguard Worker     if (mCompiledState->shaderType == ShaderType::Compute && mCompiledState->localSize.isDeclared())
208*8975f5c5SAndroid Build Coastguard Worker     {
209*8975f5c5SAndroid Build Coastguard Worker         angle::CheckedNumeric<size_t> checked_local_size_product(mCompiledState->localSize[0]);
210*8975f5c5SAndroid Build Coastguard Worker         checked_local_size_product *= mCompiledState->localSize[1];
211*8975f5c5SAndroid Build Coastguard Worker         checked_local_size_product *= mCompiledState->localSize[2];
212*8975f5c5SAndroid Build Coastguard Worker 
213*8975f5c5SAndroid Build Coastguard Worker         if (!checked_local_size_product.IsValid() ||
214*8975f5c5SAndroid Build Coastguard Worker             checked_local_size_product.ValueOrDie() > mMaxComputeWorkGroupInvocations)
215*8975f5c5SAndroid Build Coastguard Worker         {
216*8975f5c5SAndroid Build Coastguard Worker             mInfoLog +=
217*8975f5c5SAndroid Build Coastguard Worker                 "\nThe total number of invocations within a work group exceeds "
218*8975f5c5SAndroid Build Coastguard Worker                 "MAX_COMPUTE_WORK_GROUP_INVOCATIONS.";
219*8975f5c5SAndroid Build Coastguard Worker             return angle::Result::Stop;
220*8975f5c5SAndroid Build Coastguard Worker         }
221*8975f5c5SAndroid Build Coastguard Worker     }
222*8975f5c5SAndroid Build Coastguard Worker 
223*8975f5c5SAndroid Build Coastguard Worker     unsigned int sharedMemSize = sh::GetShaderSharedMemorySize(mCompilerHandle);
224*8975f5c5SAndroid Build Coastguard Worker     if (sharedMemSize > mMaxComputeSharedMemory)
225*8975f5c5SAndroid Build Coastguard Worker     {
226*8975f5c5SAndroid Build Coastguard Worker         mInfoLog += "\nShared memory size exceeds GL_MAX_COMPUTE_SHARED_MEMORY_SIZE";
227*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Stop;
228*8975f5c5SAndroid Build Coastguard Worker     }
229*8975f5c5SAndroid Build Coastguard Worker 
230*8975f5c5SAndroid Build Coastguard Worker     bool substitutedTranslatedShader = false;
231*8975f5c5SAndroid Build Coastguard Worker     const char *suffix               = "translated";
232*8975f5c5SAndroid Build Coastguard Worker     if (mFrontendFeatures.enableTranslatedShaderSubstitution.enabled)
233*8975f5c5SAndroid Build Coastguard Worker     {
234*8975f5c5SAndroid Build Coastguard Worker         // To support reading/writing compiled binaries (SPIR-V representation), need more file
235*8975f5c5SAndroid Build Coastguard Worker         // input/output facilities, and figure out the byte ordering of writing the 32-bit words to
236*8975f5c5SAndroid Build Coastguard Worker         // disk.
237*8975f5c5SAndroid Build Coastguard Worker         if (isBinaryOutput)
238*8975f5c5SAndroid Build Coastguard Worker         {
239*8975f5c5SAndroid Build Coastguard Worker             INFO() << "Can not substitute compiled binary (SPIR-V) shaders yet";
240*8975f5c5SAndroid Build Coastguard Worker         }
241*8975f5c5SAndroid Build Coastguard Worker         else
242*8975f5c5SAndroid Build Coastguard Worker         {
243*8975f5c5SAndroid Build Coastguard Worker             std::string substituteShaderPath = GetShaderDumpFilePath(mSourceHash, suffix);
244*8975f5c5SAndroid Build Coastguard Worker 
245*8975f5c5SAndroid Build Coastguard Worker             std::string substituteShader;
246*8975f5c5SAndroid Build Coastguard Worker             if (angle::ReadFileToString(substituteShaderPath, &substituteShader))
247*8975f5c5SAndroid Build Coastguard Worker             {
248*8975f5c5SAndroid Build Coastguard Worker                 mCompiledState->translatedSource = std::move(substituteShader);
249*8975f5c5SAndroid Build Coastguard Worker                 substitutedTranslatedShader      = true;
250*8975f5c5SAndroid Build Coastguard Worker                 INFO() << "Translated shader substitute found, loading from "
251*8975f5c5SAndroid Build Coastguard Worker                        << substituteShaderPath;
252*8975f5c5SAndroid Build Coastguard Worker             }
253*8975f5c5SAndroid Build Coastguard Worker         }
254*8975f5c5SAndroid Build Coastguard Worker     }
255*8975f5c5SAndroid Build Coastguard Worker 
256*8975f5c5SAndroid Build Coastguard Worker     // Only dump translated shaders that have not been previously substituted. It would write the
257*8975f5c5SAndroid Build Coastguard Worker     // same data back to the file.
258*8975f5c5SAndroid Build Coastguard Worker     if (mFrontendFeatures.dumpTranslatedShaders.enabled && !substitutedTranslatedShader)
259*8975f5c5SAndroid Build Coastguard Worker     {
260*8975f5c5SAndroid Build Coastguard Worker         if (isBinaryOutput)
261*8975f5c5SAndroid Build Coastguard Worker         {
262*8975f5c5SAndroid Build Coastguard Worker             INFO() << "Can not dump compiled binary (SPIR-V) shaders yet";
263*8975f5c5SAndroid Build Coastguard Worker         }
264*8975f5c5SAndroid Build Coastguard Worker         else
265*8975f5c5SAndroid Build Coastguard Worker         {
266*8975f5c5SAndroid Build Coastguard Worker             std::string dumpFile = GetShaderDumpFilePath(mSourceHash, suffix);
267*8975f5c5SAndroid Build Coastguard Worker 
268*8975f5c5SAndroid Build Coastguard Worker             const std::string &translatedSource = mCompiledState->translatedSource;
269*8975f5c5SAndroid Build Coastguard Worker             writeFile(dumpFile.c_str(), translatedSource.c_str(), translatedSource.length());
270*8975f5c5SAndroid Build Coastguard Worker             INFO() << "Dumped translated source: " << dumpFile;
271*8975f5c5SAndroid Build Coastguard Worker         }
272*8975f5c5SAndroid Build Coastguard Worker     }
273*8975f5c5SAndroid Build Coastguard Worker 
274*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_ENABLE_ASSERTS)
275*8975f5c5SAndroid Build Coastguard Worker     if (!isBinaryOutput)
276*8975f5c5SAndroid Build Coastguard Worker     {
277*8975f5c5SAndroid Build Coastguard Worker         // Suffix the translated shader with commented out un-translated shader.
278*8975f5c5SAndroid Build Coastguard Worker         // Useful in diagnostics tools which capture the shader source.
279*8975f5c5SAndroid Build Coastguard Worker         std::ostringstream shaderStream;
280*8975f5c5SAndroid Build Coastguard Worker         shaderStream << "\n";
281*8975f5c5SAndroid Build Coastguard Worker         shaderStream << "// GLSL\n";
282*8975f5c5SAndroid Build Coastguard Worker         shaderStream << "//\n";
283*8975f5c5SAndroid Build Coastguard Worker 
284*8975f5c5SAndroid Build Coastguard Worker         std::istringstream inputSourceStream(mSource);
285*8975f5c5SAndroid Build Coastguard Worker         std::string line;
286*8975f5c5SAndroid Build Coastguard Worker         while (std::getline(inputSourceStream, line))
287*8975f5c5SAndroid Build Coastguard Worker         {
288*8975f5c5SAndroid Build Coastguard Worker             // Remove null characters from the source line
289*8975f5c5SAndroid Build Coastguard Worker             line.erase(std::remove(line.begin(), line.end(), '\0'), line.end());
290*8975f5c5SAndroid Build Coastguard Worker 
291*8975f5c5SAndroid Build Coastguard Worker             shaderStream << "// " << line;
292*8975f5c5SAndroid Build Coastguard Worker 
293*8975f5c5SAndroid Build Coastguard Worker             // glslang complains if a comment ends with backslash
294*8975f5c5SAndroid Build Coastguard Worker             if (!line.empty() && line.back() == '\\')
295*8975f5c5SAndroid Build Coastguard Worker             {
296*8975f5c5SAndroid Build Coastguard Worker                 shaderStream << "\\";
297*8975f5c5SAndroid Build Coastguard Worker             }
298*8975f5c5SAndroid Build Coastguard Worker 
299*8975f5c5SAndroid Build Coastguard Worker             shaderStream << std::endl;
300*8975f5c5SAndroid Build Coastguard Worker         }
301*8975f5c5SAndroid Build Coastguard Worker         mCompiledState->translatedSource += shaderStream.str();
302*8975f5c5SAndroid Build Coastguard Worker     }
303*8975f5c5SAndroid Build Coastguard Worker #endif  // defined(ANGLE_ENABLE_ASSERTS)
304*8975f5c5SAndroid Build Coastguard Worker 
305*8975f5c5SAndroid Build Coastguard Worker     // Let the backend process the result of the compilation.  For the GL backend, this means
306*8975f5c5SAndroid Build Coastguard Worker     // kicking off compilation internally.  Some of the other backends fill in their internal
307*8975f5c5SAndroid Build Coastguard Worker     // "compiled state" at this point.
308*8975f5c5SAndroid Build Coastguard Worker     mTranslateTask->postTranslate(mCompilerHandle, *mCompiledState.get());
309*8975f5c5SAndroid Build Coastguard Worker 
310*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
311*8975f5c5SAndroid Build Coastguard Worker }
312*8975f5c5SAndroid Build Coastguard Worker 
313*8975f5c5SAndroid Build Coastguard Worker template <typename T>
AppendHashValue(angle::base::SecureHashAlgorithm & hasher,T value)314*8975f5c5SAndroid Build Coastguard Worker void AppendHashValue(angle::base::SecureHashAlgorithm &hasher, T value)
315*8975f5c5SAndroid Build Coastguard Worker {
316*8975f5c5SAndroid Build Coastguard Worker     static_assert(std::is_fundamental<T>::value || std::is_enum<T>::value);
317*8975f5c5SAndroid Build Coastguard Worker     hasher.Update(&value, sizeof(T));
318*8975f5c5SAndroid Build Coastguard Worker }
319*8975f5c5SAndroid Build Coastguard Worker 
GetTranslateTaskThreadSafety(const Context * context)320*8975f5c5SAndroid Build Coastguard Worker angle::JobThreadSafety GetTranslateTaskThreadSafety(const Context *context)
321*8975f5c5SAndroid Build Coastguard Worker {
322*8975f5c5SAndroid Build Coastguard Worker     // The GL backend relies on the driver's internal parallel compilation, and thus does not use a
323*8975f5c5SAndroid Build Coastguard Worker     // thread to compile.  A front-end feature selects whether the single-threaded pool must be
324*8975f5c5SAndroid Build Coastguard Worker     // used.
325*8975f5c5SAndroid Build Coastguard Worker     return context->getFrontendFeatures().compileJobIsThreadSafe.enabled
326*8975f5c5SAndroid Build Coastguard Worker                ? angle::JobThreadSafety::Safe
327*8975f5c5SAndroid Build Coastguard Worker                : angle::JobThreadSafety::Unsafe;
328*8975f5c5SAndroid Build Coastguard Worker }
329*8975f5c5SAndroid Build Coastguard Worker 
330*8975f5c5SAndroid Build Coastguard Worker }  // anonymous namespace
331*8975f5c5SAndroid Build Coastguard Worker 
GetShaderTypeString(ShaderType type)332*8975f5c5SAndroid Build Coastguard Worker const char *GetShaderTypeString(ShaderType type)
333*8975f5c5SAndroid Build Coastguard Worker {
334*8975f5c5SAndroid Build Coastguard Worker     switch (type)
335*8975f5c5SAndroid Build Coastguard Worker     {
336*8975f5c5SAndroid Build Coastguard Worker         case ShaderType::Vertex:
337*8975f5c5SAndroid Build Coastguard Worker             return "VERTEX";
338*8975f5c5SAndroid Build Coastguard Worker 
339*8975f5c5SAndroid Build Coastguard Worker         case ShaderType::Fragment:
340*8975f5c5SAndroid Build Coastguard Worker             return "FRAGMENT";
341*8975f5c5SAndroid Build Coastguard Worker 
342*8975f5c5SAndroid Build Coastguard Worker         case ShaderType::Compute:
343*8975f5c5SAndroid Build Coastguard Worker             return "COMPUTE";
344*8975f5c5SAndroid Build Coastguard Worker 
345*8975f5c5SAndroid Build Coastguard Worker         case ShaderType::Geometry:
346*8975f5c5SAndroid Build Coastguard Worker             return "GEOMETRY";
347*8975f5c5SAndroid Build Coastguard Worker 
348*8975f5c5SAndroid Build Coastguard Worker         case ShaderType::TessControl:
349*8975f5c5SAndroid Build Coastguard Worker             return "TESS_CONTROL";
350*8975f5c5SAndroid Build Coastguard Worker 
351*8975f5c5SAndroid Build Coastguard Worker         case ShaderType::TessEvaluation:
352*8975f5c5SAndroid Build Coastguard Worker             return "TESS_EVALUATION";
353*8975f5c5SAndroid Build Coastguard Worker 
354*8975f5c5SAndroid Build Coastguard Worker         default:
355*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
356*8975f5c5SAndroid Build Coastguard Worker             return "";
357*8975f5c5SAndroid Build Coastguard Worker     }
358*8975f5c5SAndroid Build Coastguard Worker }
359*8975f5c5SAndroid Build Coastguard Worker 
GetShaderDumpFileDirectory()360*8975f5c5SAndroid Build Coastguard Worker std::string GetShaderDumpFileDirectory()
361*8975f5c5SAndroid Build Coastguard Worker {
362*8975f5c5SAndroid Build Coastguard Worker     // Check the environment variable for the path to save and read shader dump files.
363*8975f5c5SAndroid Build Coastguard Worker     std::string environmentVariableDumpDir =
364*8975f5c5SAndroid Build Coastguard Worker         angle::GetAndSetEnvironmentVarOrUnCachedAndroidProperty(kShaderDumpPathVarName,
365*8975f5c5SAndroid Build Coastguard Worker                                                                 kEShaderDumpPathPropertyName);
366*8975f5c5SAndroid Build Coastguard Worker     if (!environmentVariableDumpDir.empty() && environmentVariableDumpDir.compare("0") != 0)
367*8975f5c5SAndroid Build Coastguard Worker     {
368*8975f5c5SAndroid Build Coastguard Worker         return environmentVariableDumpDir;
369*8975f5c5SAndroid Build Coastguard Worker     }
370*8975f5c5SAndroid Build Coastguard Worker 
371*8975f5c5SAndroid Build Coastguard Worker     // Fall back to the temp dir. If that doesn't exist, use the current working directory.
372*8975f5c5SAndroid Build Coastguard Worker     return angle::GetTempDirectory().valueOr("");
373*8975f5c5SAndroid Build Coastguard Worker }
374*8975f5c5SAndroid Build Coastguard Worker 
GetShaderDumpFileName(size_t shaderHash)375*8975f5c5SAndroid Build Coastguard Worker std::string GetShaderDumpFileName(size_t shaderHash)
376*8975f5c5SAndroid Build Coastguard Worker {
377*8975f5c5SAndroid Build Coastguard Worker     std::stringstream name;
378*8975f5c5SAndroid Build Coastguard Worker     name << shaderHash << ".essl";
379*8975f5c5SAndroid Build Coastguard Worker     return name.str();
380*8975f5c5SAndroid Build Coastguard Worker }
381*8975f5c5SAndroid Build Coastguard Worker 
382*8975f5c5SAndroid Build Coastguard Worker struct CompileJob
383*8975f5c5SAndroid Build Coastguard Worker {
384*8975f5c5SAndroid Build Coastguard Worker     virtual ~CompileJob() = default;
waitgl::CompileJob385*8975f5c5SAndroid Build Coastguard Worker     virtual bool wait() { return compileEvent->wait() == angle::Result::Continue; }
386*8975f5c5SAndroid Build Coastguard Worker 
387*8975f5c5SAndroid Build Coastguard Worker     std::unique_ptr<CompileEvent> compileEvent;
388*8975f5c5SAndroid Build Coastguard Worker     ShCompilerInstance shCompilerInstance;
389*8975f5c5SAndroid Build Coastguard Worker };
390*8975f5c5SAndroid Build Coastguard Worker 
391*8975f5c5SAndroid Build Coastguard Worker struct CompileJobDone final : public CompileJob
392*8975f5c5SAndroid Build Coastguard Worker {
CompileJobDonegl::CompileJobDone393*8975f5c5SAndroid Build Coastguard Worker     CompileJobDone(bool compiledIn) : compiled(compiledIn) {}
waitgl::CompileJobDone394*8975f5c5SAndroid Build Coastguard Worker     bool wait() override { return compiled; }
395*8975f5c5SAndroid Build Coastguard Worker 
396*8975f5c5SAndroid Build Coastguard Worker     bool compiled;
397*8975f5c5SAndroid Build Coastguard Worker };
398*8975f5c5SAndroid Build Coastguard Worker 
ShaderState(ShaderType shaderType)399*8975f5c5SAndroid Build Coastguard Worker ShaderState::ShaderState(ShaderType shaderType)
400*8975f5c5SAndroid Build Coastguard Worker     : mCompiledState(std::make_shared<CompiledShaderState>(shaderType))
401*8975f5c5SAndroid Build Coastguard Worker {}
402*8975f5c5SAndroid Build Coastguard Worker 
~ShaderState()403*8975f5c5SAndroid Build Coastguard Worker ShaderState::~ShaderState() {}
404*8975f5c5SAndroid Build Coastguard Worker 
Shader(ShaderProgramManager * manager,rx::GLImplFactory * implFactory,const gl::Limitations & rendererLimitations,ShaderType type,ShaderProgramID handle)405*8975f5c5SAndroid Build Coastguard Worker Shader::Shader(ShaderProgramManager *manager,
406*8975f5c5SAndroid Build Coastguard Worker                rx::GLImplFactory *implFactory,
407*8975f5c5SAndroid Build Coastguard Worker                const gl::Limitations &rendererLimitations,
408*8975f5c5SAndroid Build Coastguard Worker                ShaderType type,
409*8975f5c5SAndroid Build Coastguard Worker                ShaderProgramID handle)
410*8975f5c5SAndroid Build Coastguard Worker     : mState(type),
411*8975f5c5SAndroid Build Coastguard Worker       mImplementation(implFactory->createShader(mState)),
412*8975f5c5SAndroid Build Coastguard Worker       mRendererLimitations(rendererLimitations),
413*8975f5c5SAndroid Build Coastguard Worker       mHandle(handle),
414*8975f5c5SAndroid Build Coastguard Worker       mRefCount(0),
415*8975f5c5SAndroid Build Coastguard Worker       mDeleteStatus(false),
416*8975f5c5SAndroid Build Coastguard Worker       mResourceManager(manager)
417*8975f5c5SAndroid Build Coastguard Worker {
418*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mImplementation);
419*8975f5c5SAndroid Build Coastguard Worker 
420*8975f5c5SAndroid Build Coastguard Worker     mShaderHash = {0};
421*8975f5c5SAndroid Build Coastguard Worker }
422*8975f5c5SAndroid Build Coastguard Worker 
onDestroy(const gl::Context * context)423*8975f5c5SAndroid Build Coastguard Worker void Shader::onDestroy(const gl::Context *context)
424*8975f5c5SAndroid Build Coastguard Worker {
425*8975f5c5SAndroid Build Coastguard Worker     resolveCompile(context);
426*8975f5c5SAndroid Build Coastguard Worker     mImplementation->onDestroy(context);
427*8975f5c5SAndroid Build Coastguard Worker     mBoundCompiler.set(context, nullptr);
428*8975f5c5SAndroid Build Coastguard Worker     mImplementation.reset(nullptr);
429*8975f5c5SAndroid Build Coastguard Worker     delete this;
430*8975f5c5SAndroid Build Coastguard Worker }
431*8975f5c5SAndroid Build Coastguard Worker 
~Shader()432*8975f5c5SAndroid Build Coastguard Worker Shader::~Shader()
433*8975f5c5SAndroid Build Coastguard Worker {
434*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mImplementation);
435*8975f5c5SAndroid Build Coastguard Worker }
436*8975f5c5SAndroid Build Coastguard Worker 
setLabel(const Context * context,const std::string & label)437*8975f5c5SAndroid Build Coastguard Worker angle::Result Shader::setLabel(const Context *context, const std::string &label)
438*8975f5c5SAndroid Build Coastguard Worker {
439*8975f5c5SAndroid Build Coastguard Worker     mState.mLabel = label;
440*8975f5c5SAndroid Build Coastguard Worker 
441*8975f5c5SAndroid Build Coastguard Worker     if (mImplementation)
442*8975f5c5SAndroid Build Coastguard Worker     {
443*8975f5c5SAndroid Build Coastguard Worker         return mImplementation->onLabelUpdate(context);
444*8975f5c5SAndroid Build Coastguard Worker     }
445*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
446*8975f5c5SAndroid Build Coastguard Worker }
447*8975f5c5SAndroid Build Coastguard Worker 
getLabel() const448*8975f5c5SAndroid Build Coastguard Worker const std::string &Shader::getLabel() const
449*8975f5c5SAndroid Build Coastguard Worker {
450*8975f5c5SAndroid Build Coastguard Worker     return mState.mLabel;
451*8975f5c5SAndroid Build Coastguard Worker }
452*8975f5c5SAndroid Build Coastguard Worker 
getHandle() const453*8975f5c5SAndroid Build Coastguard Worker ShaderProgramID Shader::getHandle() const
454*8975f5c5SAndroid Build Coastguard Worker {
455*8975f5c5SAndroid Build Coastguard Worker     return mHandle;
456*8975f5c5SAndroid Build Coastguard Worker }
457*8975f5c5SAndroid Build Coastguard Worker 
joinShaderSources(GLsizei count,const char * const * string,const GLint * length)458*8975f5c5SAndroid Build Coastguard Worker std::string Shader::joinShaderSources(GLsizei count, const char *const *string, const GLint *length)
459*8975f5c5SAndroid Build Coastguard Worker {
460*8975f5c5SAndroid Build Coastguard Worker     // Fast path for the most common case.
461*8975f5c5SAndroid Build Coastguard Worker     if (count == 1)
462*8975f5c5SAndroid Build Coastguard Worker     {
463*8975f5c5SAndroid Build Coastguard Worker         if (length == nullptr || length[0] < 0)
464*8975f5c5SAndroid Build Coastguard Worker             return std::string(string[0]);
465*8975f5c5SAndroid Build Coastguard Worker         else
466*8975f5c5SAndroid Build Coastguard Worker             return std::string(string[0], static_cast<size_t>(length[0]));
467*8975f5c5SAndroid Build Coastguard Worker     }
468*8975f5c5SAndroid Build Coastguard Worker 
469*8975f5c5SAndroid Build Coastguard Worker     // Start with totalLength of 1 to reserve space for the null terminator
470*8975f5c5SAndroid Build Coastguard Worker     size_t totalLength = 1;
471*8975f5c5SAndroid Build Coastguard Worker 
472*8975f5c5SAndroid Build Coastguard Worker     // First pass, calculate the total length of the joined string
473*8975f5c5SAndroid Build Coastguard Worker     for (GLsizei i = 0; i < count; ++i)
474*8975f5c5SAndroid Build Coastguard Worker     {
475*8975f5c5SAndroid Build Coastguard Worker         if (length == nullptr || length[i] < 0)
476*8975f5c5SAndroid Build Coastguard Worker             totalLength += std::strlen(string[i]);
477*8975f5c5SAndroid Build Coastguard Worker         else
478*8975f5c5SAndroid Build Coastguard Worker             totalLength += static_cast<size_t>(length[i]);
479*8975f5c5SAndroid Build Coastguard Worker     }
480*8975f5c5SAndroid Build Coastguard Worker 
481*8975f5c5SAndroid Build Coastguard Worker     // Second pass, allocate the string and concatenate each shader source
482*8975f5c5SAndroid Build Coastguard Worker     // fragment
483*8975f5c5SAndroid Build Coastguard Worker     std::string joinedString;
484*8975f5c5SAndroid Build Coastguard Worker     joinedString.reserve(totalLength);
485*8975f5c5SAndroid Build Coastguard Worker     for (GLsizei i = 0; i < count; ++i)
486*8975f5c5SAndroid Build Coastguard Worker     {
487*8975f5c5SAndroid Build Coastguard Worker         if (length == nullptr || length[i] < 0)
488*8975f5c5SAndroid Build Coastguard Worker             joinedString.append(string[i]);
489*8975f5c5SAndroid Build Coastguard Worker         else
490*8975f5c5SAndroid Build Coastguard Worker             joinedString.append(string[i], static_cast<size_t>(length[i]));
491*8975f5c5SAndroid Build Coastguard Worker     }
492*8975f5c5SAndroid Build Coastguard Worker 
493*8975f5c5SAndroid Build Coastguard Worker     return joinedString;
494*8975f5c5SAndroid Build Coastguard Worker }
495*8975f5c5SAndroid Build Coastguard Worker 
setSource(const Context * context,GLsizei count,const char * const * string,const GLint * length)496*8975f5c5SAndroid Build Coastguard Worker void Shader::setSource(const Context *context,
497*8975f5c5SAndroid Build Coastguard Worker                        GLsizei count,
498*8975f5c5SAndroid Build Coastguard Worker                        const char *const *string,
499*8975f5c5SAndroid Build Coastguard Worker                        const GLint *length)
500*8975f5c5SAndroid Build Coastguard Worker {
501*8975f5c5SAndroid Build Coastguard Worker     std::string source = joinShaderSources(count, string, length);
502*8975f5c5SAndroid Build Coastguard Worker 
503*8975f5c5SAndroid Build Coastguard Worker     // Compute the hash based on the original source before any substitutions
504*8975f5c5SAndroid Build Coastguard Worker     size_t sourceHash = ComputeShaderHash(source);
505*8975f5c5SAndroid Build Coastguard Worker 
506*8975f5c5SAndroid Build Coastguard Worker     const angle::FrontendFeatures &frontendFeatures = context->getFrontendFeatures();
507*8975f5c5SAndroid Build Coastguard Worker 
508*8975f5c5SAndroid Build Coastguard Worker     bool substitutedShader = false;
509*8975f5c5SAndroid Build Coastguard Worker     const char *suffix     = "essl";
510*8975f5c5SAndroid Build Coastguard Worker     if (frontendFeatures.enableShaderSubstitution.enabled)
511*8975f5c5SAndroid Build Coastguard Worker     {
512*8975f5c5SAndroid Build Coastguard Worker         std::string subsitutionShaderPath = GetShaderDumpFilePath(sourceHash, suffix);
513*8975f5c5SAndroid Build Coastguard Worker 
514*8975f5c5SAndroid Build Coastguard Worker         std::string substituteShader;
515*8975f5c5SAndroid Build Coastguard Worker         if (angle::ReadFileToString(subsitutionShaderPath, &substituteShader))
516*8975f5c5SAndroid Build Coastguard Worker         {
517*8975f5c5SAndroid Build Coastguard Worker             source            = std::move(substituteShader);
518*8975f5c5SAndroid Build Coastguard Worker             substitutedShader = true;
519*8975f5c5SAndroid Build Coastguard Worker             INFO() << "Shader substitute found, loading from " << subsitutionShaderPath;
520*8975f5c5SAndroid Build Coastguard Worker         }
521*8975f5c5SAndroid Build Coastguard Worker     }
522*8975f5c5SAndroid Build Coastguard Worker 
523*8975f5c5SAndroid Build Coastguard Worker     // Only dump shaders that have not been previously substituted. It would write the same data
524*8975f5c5SAndroid Build Coastguard Worker     // back to the file.
525*8975f5c5SAndroid Build Coastguard Worker     if (frontendFeatures.dumpShaderSource.enabled && !substitutedShader)
526*8975f5c5SAndroid Build Coastguard Worker     {
527*8975f5c5SAndroid Build Coastguard Worker         std::string dumpFile = GetShaderDumpFilePath(sourceHash, suffix);
528*8975f5c5SAndroid Build Coastguard Worker 
529*8975f5c5SAndroid Build Coastguard Worker         writeFile(dumpFile.c_str(), source.c_str(), source.length());
530*8975f5c5SAndroid Build Coastguard Worker         INFO() << "Dumped shader source: " << dumpFile;
531*8975f5c5SAndroid Build Coastguard Worker     }
532*8975f5c5SAndroid Build Coastguard Worker 
533*8975f5c5SAndroid Build Coastguard Worker     mState.mSource     = std::move(source);
534*8975f5c5SAndroid Build Coastguard Worker     mState.mSourceHash = sourceHash;
535*8975f5c5SAndroid Build Coastguard Worker }
536*8975f5c5SAndroid Build Coastguard Worker 
getInfoLogLength(const Context * context)537*8975f5c5SAndroid Build Coastguard Worker int Shader::getInfoLogLength(const Context *context)
538*8975f5c5SAndroid Build Coastguard Worker {
539*8975f5c5SAndroid Build Coastguard Worker     resolveCompile(context);
540*8975f5c5SAndroid Build Coastguard Worker     if (mInfoLog.empty())
541*8975f5c5SAndroid Build Coastguard Worker     {
542*8975f5c5SAndroid Build Coastguard Worker         return 0;
543*8975f5c5SAndroid Build Coastguard Worker     }
544*8975f5c5SAndroid Build Coastguard Worker 
545*8975f5c5SAndroid Build Coastguard Worker     return (static_cast<int>(mInfoLog.length()) + 1);
546*8975f5c5SAndroid Build Coastguard Worker }
547*8975f5c5SAndroid Build Coastguard Worker 
getInfoLog(const Context * context,GLsizei bufSize,GLsizei * length,char * infoLog)548*8975f5c5SAndroid Build Coastguard Worker void Shader::getInfoLog(const Context *context, GLsizei bufSize, GLsizei *length, char *infoLog)
549*8975f5c5SAndroid Build Coastguard Worker {
550*8975f5c5SAndroid Build Coastguard Worker     resolveCompile(context);
551*8975f5c5SAndroid Build Coastguard Worker 
552*8975f5c5SAndroid Build Coastguard Worker     int index = 0;
553*8975f5c5SAndroid Build Coastguard Worker 
554*8975f5c5SAndroid Build Coastguard Worker     if (bufSize > 0)
555*8975f5c5SAndroid Build Coastguard Worker     {
556*8975f5c5SAndroid Build Coastguard Worker         index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
557*8975f5c5SAndroid Build Coastguard Worker         memcpy(infoLog, mInfoLog.c_str(), index);
558*8975f5c5SAndroid Build Coastguard Worker 
559*8975f5c5SAndroid Build Coastguard Worker         infoLog[index] = '\0';
560*8975f5c5SAndroid Build Coastguard Worker     }
561*8975f5c5SAndroid Build Coastguard Worker 
562*8975f5c5SAndroid Build Coastguard Worker     if (length)
563*8975f5c5SAndroid Build Coastguard Worker     {
564*8975f5c5SAndroid Build Coastguard Worker         *length = index;
565*8975f5c5SAndroid Build Coastguard Worker     }
566*8975f5c5SAndroid Build Coastguard Worker }
567*8975f5c5SAndroid Build Coastguard Worker 
getSourceLength() const568*8975f5c5SAndroid Build Coastguard Worker int Shader::getSourceLength() const
569*8975f5c5SAndroid Build Coastguard Worker {
570*8975f5c5SAndroid Build Coastguard Worker     return mState.mSource.empty() ? 0 : (static_cast<int>(mState.mSource.length()) + 1);
571*8975f5c5SAndroid Build Coastguard Worker }
572*8975f5c5SAndroid Build Coastguard Worker 
getTranslatedSourceLength(const Context * context)573*8975f5c5SAndroid Build Coastguard Worker int Shader::getTranslatedSourceLength(const Context *context)
574*8975f5c5SAndroid Build Coastguard Worker {
575*8975f5c5SAndroid Build Coastguard Worker     resolveCompile(context);
576*8975f5c5SAndroid Build Coastguard Worker 
577*8975f5c5SAndroid Build Coastguard Worker     if (mState.mCompiledState->translatedSource.empty())
578*8975f5c5SAndroid Build Coastguard Worker     {
579*8975f5c5SAndroid Build Coastguard Worker         return 0;
580*8975f5c5SAndroid Build Coastguard Worker     }
581*8975f5c5SAndroid Build Coastguard Worker 
582*8975f5c5SAndroid Build Coastguard Worker     return static_cast<int>(mState.mCompiledState->translatedSource.length()) + 1;
583*8975f5c5SAndroid Build Coastguard Worker }
584*8975f5c5SAndroid Build Coastguard Worker 
getTranslatedSourceWithDebugInfoLength(const Context * context)585*8975f5c5SAndroid Build Coastguard Worker int Shader::getTranslatedSourceWithDebugInfoLength(const Context *context)
586*8975f5c5SAndroid Build Coastguard Worker {
587*8975f5c5SAndroid Build Coastguard Worker     resolveCompile(context);
588*8975f5c5SAndroid Build Coastguard Worker 
589*8975f5c5SAndroid Build Coastguard Worker     const std::string &debugInfo = mImplementation->getDebugInfo();
590*8975f5c5SAndroid Build Coastguard Worker     if (debugInfo.empty())
591*8975f5c5SAndroid Build Coastguard Worker     {
592*8975f5c5SAndroid Build Coastguard Worker         return 0;
593*8975f5c5SAndroid Build Coastguard Worker     }
594*8975f5c5SAndroid Build Coastguard Worker 
595*8975f5c5SAndroid Build Coastguard Worker     return (static_cast<int>(debugInfo.length()) + 1);
596*8975f5c5SAndroid Build Coastguard Worker }
597*8975f5c5SAndroid Build Coastguard Worker 
598*8975f5c5SAndroid Build Coastguard Worker // static
GetSourceImpl(const std::string & source,GLsizei bufSize,GLsizei * length,char * buffer)599*8975f5c5SAndroid Build Coastguard Worker void Shader::GetSourceImpl(const std::string &source,
600*8975f5c5SAndroid Build Coastguard Worker                            GLsizei bufSize,
601*8975f5c5SAndroid Build Coastguard Worker                            GLsizei *length,
602*8975f5c5SAndroid Build Coastguard Worker                            char *buffer)
603*8975f5c5SAndroid Build Coastguard Worker {
604*8975f5c5SAndroid Build Coastguard Worker     int index = 0;
605*8975f5c5SAndroid Build Coastguard Worker 
606*8975f5c5SAndroid Build Coastguard Worker     if (bufSize > 0)
607*8975f5c5SAndroid Build Coastguard Worker     {
608*8975f5c5SAndroid Build Coastguard Worker         index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
609*8975f5c5SAndroid Build Coastguard Worker         memcpy(buffer, source.c_str(), index);
610*8975f5c5SAndroid Build Coastguard Worker 
611*8975f5c5SAndroid Build Coastguard Worker         buffer[index] = '\0';
612*8975f5c5SAndroid Build Coastguard Worker     }
613*8975f5c5SAndroid Build Coastguard Worker 
614*8975f5c5SAndroid Build Coastguard Worker     if (length)
615*8975f5c5SAndroid Build Coastguard Worker     {
616*8975f5c5SAndroid Build Coastguard Worker         *length = index;
617*8975f5c5SAndroid Build Coastguard Worker     }
618*8975f5c5SAndroid Build Coastguard Worker }
619*8975f5c5SAndroid Build Coastguard Worker 
getSource(GLsizei bufSize,GLsizei * length,char * buffer) const620*8975f5c5SAndroid Build Coastguard Worker void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
621*8975f5c5SAndroid Build Coastguard Worker {
622*8975f5c5SAndroid Build Coastguard Worker     GetSourceImpl(mState.mSource, bufSize, length, buffer);
623*8975f5c5SAndroid Build Coastguard Worker }
624*8975f5c5SAndroid Build Coastguard Worker 
getTranslatedSource(const Context * context,GLsizei bufSize,GLsizei * length,char * buffer)625*8975f5c5SAndroid Build Coastguard Worker void Shader::getTranslatedSource(const Context *context,
626*8975f5c5SAndroid Build Coastguard Worker                                  GLsizei bufSize,
627*8975f5c5SAndroid Build Coastguard Worker                                  GLsizei *length,
628*8975f5c5SAndroid Build Coastguard Worker                                  char *buffer)
629*8975f5c5SAndroid Build Coastguard Worker {
630*8975f5c5SAndroid Build Coastguard Worker     GetSourceImpl(getTranslatedSource(context), bufSize, length, buffer);
631*8975f5c5SAndroid Build Coastguard Worker }
632*8975f5c5SAndroid Build Coastguard Worker 
getTranslatedSource(const Context * context)633*8975f5c5SAndroid Build Coastguard Worker const std::string &Shader::getTranslatedSource(const Context *context)
634*8975f5c5SAndroid Build Coastguard Worker {
635*8975f5c5SAndroid Build Coastguard Worker     resolveCompile(context);
636*8975f5c5SAndroid Build Coastguard Worker     return mState.mCompiledState->translatedSource;
637*8975f5c5SAndroid Build Coastguard Worker }
638*8975f5c5SAndroid Build Coastguard Worker 
getSourceHash() const639*8975f5c5SAndroid Build Coastguard Worker size_t Shader::getSourceHash() const
640*8975f5c5SAndroid Build Coastguard Worker {
641*8975f5c5SAndroid Build Coastguard Worker     return mState.mSourceHash;
642*8975f5c5SAndroid Build Coastguard Worker }
643*8975f5c5SAndroid Build Coastguard Worker 
getTranslatedSourceWithDebugInfo(const Context * context,GLsizei bufSize,GLsizei * length,char * buffer)644*8975f5c5SAndroid Build Coastguard Worker void Shader::getTranslatedSourceWithDebugInfo(const Context *context,
645*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei bufSize,
646*8975f5c5SAndroid Build Coastguard Worker                                               GLsizei *length,
647*8975f5c5SAndroid Build Coastguard Worker                                               char *buffer)
648*8975f5c5SAndroid Build Coastguard Worker {
649*8975f5c5SAndroid Build Coastguard Worker     resolveCompile(context);
650*8975f5c5SAndroid Build Coastguard Worker     const std::string &debugInfo = mImplementation->getDebugInfo();
651*8975f5c5SAndroid Build Coastguard Worker     GetSourceImpl(debugInfo, bufSize, length, buffer);
652*8975f5c5SAndroid Build Coastguard Worker }
653*8975f5c5SAndroid Build Coastguard Worker 
compile(const Context * context,angle::JobResultExpectancy resultExpectancy)654*8975f5c5SAndroid Build Coastguard Worker void Shader::compile(const Context *context, angle::JobResultExpectancy resultExpectancy)
655*8975f5c5SAndroid Build Coastguard Worker {
656*8975f5c5SAndroid Build Coastguard Worker     resolveCompile(context);
657*8975f5c5SAndroid Build Coastguard Worker 
658*8975f5c5SAndroid Build Coastguard Worker     // Create a new compiled shader state.  If any programs are currently linking using this shader,
659*8975f5c5SAndroid Build Coastguard Worker     // they would use the old compiled state, and this shader is free to recompile in the meantime.
660*8975f5c5SAndroid Build Coastguard Worker     mState.mCompiledState = std::make_shared<CompiledShaderState>(mState.getShaderType());
661*8975f5c5SAndroid Build Coastguard Worker 
662*8975f5c5SAndroid Build Coastguard Worker     mInfoLog.clear();
663*8975f5c5SAndroid Build Coastguard Worker 
664*8975f5c5SAndroid Build Coastguard Worker     ShCompileOptions options = {};
665*8975f5c5SAndroid Build Coastguard Worker     options.objectCode       = true;
666*8975f5c5SAndroid Build Coastguard Worker     options.emulateGLDrawID  = true;
667*8975f5c5SAndroid Build Coastguard Worker 
668*8975f5c5SAndroid Build Coastguard Worker     // Add default options to WebGL shaders to prevent unexpected behavior during
669*8975f5c5SAndroid Build Coastguard Worker     // compilation.
670*8975f5c5SAndroid Build Coastguard Worker     if (context->isWebGL())
671*8975f5c5SAndroid Build Coastguard Worker     {
672*8975f5c5SAndroid Build Coastguard Worker         options.initGLPosition             = true;
673*8975f5c5SAndroid Build Coastguard Worker         options.limitCallStackDepth        = true;
674*8975f5c5SAndroid Build Coastguard Worker         options.limitExpressionComplexity  = true;
675*8975f5c5SAndroid Build Coastguard Worker         options.enforcePackingRestrictions = true;
676*8975f5c5SAndroid Build Coastguard Worker         options.initSharedVariables        = true;
677*8975f5c5SAndroid Build Coastguard Worker 
678*8975f5c5SAndroid Build Coastguard Worker         if (context->getFrontendFeatures().rejectWebglShadersWithUndefinedBehavior.enabled)
679*8975f5c5SAndroid Build Coastguard Worker         {
680*8975f5c5SAndroid Build Coastguard Worker             options.rejectWebglShadersWithUndefinedBehavior = true;
681*8975f5c5SAndroid Build Coastguard Worker         }
682*8975f5c5SAndroid Build Coastguard Worker     }
683*8975f5c5SAndroid Build Coastguard Worker     else
684*8975f5c5SAndroid Build Coastguard Worker     {
685*8975f5c5SAndroid Build Coastguard Worker         // Per https://github.com/KhronosGroup/WebGL/pull/3278 gl_BaseVertex/gl_BaseInstance are
686*8975f5c5SAndroid Build Coastguard Worker         // removed from WebGL
687*8975f5c5SAndroid Build Coastguard Worker         options.emulateGLBaseVertexBaseInstance = true;
688*8975f5c5SAndroid Build Coastguard Worker     }
689*8975f5c5SAndroid Build Coastguard Worker 
690*8975f5c5SAndroid Build Coastguard Worker     if (context->getFrontendFeatures().forceInitShaderVariables.enabled)
691*8975f5c5SAndroid Build Coastguard Worker     {
692*8975f5c5SAndroid Build Coastguard Worker         options.initOutputVariables           = true;
693*8975f5c5SAndroid Build Coastguard Worker         options.initializeUninitializedLocals = true;
694*8975f5c5SAndroid Build Coastguard Worker     }
695*8975f5c5SAndroid Build Coastguard Worker 
696*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_ENABLE_ASSERTS)
697*8975f5c5SAndroid Build Coastguard Worker     options.validateAST = true;
698*8975f5c5SAndroid Build Coastguard Worker #endif
699*8975f5c5SAndroid Build Coastguard Worker 
700*8975f5c5SAndroid Build Coastguard Worker     // Find a shader in Blob Cache
701*8975f5c5SAndroid Build Coastguard Worker     Compiler *compiler = context->getCompiler();
702*8975f5c5SAndroid Build Coastguard Worker     setShaderKey(context, options, compiler->getShaderOutputType(),
703*8975f5c5SAndroid Build Coastguard Worker                  compiler->getBuiltInResources());
704*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mShaderHash.empty());
705*8975f5c5SAndroid Build Coastguard Worker     MemoryShaderCache *shaderCache = context->getMemoryShaderCache();
706*8975f5c5SAndroid Build Coastguard Worker     if (shaderCache != nullptr)
707*8975f5c5SAndroid Build Coastguard Worker     {
708*8975f5c5SAndroid Build Coastguard Worker         egl::CacheGetResult result =
709*8975f5c5SAndroid Build Coastguard Worker             shaderCache->getShader(context, this, mShaderHash, resultExpectancy);
710*8975f5c5SAndroid Build Coastguard Worker         switch (result)
711*8975f5c5SAndroid Build Coastguard Worker         {
712*8975f5c5SAndroid Build Coastguard Worker             case egl::CacheGetResult::Success:
713*8975f5c5SAndroid Build Coastguard Worker                 return;
714*8975f5c5SAndroid Build Coastguard Worker             case egl::CacheGetResult::Rejected:
715*8975f5c5SAndroid Build Coastguard Worker                 // Reset the state
716*8975f5c5SAndroid Build Coastguard Worker                 mState.mCompiledState =
717*8975f5c5SAndroid Build Coastguard Worker                     std::make_shared<CompiledShaderState>(mState.getShaderType());
718*8975f5c5SAndroid Build Coastguard Worker                 break;
719*8975f5c5SAndroid Build Coastguard Worker             case egl::CacheGetResult::NotFound:
720*8975f5c5SAndroid Build Coastguard Worker             default:
721*8975f5c5SAndroid Build Coastguard Worker                 break;
722*8975f5c5SAndroid Build Coastguard Worker         }
723*8975f5c5SAndroid Build Coastguard Worker     }
724*8975f5c5SAndroid Build Coastguard Worker 
725*8975f5c5SAndroid Build Coastguard Worker     mBoundCompiler.set(context, compiler);
726*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mBoundCompiler.get());
727*8975f5c5SAndroid Build Coastguard Worker 
728*8975f5c5SAndroid Build Coastguard Worker     ShCompilerInstance compilerInstance = mBoundCompiler->getInstance(mState.getShaderType());
729*8975f5c5SAndroid Build Coastguard Worker     ShHandle compilerHandle             = compilerInstance.getHandle();
730*8975f5c5SAndroid Build Coastguard Worker     ASSERT(compilerHandle);
731*8975f5c5SAndroid Build Coastguard Worker 
732*8975f5c5SAndroid Build Coastguard Worker     // Cache load failed, fall through normal compiling.
733*8975f5c5SAndroid Build Coastguard Worker     mState.mCompileStatus = CompileStatus::COMPILE_REQUESTED;
734*8975f5c5SAndroid Build Coastguard Worker 
735*8975f5c5SAndroid Build Coastguard Worker     // Ask the backend to prepare the translate task
736*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<rx::ShaderTranslateTask> translateTask =
737*8975f5c5SAndroid Build Coastguard Worker         mImplementation->compile(context, &options);
738*8975f5c5SAndroid Build Coastguard Worker 
739*8975f5c5SAndroid Build Coastguard Worker     // Prepare the complete compile task
740*8975f5c5SAndroid Build Coastguard Worker     const size_t maxComputeWorkGroupInvocations =
741*8975f5c5SAndroid Build Coastguard Worker         static_cast<size_t>(context->getCaps().maxComputeWorkGroupInvocations);
742*8975f5c5SAndroid Build Coastguard Worker     const size_t maxComputeSharedMemory = context->getCaps().maxComputeSharedMemorySize;
743*8975f5c5SAndroid Build Coastguard Worker 
744*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<CompileTask> compileTask(
745*8975f5c5SAndroid Build Coastguard Worker         new CompileTask(context->getFrontendFeatures(), compilerInstance.getHandle(),
746*8975f5c5SAndroid Build Coastguard Worker                         compilerInstance.getShaderOutputType(), options, mState.mSource,
747*8975f5c5SAndroid Build Coastguard Worker                         mState.mSourceHash, mState.mCompiledState, maxComputeWorkGroupInvocations,
748*8975f5c5SAndroid Build Coastguard Worker                         maxComputeSharedMemory, std::move(translateTask)));
749*8975f5c5SAndroid Build Coastguard Worker 
750*8975f5c5SAndroid Build Coastguard Worker     // The GL backend relies on the driver's internal parallel compilation, and thus does not use a
751*8975f5c5SAndroid Build Coastguard Worker     // thread to compile.  A front-end feature selects whether the single-threaded pool must be
752*8975f5c5SAndroid Build Coastguard Worker     // used.
753*8975f5c5SAndroid Build Coastguard Worker     const angle::JobThreadSafety threadSafety =
754*8975f5c5SAndroid Build Coastguard Worker         context->getFrontendFeatures().compileJobIsThreadSafe.enabled
755*8975f5c5SAndroid Build Coastguard Worker             ? angle::JobThreadSafety::Safe
756*8975f5c5SAndroid Build Coastguard Worker             : angle::JobThreadSafety::Unsafe;
757*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<angle::WaitableEvent> compileEvent =
758*8975f5c5SAndroid Build Coastguard Worker         context->postCompileLinkTask(compileTask, threadSafety, resultExpectancy);
759*8975f5c5SAndroid Build Coastguard Worker 
760*8975f5c5SAndroid Build Coastguard Worker     mCompileJob                     = std::make_shared<CompileJob>();
761*8975f5c5SAndroid Build Coastguard Worker     mCompileJob->shCompilerInstance = std::move(compilerInstance);
762*8975f5c5SAndroid Build Coastguard Worker     mCompileJob->compileEvent       = std::make_unique<CompileEvent>(compileTask, compileEvent);
763*8975f5c5SAndroid Build Coastguard Worker }
764*8975f5c5SAndroid Build Coastguard Worker 
resolveCompile(const Context * context)765*8975f5c5SAndroid Build Coastguard Worker void Shader::resolveCompile(const Context *context)
766*8975f5c5SAndroid Build Coastguard Worker {
767*8975f5c5SAndroid Build Coastguard Worker     if (!mState.compilePending())
768*8975f5c5SAndroid Build Coastguard Worker     {
769*8975f5c5SAndroid Build Coastguard Worker         return;
770*8975f5c5SAndroid Build Coastguard Worker     }
771*8975f5c5SAndroid Build Coastguard Worker 
772*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mCompileJob.get());
773*8975f5c5SAndroid Build Coastguard Worker     mState.mCompileStatus = CompileStatus::IS_RESOLVING;
774*8975f5c5SAndroid Build Coastguard Worker 
775*8975f5c5SAndroid Build Coastguard Worker     const bool success    = WaitCompileJobUnlocked(mCompileJob);
776*8975f5c5SAndroid Build Coastguard Worker     mInfoLog              = std::move(mCompileJob->compileEvent->getInfoLog());
777*8975f5c5SAndroid Build Coastguard Worker     mState.mCompileStatus = success ? CompileStatus::COMPILED : CompileStatus::NOT_COMPILED;
778*8975f5c5SAndroid Build Coastguard Worker 
779*8975f5c5SAndroid Build Coastguard Worker     if (mCompileJob->shCompilerInstance.getHandle())
780*8975f5c5SAndroid Build Coastguard Worker     {
781*8975f5c5SAndroid Build Coastguard Worker         // Only save this shader to the cache if it was a compile from source (not load from binary)
782*8975f5c5SAndroid Build Coastguard Worker         if (success)
783*8975f5c5SAndroid Build Coastguard Worker         {
784*8975f5c5SAndroid Build Coastguard Worker             MemoryShaderCache *shaderCache = context->getMemoryShaderCache();
785*8975f5c5SAndroid Build Coastguard Worker             if (shaderCache != nullptr)
786*8975f5c5SAndroid Build Coastguard Worker             {
787*8975f5c5SAndroid Build Coastguard Worker                 // Save to the shader cache.
788*8975f5c5SAndroid Build Coastguard Worker                 if (shaderCache->putShader(context, mShaderHash, this) != angle::Result::Continue)
789*8975f5c5SAndroid Build Coastguard Worker                 {
790*8975f5c5SAndroid Build Coastguard Worker                     ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
791*8975f5c5SAndroid Build Coastguard Worker                                        "Failed to save compiled shader to memory shader cache.");
792*8975f5c5SAndroid Build Coastguard Worker                 }
793*8975f5c5SAndroid Build Coastguard Worker             }
794*8975f5c5SAndroid Build Coastguard Worker         }
795*8975f5c5SAndroid Build Coastguard Worker 
796*8975f5c5SAndroid Build Coastguard Worker         mBoundCompiler->putInstance(std::move(mCompileJob->shCompilerInstance));
797*8975f5c5SAndroid Build Coastguard Worker     }
798*8975f5c5SAndroid Build Coastguard Worker     mCompileJob.reset();
799*8975f5c5SAndroid Build Coastguard Worker }
800*8975f5c5SAndroid Build Coastguard Worker 
addRef()801*8975f5c5SAndroid Build Coastguard Worker void Shader::addRef()
802*8975f5c5SAndroid Build Coastguard Worker {
803*8975f5c5SAndroid Build Coastguard Worker     mRefCount++;
804*8975f5c5SAndroid Build Coastguard Worker }
805*8975f5c5SAndroid Build Coastguard Worker 
release(const Context * context)806*8975f5c5SAndroid Build Coastguard Worker void Shader::release(const Context *context)
807*8975f5c5SAndroid Build Coastguard Worker {
808*8975f5c5SAndroid Build Coastguard Worker     mRefCount--;
809*8975f5c5SAndroid Build Coastguard Worker 
810*8975f5c5SAndroid Build Coastguard Worker     if (mRefCount == 0 && mDeleteStatus)
811*8975f5c5SAndroid Build Coastguard Worker     {
812*8975f5c5SAndroid Build Coastguard Worker         mResourceManager->deleteShader(context, mHandle);
813*8975f5c5SAndroid Build Coastguard Worker     }
814*8975f5c5SAndroid Build Coastguard Worker }
815*8975f5c5SAndroid Build Coastguard Worker 
getRefCount() const816*8975f5c5SAndroid Build Coastguard Worker unsigned int Shader::getRefCount() const
817*8975f5c5SAndroid Build Coastguard Worker {
818*8975f5c5SAndroid Build Coastguard Worker     return mRefCount;
819*8975f5c5SAndroid Build Coastguard Worker }
820*8975f5c5SAndroid Build Coastguard Worker 
isFlaggedForDeletion() const821*8975f5c5SAndroid Build Coastguard Worker bool Shader::isFlaggedForDeletion() const
822*8975f5c5SAndroid Build Coastguard Worker {
823*8975f5c5SAndroid Build Coastguard Worker     return mDeleteStatus;
824*8975f5c5SAndroid Build Coastguard Worker }
825*8975f5c5SAndroid Build Coastguard Worker 
flagForDeletion()826*8975f5c5SAndroid Build Coastguard Worker void Shader::flagForDeletion()
827*8975f5c5SAndroid Build Coastguard Worker {
828*8975f5c5SAndroid Build Coastguard Worker     mDeleteStatus = true;
829*8975f5c5SAndroid Build Coastguard Worker }
830*8975f5c5SAndroid Build Coastguard Worker 
isCompiled(const Context * context)831*8975f5c5SAndroid Build Coastguard Worker bool Shader::isCompiled(const Context *context)
832*8975f5c5SAndroid Build Coastguard Worker {
833*8975f5c5SAndroid Build Coastguard Worker     resolveCompile(context);
834*8975f5c5SAndroid Build Coastguard Worker     return mState.mCompileStatus == CompileStatus::COMPILED;
835*8975f5c5SAndroid Build Coastguard Worker }
836*8975f5c5SAndroid Build Coastguard Worker 
isCompleted()837*8975f5c5SAndroid Build Coastguard Worker bool Shader::isCompleted()
838*8975f5c5SAndroid Build Coastguard Worker {
839*8975f5c5SAndroid Build Coastguard Worker     return !mState.compilePending() || !mCompileJob->compileEvent->isCompiling();
840*8975f5c5SAndroid Build Coastguard Worker }
841*8975f5c5SAndroid Build Coastguard Worker 
getCompileJob(SharedCompiledShaderState * compiledStateOut)842*8975f5c5SAndroid Build Coastguard Worker SharedCompileJob Shader::getCompileJob(SharedCompiledShaderState *compiledStateOut)
843*8975f5c5SAndroid Build Coastguard Worker {
844*8975f5c5SAndroid Build Coastguard Worker     // mState.mCompiledState is the same as the one in the current compile job, because this call is
845*8975f5c5SAndroid Build Coastguard Worker     // made during link which expects to pick up the currently compiled (or pending compilation)
846*8975f5c5SAndroid Build Coastguard Worker     // state.
847*8975f5c5SAndroid Build Coastguard Worker     *compiledStateOut = mState.mCompiledState;
848*8975f5c5SAndroid Build Coastguard Worker 
849*8975f5c5SAndroid Build Coastguard Worker     if (mCompileJob)
850*8975f5c5SAndroid Build Coastguard Worker     {
851*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mState.compilePending());
852*8975f5c5SAndroid Build Coastguard Worker         return mCompileJob;
853*8975f5c5SAndroid Build Coastguard Worker     }
854*8975f5c5SAndroid Build Coastguard Worker 
855*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!mState.compilePending());
856*8975f5c5SAndroid Build Coastguard Worker     ASSERT(mState.mCompileStatus == CompileStatus::COMPILED ||
857*8975f5c5SAndroid Build Coastguard Worker            mState.mCompileStatus == CompileStatus::NOT_COMPILED);
858*8975f5c5SAndroid Build Coastguard Worker 
859*8975f5c5SAndroid Build Coastguard Worker     return std::make_shared<CompileJobDone>(mState.mCompileStatus == CompileStatus::COMPILED);
860*8975f5c5SAndroid Build Coastguard Worker }
861*8975f5c5SAndroid Build Coastguard Worker 
serialize(const Context * context,angle::MemoryBuffer * binaryOut) const862*8975f5c5SAndroid Build Coastguard Worker angle::Result Shader::serialize(const Context *context, angle::MemoryBuffer *binaryOut) const
863*8975f5c5SAndroid Build Coastguard Worker {
864*8975f5c5SAndroid Build Coastguard Worker     BinaryOutputStream stream;
865*8975f5c5SAndroid Build Coastguard Worker 
866*8975f5c5SAndroid Build Coastguard Worker     stream.writeInt(kShaderCacheIdentifier);
867*8975f5c5SAndroid Build Coastguard Worker     mState.mCompiledState->serialize(stream);
868*8975f5c5SAndroid Build Coastguard Worker 
869*8975f5c5SAndroid Build Coastguard Worker     ASSERT(binaryOut);
870*8975f5c5SAndroid Build Coastguard Worker     if (!binaryOut->resize(stream.length()))
871*8975f5c5SAndroid Build Coastguard Worker     {
872*8975f5c5SAndroid Build Coastguard Worker         ANGLE_PERF_WARNING(context->getState().getDebug(), GL_DEBUG_SEVERITY_LOW,
873*8975f5c5SAndroid Build Coastguard Worker                            "Failed to allocate enough memory to serialize a shader. (%zu bytes)",
874*8975f5c5SAndroid Build Coastguard Worker                            stream.length());
875*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Stop;
876*8975f5c5SAndroid Build Coastguard Worker     }
877*8975f5c5SAndroid Build Coastguard Worker 
878*8975f5c5SAndroid Build Coastguard Worker     memcpy(binaryOut->data(), stream.data(), stream.length());
879*8975f5c5SAndroid Build Coastguard Worker 
880*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
881*8975f5c5SAndroid Build Coastguard Worker }
882*8975f5c5SAndroid Build Coastguard Worker 
deserialize(BinaryInputStream & stream)883*8975f5c5SAndroid Build Coastguard Worker bool Shader::deserialize(BinaryInputStream &stream)
884*8975f5c5SAndroid Build Coastguard Worker {
885*8975f5c5SAndroid Build Coastguard Worker     mState.mCompiledState->deserialize(stream);
886*8975f5c5SAndroid Build Coastguard Worker 
887*8975f5c5SAndroid Build Coastguard Worker     if (stream.error())
888*8975f5c5SAndroid Build Coastguard Worker     {
889*8975f5c5SAndroid Build Coastguard Worker         // Error while deserializing binary stream
890*8975f5c5SAndroid Build Coastguard Worker         return false;
891*8975f5c5SAndroid Build Coastguard Worker     }
892*8975f5c5SAndroid Build Coastguard Worker 
893*8975f5c5SAndroid Build Coastguard Worker     // Note: Currently, shader binaries are only supported on backends that don't happen to have any
894*8975f5c5SAndroid Build Coastguard Worker     // additional state used at link time.  If other backends implement this functionality, this
895*8975f5c5SAndroid Build Coastguard Worker     // function should call into the backend object to deserialize their part.
896*8975f5c5SAndroid Build Coastguard Worker 
897*8975f5c5SAndroid Build Coastguard Worker     return true;
898*8975f5c5SAndroid Build Coastguard Worker }
899*8975f5c5SAndroid Build Coastguard Worker 
loadBinary(const Context * context,const void * binary,GLsizei length,angle::JobResultExpectancy resultExpectancy)900*8975f5c5SAndroid Build Coastguard Worker bool Shader::loadBinary(const Context *context,
901*8975f5c5SAndroid Build Coastguard Worker                         const void *binary,
902*8975f5c5SAndroid Build Coastguard Worker                         GLsizei length,
903*8975f5c5SAndroid Build Coastguard Worker                         angle::JobResultExpectancy resultExpectancy)
904*8975f5c5SAndroid Build Coastguard Worker {
905*8975f5c5SAndroid Build Coastguard Worker     return loadBinaryImpl(context, binary, length, resultExpectancy, false);
906*8975f5c5SAndroid Build Coastguard Worker }
907*8975f5c5SAndroid Build Coastguard Worker 
loadShaderBinary(const Context * context,const void * binary,GLsizei length,angle::JobResultExpectancy resultExpectancy)908*8975f5c5SAndroid Build Coastguard Worker bool Shader::loadShaderBinary(const Context *context,
909*8975f5c5SAndroid Build Coastguard Worker                               const void *binary,
910*8975f5c5SAndroid Build Coastguard Worker                               GLsizei length,
911*8975f5c5SAndroid Build Coastguard Worker                               angle::JobResultExpectancy resultExpectancy)
912*8975f5c5SAndroid Build Coastguard Worker {
913*8975f5c5SAndroid Build Coastguard Worker     return loadBinaryImpl(context, binary, length, resultExpectancy, true);
914*8975f5c5SAndroid Build Coastguard Worker }
915*8975f5c5SAndroid Build Coastguard Worker 
loadBinaryImpl(const Context * context,const void * binary,GLsizei length,angle::JobResultExpectancy resultExpectancy,bool generatedWithOfflineCompiler)916*8975f5c5SAndroid Build Coastguard Worker bool Shader::loadBinaryImpl(const Context *context,
917*8975f5c5SAndroid Build Coastguard Worker                             const void *binary,
918*8975f5c5SAndroid Build Coastguard Worker                             GLsizei length,
919*8975f5c5SAndroid Build Coastguard Worker                             angle::JobResultExpectancy resultExpectancy,
920*8975f5c5SAndroid Build Coastguard Worker                             bool generatedWithOfflineCompiler)
921*8975f5c5SAndroid Build Coastguard Worker {
922*8975f5c5SAndroid Build Coastguard Worker     BinaryInputStream stream(binary, length);
923*8975f5c5SAndroid Build Coastguard Worker 
924*8975f5c5SAndroid Build Coastguard Worker     mState.mCompiledState = std::make_shared<CompiledShaderState>(mState.getShaderType());
925*8975f5c5SAndroid Build Coastguard Worker 
926*8975f5c5SAndroid Build Coastguard Worker     // Shader binaries generated with offline compiler have additional fields
927*8975f5c5SAndroid Build Coastguard Worker     if (generatedWithOfflineCompiler)
928*8975f5c5SAndroid Build Coastguard Worker     {
929*8975f5c5SAndroid Build Coastguard Worker         // Load binary from a glShaderBinary call.
930*8975f5c5SAndroid Build Coastguard Worker         // Validation layer should have already verified that the shader program version and shader
931*8975f5c5SAndroid Build Coastguard Worker         // type match
932*8975f5c5SAndroid Build Coastguard Worker         std::vector<uint8_t> commitString(angle::GetANGLEShaderProgramVersionHashSize(), 0);
933*8975f5c5SAndroid Build Coastguard Worker         stream.readBytes(commitString.data(), commitString.size());
934*8975f5c5SAndroid Build Coastguard Worker         ASSERT(memcmp(commitString.data(), angle::GetANGLEShaderProgramVersion(),
935*8975f5c5SAndroid Build Coastguard Worker                       commitString.size()) == 0);
936*8975f5c5SAndroid Build Coastguard Worker 
937*8975f5c5SAndroid Build Coastguard Worker         gl::ShaderType shaderType;
938*8975f5c5SAndroid Build Coastguard Worker         stream.readEnum(&shaderType);
939*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mState.getShaderType() == shaderType);
940*8975f5c5SAndroid Build Coastguard Worker 
941*8975f5c5SAndroid Build Coastguard Worker         // Get fields needed to generate the key for memory caches.
942*8975f5c5SAndroid Build Coastguard Worker         ShShaderOutput outputType;
943*8975f5c5SAndroid Build Coastguard Worker         stream.readEnum<ShShaderOutput>(&outputType);
944*8975f5c5SAndroid Build Coastguard Worker 
945*8975f5c5SAndroid Build Coastguard Worker         // Get the shader's source string.
946*8975f5c5SAndroid Build Coastguard Worker         mState.mSource = stream.readString();
947*8975f5c5SAndroid Build Coastguard Worker 
948*8975f5c5SAndroid Build Coastguard Worker         // In the absence of element-by-element serialize/deserialize functions, read
949*8975f5c5SAndroid Build Coastguard Worker         // ShCompileOptions and ShBuiltInResources as raw binary blobs.
950*8975f5c5SAndroid Build Coastguard Worker         ShCompileOptions compileOptions;
951*8975f5c5SAndroid Build Coastguard Worker         stream.readBytes(reinterpret_cast<uint8_t *>(&compileOptions), sizeof(ShCompileOptions));
952*8975f5c5SAndroid Build Coastguard Worker 
953*8975f5c5SAndroid Build Coastguard Worker         ShBuiltInResources resources;
954*8975f5c5SAndroid Build Coastguard Worker         stream.readBytes(reinterpret_cast<uint8_t *>(&resources), sizeof(ShBuiltInResources));
955*8975f5c5SAndroid Build Coastguard Worker 
956*8975f5c5SAndroid Build Coastguard Worker         setShaderKey(context, compileOptions, outputType, resources);
957*8975f5c5SAndroid Build Coastguard Worker     }
958*8975f5c5SAndroid Build Coastguard Worker     else
959*8975f5c5SAndroid Build Coastguard Worker     {
960*8975f5c5SAndroid Build Coastguard Worker         // Load binary from shader cache.
961*8975f5c5SAndroid Build Coastguard Worker         if (stream.readInt<uint32_t>() != kShaderCacheIdentifier)
962*8975f5c5SAndroid Build Coastguard Worker         {
963*8975f5c5SAndroid Build Coastguard Worker             return false;
964*8975f5c5SAndroid Build Coastguard Worker         }
965*8975f5c5SAndroid Build Coastguard Worker     }
966*8975f5c5SAndroid Build Coastguard Worker 
967*8975f5c5SAndroid Build Coastguard Worker     if (!deserialize(stream))
968*8975f5c5SAndroid Build Coastguard Worker     {
969*8975f5c5SAndroid Build Coastguard Worker         return false;
970*8975f5c5SAndroid Build Coastguard Worker     }
971*8975f5c5SAndroid Build Coastguard Worker 
972*8975f5c5SAndroid Build Coastguard Worker     mState.mCompileStatus = CompileStatus::COMPILE_REQUESTED;
973*8975f5c5SAndroid Build Coastguard Worker 
974*8975f5c5SAndroid Build Coastguard Worker     // Ask the backend to prepare the translate task
975*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<rx::ShaderTranslateTask> translateTask =
976*8975f5c5SAndroid Build Coastguard Worker         mImplementation->load(context, &stream);
977*8975f5c5SAndroid Build Coastguard Worker 
978*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<CompileTask> compileTask(new CompileTask(
979*8975f5c5SAndroid Build Coastguard Worker         context->getFrontendFeatures(), mState.mCompiledState, std::move(translateTask)));
980*8975f5c5SAndroid Build Coastguard Worker 
981*8975f5c5SAndroid Build Coastguard Worker     const angle::JobThreadSafety threadSafety = GetTranslateTaskThreadSafety(context);
982*8975f5c5SAndroid Build Coastguard Worker     std::shared_ptr<angle::WaitableEvent> compileEvent =
983*8975f5c5SAndroid Build Coastguard Worker         context->postCompileLinkTask(compileTask, threadSafety, resultExpectancy);
984*8975f5c5SAndroid Build Coastguard Worker 
985*8975f5c5SAndroid Build Coastguard Worker     mCompileJob               = std::make_shared<CompileJob>();
986*8975f5c5SAndroid Build Coastguard Worker     mCompileJob->compileEvent = std::make_unique<CompileEvent>(compileTask, compileEvent);
987*8975f5c5SAndroid Build Coastguard Worker 
988*8975f5c5SAndroid Build Coastguard Worker     return true;
989*8975f5c5SAndroid Build Coastguard Worker }
990*8975f5c5SAndroid Build Coastguard Worker 
setShaderKey(const Context * context,const ShCompileOptions & compileOptions,const ShShaderOutput & outputType,const ShBuiltInResources & resources)991*8975f5c5SAndroid Build Coastguard Worker void Shader::setShaderKey(const Context *context,
992*8975f5c5SAndroid Build Coastguard Worker                           const ShCompileOptions &compileOptions,
993*8975f5c5SAndroid Build Coastguard Worker                           const ShShaderOutput &outputType,
994*8975f5c5SAndroid Build Coastguard Worker                           const ShBuiltInResources &resources)
995*8975f5c5SAndroid Build Coastguard Worker {
996*8975f5c5SAndroid Build Coastguard Worker     // Compute shader key.
997*8975f5c5SAndroid Build Coastguard Worker     angle::base::SecureHashAlgorithm hasher;
998*8975f5c5SAndroid Build Coastguard Worker     hasher.Init();
999*8975f5c5SAndroid Build Coastguard Worker 
1000*8975f5c5SAndroid Build Coastguard Worker     // Start with the shader type and source.
1001*8975f5c5SAndroid Build Coastguard Worker     AppendHashValue(hasher, mState.getShaderType());
1002*8975f5c5SAndroid Build Coastguard Worker     hasher.Update(mState.getSource().c_str(), mState.getSource().length());
1003*8975f5c5SAndroid Build Coastguard Worker 
1004*8975f5c5SAndroid Build Coastguard Worker     // Include the shader program version hash.
1005*8975f5c5SAndroid Build Coastguard Worker     hasher.Update(angle::GetANGLEShaderProgramVersion(),
1006*8975f5c5SAndroid Build Coastguard Worker                   angle::GetANGLEShaderProgramVersionHashSize());
1007*8975f5c5SAndroid Build Coastguard Worker 
1008*8975f5c5SAndroid Build Coastguard Worker     AppendHashValue(hasher, Compiler::SelectShaderSpec(context->getState()));
1009*8975f5c5SAndroid Build Coastguard Worker     AppendHashValue(hasher, outputType);
1010*8975f5c5SAndroid Build Coastguard Worker     hasher.Update(reinterpret_cast<const uint8_t *>(&compileOptions), sizeof(compileOptions));
1011*8975f5c5SAndroid Build Coastguard Worker 
1012*8975f5c5SAndroid Build Coastguard Worker     // Include the ShBuiltInResources, which represent the extensions and constants used by the
1013*8975f5c5SAndroid Build Coastguard Worker     // shader.
1014*8975f5c5SAndroid Build Coastguard Worker     hasher.Update(reinterpret_cast<const uint8_t *>(&resources), sizeof(resources));
1015*8975f5c5SAndroid Build Coastguard Worker 
1016*8975f5c5SAndroid Build Coastguard Worker     // Call the secure SHA hashing function.
1017*8975f5c5SAndroid Build Coastguard Worker     hasher.Final();
1018*8975f5c5SAndroid Build Coastguard Worker     memcpy(mShaderHash.data(), hasher.Digest(), angle::base::kSHA1Length);
1019*8975f5c5SAndroid Build Coastguard Worker }
1020*8975f5c5SAndroid Build Coastguard Worker 
WaitCompileJobUnlocked(const SharedCompileJob & compileJob)1021*8975f5c5SAndroid Build Coastguard Worker bool WaitCompileJobUnlocked(const SharedCompileJob &compileJob)
1022*8975f5c5SAndroid Build Coastguard Worker {
1023*8975f5c5SAndroid Build Coastguard Worker     // Simply wait for the job and return whether it succeeded.  Do nothing more as this can be
1024*8975f5c5SAndroid Build Coastguard Worker     // called from multiple threads.  Caching of the shader results and compiler clean up will be
1025*8975f5c5SAndroid Build Coastguard Worker     // done in resolveCompile() when the main thread happens to call it.
1026*8975f5c5SAndroid Build Coastguard Worker     return compileJob->wait();
1027*8975f5c5SAndroid Build Coastguard Worker }
1028*8975f5c5SAndroid Build Coastguard Worker }  // namespace gl
1029