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