blob: 3ebcab2f8407eb210512475c0938d2ebe822ee38 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Shader.cpp: Implements the gl::Shader class and its derived classes
8// VertexShader and FragmentShader. Implements GL shader objects and related
9// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
10
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Shader.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040012
jchen10a155bac2018-08-16 15:26:39 +080013#include <functional>
Geoff Lang0b7eef72014-06-12 14:10:47 -040014#include <sstream>
15
Jamie Madill91445bc2015-09-23 16:47:53 -040016#include "GLSLANG/ShaderLang.h"
Jamie Madill493f9572018-05-24 19:52:15 -040017#include "common/utilities.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040018#include "libANGLE/Caps.h"
Jamie Madill006cbc52015-09-23 16:47:54 -040019#include "libANGLE/Compiler.h"
Jamie Madill91445bc2015-09-23 16:47:53 -040020#include "libANGLE/Constants.h"
Jamie Madill493f9572018-05-24 19:52:15 -040021#include "libANGLE/Context.h"
22#include "libANGLE/ResourceManager.h"
jchen10a155bac2018-08-16 15:26:39 +080023#include "libANGLE/WorkerThread.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040024#include "libANGLE/renderer/GLImplFactory.h"
Jamie Madill91445bc2015-09-23 16:47:53 -040025#include "libANGLE/renderer/ShaderImpl.h"
Jamie Madill91445bc2015-09-23 16:47:53 -040026
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000027namespace gl
28{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000029
Jamie Madill006cbc52015-09-23 16:47:54 -040030namespace
31{
32template <typename VarT>
33std::vector<VarT> GetActiveShaderVariables(const std::vector<VarT> *variableList)
34{
35 ASSERT(variableList);
36 std::vector<VarT> result;
37 for (size_t varIndex = 0; varIndex < variableList->size(); varIndex++)
38 {
39 const VarT &var = variableList->at(varIndex);
Olli Etuaho107c7242018-03-20 15:45:35 +020040 if (var.active)
Jamie Madill006cbc52015-09-23 16:47:54 -040041 {
42 result.push_back(var);
43 }
44 }
45 return result;
46}
47
48template <typename VarT>
49const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableList)
50{
51 ASSERT(variableList);
52 return *variableList;
53}
54
Jamie Madill9fc36822015-11-18 13:08:07 -050055} // anonymous namespace
56
Jamie Madill006cbc52015-09-23 16:47:54 -040057// true if varying x has a higher priority in packing than y
Jamie Madill55c25d02015-11-18 13:08:08 -050058bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
Jamie Madill006cbc52015-09-23 16:47:54 -040059{
60 if (x.type == y.type)
61 {
Olli Etuaho465835d2017-09-26 13:34:10 +030062 return x.getArraySizeProduct() > y.getArraySizeProduct();
Jamie Madill006cbc52015-09-23 16:47:54 -040063 }
64
65 // Special case for handling structs: we sort these to the end of the list
Jamie Madillf00f7ff2017-08-31 14:39:15 -040066 if (x.type == GL_NONE)
Jamie Madill006cbc52015-09-23 16:47:54 -040067 {
68 return false;
69 }
70
Jamie Madillf00f7ff2017-08-31 14:39:15 -040071 if (y.type == GL_NONE)
Jamie Madill006cbc52015-09-23 16:47:54 -040072 {
73 return true;
74 }
75
76 return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
77}
78
Jiawei Shao385b3e02018-03-21 09:43:28 +080079const char *GetShaderTypeString(ShaderType type)
Jiawei Shao881b7bf2017-12-25 11:18:37 +080080{
81 switch (type)
82 {
Jiawei Shao385b3e02018-03-21 09:43:28 +080083 case ShaderType::Vertex:
Jiawei Shao881b7bf2017-12-25 11:18:37 +080084 return "VERTEX";
85
Jiawei Shao385b3e02018-03-21 09:43:28 +080086 case ShaderType::Fragment:
Jiawei Shao881b7bf2017-12-25 11:18:37 +080087 return "FRAGMENT";
88
Jiawei Shao385b3e02018-03-21 09:43:28 +080089 case ShaderType::Compute:
Jiawei Shao881b7bf2017-12-25 11:18:37 +080090 return "COMPUTE";
91
Jiawei Shao385b3e02018-03-21 09:43:28 +080092 case ShaderType::Geometry:
Jiawei Shao881b7bf2017-12-25 11:18:37 +080093 return "GEOMETRY";
94
95 default:
96 UNREACHABLE();
97 return "";
98 }
99}
100
jchen10a155bac2018-08-16 15:26:39 +0800101class ScopedExit final : angle::NonCopyable
102{
103 public:
104 ScopedExit(std::function<void()> exit) : mExit(exit) {}
105 ~ScopedExit() { mExit(); }
106
107 private:
108 std::function<void()> mExit;
109};
110
111class CompileTask : public angle::Closure
112{
113 public:
114 CompileTask(ShHandle handle,
115 std::string &&sourcePath,
116 std::string &&source,
117 ShCompileOptions options)
118 : mHandle(handle),
119 mSourcePath(sourcePath),
120 mSource(source),
121 mOptions(options),
122 mResult(false)
123 {
124 }
125 void operator()() override
126 {
127 std::vector<const char *> srcStrings;
128 if (!mSourcePath.empty())
129 {
130 srcStrings.push_back(mSourcePath.c_str());
131 }
132 srcStrings.push_back(mSource.c_str());
133 mResult = sh::Compile(mHandle, &srcStrings[0], srcStrings.size(), mOptions);
134 }
135 bool getResult() { return mResult; }
136
137 private:
138 ShHandle mHandle;
139 std::string mSourcePath;
140 std::string mSource;
141 ShCompileOptions mOptions;
142 bool mResult;
143};
144
Jiawei Shao385b3e02018-03-21 09:43:28 +0800145ShaderState::ShaderState(ShaderType shaderType)
Jamie Madill34ca4f52017-06-13 11:49:39 -0400146 : mLabel(),
147 mShaderType(shaderType),
148 mShaderVersion(100),
Martin Radev7cf61662017-07-26 17:10:53 +0300149 mNumViews(-1),
Jiawei Shao89be29a2017-11-06 14:36:45 +0800150 mGeometryShaderInvocations(1),
Jamie Madill34ca4f52017-06-13 11:49:39 -0400151 mCompileStatus(CompileStatus::NOT_COMPILED)
Jamie Madill91445bc2015-09-23 16:47:53 -0400152{
Martin Radev4c4c8e72016-08-04 12:25:34 +0300153 mLocalSize.fill(-1);
Jamie Madill91445bc2015-09-23 16:47:53 -0400154}
155
Jamie Madill15243d92016-04-26 13:41:35 -0400156ShaderState::~ShaderState()
Jamie Madill91445bc2015-09-23 16:47:53 -0400157{
158}
159
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500160Shader::Shader(ShaderProgramManager *manager,
Jamie Madill7aea7e02016-05-10 10:39:45 -0400161 rx::GLImplFactory *implFactory,
Jamie Madill006cbc52015-09-23 16:47:54 -0400162 const gl::Limitations &rendererLimitations,
Jiawei Shao385b3e02018-03-21 09:43:28 +0800163 ShaderType type,
Jamie Madill006cbc52015-09-23 16:47:54 -0400164 GLuint handle)
Jamie Madill15243d92016-04-26 13:41:35 -0400165 : mState(type),
166 mImplementation(implFactory->createShader(mState)),
Jamie Madill006cbc52015-09-23 16:47:54 -0400167 mRendererLimitations(rendererLimitations),
Brandon Jonesf05cdee2014-08-27 15:24:07 -0700168 mHandle(handle),
Corentin Wallezbc99bb62015-05-14 17:42:20 -0400169 mType(type),
Brandon Jonesf05cdee2014-08-27 15:24:07 -0700170 mRefCount(0),
171 mDeleteStatus(false),
jchen103fd614d2018-08-13 12:21:58 +0800172 mResourceManager(manager),
173 mCurrentMaxComputeWorkGroupInvocations(0u)
Jamie Madille294bb82014-07-17 14:16:26 -0400174{
Jamie Madill91445bc2015-09-23 16:47:53 -0400175 ASSERT(mImplementation);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176}
177
Jamie Madill4928b7c2017-06-20 12:57:39 -0400178void Shader::onDestroy(const gl::Context *context)
179{
jchen10a155bac2018-08-16 15:26:39 +0800180 resolveCompile();
jchen103fd614d2018-08-13 12:21:58 +0800181 mImplementation->destroy();
Jamie Madill4928b7c2017-06-20 12:57:39 -0400182 mBoundCompiler.set(context, nullptr);
183 mImplementation.reset(nullptr);
184 delete this;
185}
186
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187Shader::~Shader()
188{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400189 ASSERT(!mImplementation);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000190}
191
Geoff Lang70d0f492015-12-10 17:45:46 -0500192void Shader::setLabel(const std::string &label)
193{
Jamie Madill15243d92016-04-26 13:41:35 -0400194 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500195}
196
197const std::string &Shader::getLabel() const
198{
Jamie Madill15243d92016-04-26 13:41:35 -0400199 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500200}
201
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000202GLuint Shader::getHandle() const
203{
204 return mHandle;
205}
206
shannon.woods%transgaming.com@gtempaccount.com5f339332013-04-13 03:29:02 +0000207void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000208{
Geoff Lang536d7262013-08-26 17:04:20 -0400209 std::ostringstream stream;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000210
211 for (int i = 0; i < count; i++)
212 {
Geoff Langf60fab62014-11-24 11:21:20 -0500213 if (length == nullptr || length[i] < 0)
214 {
Jamie Madille7cfb3d2014-12-03 10:58:56 -0500215 stream.write(string[i], strlen(string[i]));
Geoff Langf60fab62014-11-24 11:21:20 -0500216 }
217 else
218 {
219 stream.write(string[i], length[i]);
220 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221 }
222
Jamie Madill15243d92016-04-26 13:41:35 -0400223 mState.mSource = stream.str();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224}
225
jchen103fd614d2018-08-13 12:21:58 +0800226int Shader::getInfoLogLength()
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000227{
jchen103fd614d2018-08-13 12:21:58 +0800228 resolveCompile();
Jamie Madill006cbc52015-09-23 16:47:54 -0400229 if (mInfoLog.empty())
Jamie Madill91445bc2015-09-23 16:47:53 -0400230 {
231 return 0;
232 }
233
Jamie Madill006cbc52015-09-23 16:47:54 -0400234 return (static_cast<int>(mInfoLog.length()) + 1);
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000235}
236
jchen103fd614d2018-08-13 12:21:58 +0800237void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000238{
jchen103fd614d2018-08-13 12:21:58 +0800239 resolveCompile();
Jamie Madillbd044ed2017-06-05 12:59:21 -0400240
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000241 int index = 0;
242
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000243 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000244 {
Jamie Madill006cbc52015-09-23 16:47:54 -0400245 index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
246 memcpy(infoLog, mInfoLog.c_str(), index);
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000247
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000248 infoLog[index] = '\0';
249 }
250
251 if (length)
252 {
253 *length = index;
254 }
255}
256
257int Shader::getSourceLength() const
258{
Jamie Madill15243d92016-04-26 13:41:35 -0400259 return mState.mSource.empty() ? 0 : (static_cast<int>(mState.mSource.length()) + 1);
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000260}
261
jchen103fd614d2018-08-13 12:21:58 +0800262int Shader::getTranslatedSourceLength()
zmo@google.coma574f782011-10-03 21:45:23 +0000263{
jchen103fd614d2018-08-13 12:21:58 +0800264 resolveCompile();
Jamie Madillbd044ed2017-06-05 12:59:21 -0400265
Jamie Madill15243d92016-04-26 13:41:35 -0400266 if (mState.mTranslatedSource.empty())
Jamie Madill91445bc2015-09-23 16:47:53 -0400267 {
268 return 0;
269 }
270
Jamie Madill15243d92016-04-26 13:41:35 -0400271 return (static_cast<int>(mState.mTranslatedSource.length()) + 1);
zmo@google.coma574f782011-10-03 21:45:23 +0000272}
273
jchen103fd614d2018-08-13 12:21:58 +0800274int Shader::getTranslatedSourceWithDebugInfoLength()
Jamie Madill847638a2015-11-20 13:01:41 -0500275{
jchen103fd614d2018-08-13 12:21:58 +0800276 resolveCompile();
Jamie Madillbd044ed2017-06-05 12:59:21 -0400277
jchen103fd614d2018-08-13 12:21:58 +0800278 const std::string &debugInfo = mImplementation->getDebugInfo();
Jamie Madill847638a2015-11-20 13:01:41 -0500279 if (debugInfo.empty())
280 {
281 return 0;
282 }
283
284 return (static_cast<int>(debugInfo.length()) + 1);
285}
286
Jamie Madillbd044ed2017-06-05 12:59:21 -0400287// static
288void Shader::GetSourceImpl(const std::string &source,
289 GLsizei bufSize,
290 GLsizei *length,
291 char *buffer)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000292{
293 int index = 0;
294
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000295 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000296 {
Geoff Lang536d7262013-08-26 17:04:20 -0400297 index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
298 memcpy(buffer, source.c_str(), index);
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000299
zmo@google.coma574f782011-10-03 21:45:23 +0000300 buffer[index] = '\0';
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000301 }
302
303 if (length)
304 {
305 *length = index;
306 }
307}
308
Geoff Lang536d7262013-08-26 17:04:20 -0400309void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
zmo@google.coma574f782011-10-03 21:45:23 +0000310{
Jamie Madillbd044ed2017-06-05 12:59:21 -0400311 GetSourceImpl(mState.mSource, bufSize, length, buffer);
zmo@google.coma574f782011-10-03 21:45:23 +0000312}
313
jchen103fd614d2018-08-13 12:21:58 +0800314void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
zmo@google.coma574f782011-10-03 21:45:23 +0000315{
jchen103fd614d2018-08-13 12:21:58 +0800316 GetSourceImpl(getTranslatedSource(), bufSize, length, buffer);
zmo@google.coma574f782011-10-03 21:45:23 +0000317}
318
jchen103fd614d2018-08-13 12:21:58 +0800319const std::string &Shader::getTranslatedSource()
Tibor den Ouden97049c62014-10-06 21:39:16 +0200320{
jchen103fd614d2018-08-13 12:21:58 +0800321 resolveCompile();
Jamie Madillbd044ed2017-06-05 12:59:21 -0400322 return mState.mTranslatedSource;
323}
324
jchen103fd614d2018-08-13 12:21:58 +0800325void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer)
Jamie Madillbd044ed2017-06-05 12:59:21 -0400326{
jchen103fd614d2018-08-13 12:21:58 +0800327 resolveCompile();
328 const std::string &debugInfo = mImplementation->getDebugInfo();
Jamie Madillbd044ed2017-06-05 12:59:21 -0400329 GetSourceImpl(debugInfo, bufSize, length, buffer);
Tibor den Ouden97049c62014-10-06 21:39:16 +0200330}
331
Bryan Bernhart619c8332016-11-09 11:11:41 -0800332void Shader::compile(const Context *context)
Jamie Madillbf9cce22014-07-18 10:33:09 -0400333{
jchen10a155bac2018-08-16 15:26:39 +0800334 resolveCompile();
335
Jamie Madill15243d92016-04-26 13:41:35 -0400336 mState.mTranslatedSource.clear();
Jamie Madill006cbc52015-09-23 16:47:54 -0400337 mInfoLog.clear();
Jamie Madill15243d92016-04-26 13:41:35 -0400338 mState.mShaderVersion = 100;
Jiawei Shao3d404882017-10-16 13:30:48 +0800339 mState.mInputVaryings.clear();
340 mState.mOutputVaryings.clear();
Jamie Madill15243d92016-04-26 13:41:35 -0400341 mState.mUniforms.clear();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800342 mState.mUniformBlocks.clear();
343 mState.mShaderStorageBlocks.clear();
Jamie Madill15243d92016-04-26 13:41:35 -0400344 mState.mActiveAttributes.clear();
345 mState.mActiveOutputVariables.clear();
Martin Radev7cf61662017-07-26 17:10:53 +0300346 mState.mNumViews = -1;
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800347 mState.mGeometryShaderInputPrimitiveType.reset();
348 mState.mGeometryShaderOutputPrimitiveType.reset();
349 mState.mGeometryShaderMaxVertices.reset();
350 mState.mGeometryShaderInvocations = 1;
Jamie Madill91445bc2015-09-23 16:47:53 -0400351
Jamie Madill34ca4f52017-06-13 11:49:39 -0400352 mState.mCompileStatus = CompileStatus::COMPILE_REQUESTED;
Jamie Madill4928b7c2017-06-20 12:57:39 -0400353 mBoundCompiler.set(context, context->getCompiler());
Jamie Madillbd044ed2017-06-05 12:59:21 -0400354
355 // Cache the compile source and options for compilation. Must be done now, since the source
356 // can change before the link call or another call that resolves the compile.
Jamie Madill006cbc52015-09-23 16:47:54 -0400357
358 std::stringstream sourceStream;
jchen10a155bac2018-08-16 15:26:39 +0800359 std::string sourcePath;
360 ShCompileOptions options =
361 mImplementation->prepareSourceAndReturnOptions(context, &sourceStream, &sourcePath);
362 options |= (SH_OBJECT_CODE | SH_VARIABLES);
363 auto source = sourceStream.str();
Jamie Madill006cbc52015-09-23 16:47:54 -0400364
Bryan Bernhart619c8332016-11-09 11:11:41 -0800365 // Add default options to WebGL shaders to prevent unexpected behavior during compilation.
366 if (context->getExtensions().webglCompatibility)
367 {
jchen10a155bac2018-08-16 15:26:39 +0800368 options |= SH_INIT_GL_POSITION;
369 options |= SH_LIMIT_CALL_STACK_DEPTH;
370 options |= SH_LIMIT_EXPRESSION_COMPLEXITY;
371 options |= SH_ENFORCE_PACKING_RESTRICTIONS;
Bryan Bernhart619c8332016-11-09 11:11:41 -0800372 }
373
Jamie Madill006cbc52015-09-23 16:47:54 -0400374 // Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes
375 // in fragment shaders. Shader compilation will fail. To provide a better error message we can
376 // instruct the compiler to pre-validate.
377 if (mRendererLimitations.shadersRequireIndexedLoopValidation)
378 {
jchen10a155bac2018-08-16 15:26:39 +0800379 options |= SH_VALIDATE_LOOP_INDEXING;
Jamie Madill006cbc52015-09-23 16:47:54 -0400380 }
jchen103fd614d2018-08-13 12:21:58 +0800381
382 mCurrentMaxComputeWorkGroupInvocations = context->getCaps().maxComputeWorkGroupInvocations;
jchen10a155bac2018-08-16 15:26:39 +0800383
384 ASSERT(mBoundCompiler.get());
385 mShCompilerInstance = mBoundCompiler->getInstance(mState.mShaderType);
386 ShHandle compilerHandle = mShCompilerInstance.getHandle();
387 ASSERT(compilerHandle);
388 mCompilerResourcesString = mShCompilerInstance.getBuiltinResourcesString();
389
390 mCompileTask = std::make_shared<CompileTask>(compilerHandle, std::move(sourcePath),
391 std::move(source), options);
392 mWorkerPool = context->getWorkerThreadPool();
393 mCompileEvent = mWorkerPool->postWorkerTask(mCompileTask);
Jamie Madillbd044ed2017-06-05 12:59:21 -0400394}
Jamie Madill006cbc52015-09-23 16:47:54 -0400395
jchen103fd614d2018-08-13 12:21:58 +0800396void Shader::resolveCompile()
Jamie Madillbd044ed2017-06-05 12:59:21 -0400397{
Jamie Madill34ca4f52017-06-13 11:49:39 -0400398 if (!mState.compilePending())
Jamie Madilld2c52e32015-10-14 17:07:05 -0400399 {
Jamie Madillbd044ed2017-06-05 12:59:21 -0400400 return;
Jamie Madilld2c52e32015-10-14 17:07:05 -0400401 }
402
jchen10a155bac2018-08-16 15:26:39 +0800403 ASSERT(mCompileEvent.get());
404 ASSERT(mCompileTask.get());
Jamie Madilld2c52e32015-10-14 17:07:05 -0400405
jchen10a155bac2018-08-16 15:26:39 +0800406 mCompileEvent->wait();
Jamie Madill006cbc52015-09-23 16:47:54 -0400407
jchen10a155bac2018-08-16 15:26:39 +0800408 mCompileEvent.reset();
409 mWorkerPool.reset();
Jamie Madillbd044ed2017-06-05 12:59:21 -0400410
jchen10a155bac2018-08-16 15:26:39 +0800411 bool compiled = mCompileTask->getResult();
412 mCompileTask.reset();
Jamie Madillbd044ed2017-06-05 12:59:21 -0400413
jchen10a155bac2018-08-16 15:26:39 +0800414 ScopedExit exit([this]() { mBoundCompiler->putInstance(std::move(mShCompilerInstance)); });
415
416 ShHandle compilerHandle = mShCompilerInstance.getHandle();
417 if (!compiled)
Jamie Madill006cbc52015-09-23 16:47:54 -0400418 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500419 mInfoLog = sh::GetInfoLog(compilerHandle);
Yuly Novikovd73f8522017-01-13 17:48:57 -0500420 WARN() << std::endl << mInfoLog;
Jamie Madill34ca4f52017-06-13 11:49:39 -0400421 mState.mCompileStatus = CompileStatus::NOT_COMPILED;
Jamie Madill006cbc52015-09-23 16:47:54 -0400422 return;
423 }
424
Jamie Madillacb4b812016-11-07 13:50:29 -0500425 mState.mTranslatedSource = sh::GetObjectCode(compilerHandle);
Jamie Madill006cbc52015-09-23 16:47:54 -0400426
Jamie Madillbd044ed2017-06-05 12:59:21 -0400427#if !defined(NDEBUG)
Jamie Madill006cbc52015-09-23 16:47:54 -0400428 // Prefix translated shader with commented out un-translated shader.
429 // Useful in diagnostics tools which capture the shader source.
430 std::ostringstream shaderStream;
431 shaderStream << "// GLSL\n";
432 shaderStream << "//\n";
433
Geoff Lang9e1bf102017-03-28 15:10:48 -0400434 std::istringstream inputSourceStream(mState.mSource);
435 std::string line;
436 while (std::getline(inputSourceStream, line))
Jamie Madill006cbc52015-09-23 16:47:54 -0400437 {
Geoff Lang9e1bf102017-03-28 15:10:48 -0400438 // Remove null characters from the source line
439 line.erase(std::remove(line.begin(), line.end(), '\0'), line.end());
Jamie Madill006cbc52015-09-23 16:47:54 -0400440
Geoff Langab4be842017-07-18 11:23:07 -0400441 shaderStream << "// " << line << std::endl;
Jamie Madill006cbc52015-09-23 16:47:54 -0400442 }
443 shaderStream << "\n\n";
Jamie Madill15243d92016-04-26 13:41:35 -0400444 shaderStream << mState.mTranslatedSource;
445 mState.mTranslatedSource = shaderStream.str();
Jamie Madillbd044ed2017-06-05 12:59:21 -0400446#endif // !defined(NDEBUG)
Jamie Madill006cbc52015-09-23 16:47:54 -0400447
448 // Gather the shader information
Jamie Madillacb4b812016-11-07 13:50:29 -0500449 mState.mShaderVersion = sh::GetShaderVersion(compilerHandle);
Jamie Madill006cbc52015-09-23 16:47:54 -0400450
Jamie Madill493f9572018-05-24 19:52:15 -0400451 mState.mUniforms = GetShaderVariables(sh::GetUniforms(compilerHandle));
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800452 mState.mUniformBlocks = GetShaderVariables(sh::GetUniformBlocks(compilerHandle));
453 mState.mShaderStorageBlocks = GetShaderVariables(sh::GetShaderStorageBlocks(compilerHandle));
Jamie Madill006cbc52015-09-23 16:47:54 -0400454
Martin Radev4c4c8e72016-08-04 12:25:34 +0300455 switch (mState.mShaderType)
Jamie Madill006cbc52015-09-23 16:47:54 -0400456 {
Jiawei Shao385b3e02018-03-21 09:43:28 +0800457 case ShaderType::Compute:
Martin Radev4c4c8e72016-08-04 12:25:34 +0300458 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500459 mState.mLocalSize = sh::GetComputeShaderLocalGroupSize(compilerHandle);
Xinghua Cao77a2b4c2018-05-21 17:28:29 +0800460 if (mState.mLocalSize.isDeclared())
461 {
462 angle::CheckedNumeric<uint32_t> checked_local_size_product(mState.mLocalSize[0]);
463 checked_local_size_product *= mState.mLocalSize[1];
464 checked_local_size_product *= mState.mLocalSize[2];
465
466 if (!checked_local_size_product.IsValid())
467 {
468 WARN() << std::endl
469 << "Integer overflow when computing the product of local_size_x, "
470 << "local_size_y and local_size_z.";
471 mState.mCompileStatus = CompileStatus::NOT_COMPILED;
472 return;
473 }
474 if (checked_local_size_product.ValueOrDie() >
jchen103fd614d2018-08-13 12:21:58 +0800475 mCurrentMaxComputeWorkGroupInvocations)
Xinghua Cao77a2b4c2018-05-21 17:28:29 +0800476 {
477 WARN() << std::endl
478 << "The total number of invocations within a work group exceeds "
479 << "MAX_COMPUTE_WORK_GROUP_INVOCATIONS.";
480 mState.mCompileStatus = CompileStatus::NOT_COMPILED;
481 return;
482 }
483 }
Martin Radev4c4c8e72016-08-04 12:25:34 +0300484 break;
485 }
Jiawei Shao385b3e02018-03-21 09:43:28 +0800486 case ShaderType::Vertex:
Martin Radev4c4c8e72016-08-04 12:25:34 +0300487 {
Martin Radev7cf61662017-07-26 17:10:53 +0300488 {
Jiawei Shao3d404882017-10-16 13:30:48 +0800489 mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
Olli Etuahoebd6e2d2018-03-23 17:07:55 +0200490 mState.mAllAttributes = GetShaderVariables(sh::GetAttributes(compilerHandle));
491 mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
Jamie Madill493f9572018-05-24 19:52:15 -0400492 mState.mNumViews = sh::GetVertexShaderNumViews(compilerHandle);
Martin Radev7cf61662017-07-26 17:10:53 +0300493 }
Martin Radev4c4c8e72016-08-04 12:25:34 +0300494 break;
495 }
Jiawei Shao385b3e02018-03-21 09:43:28 +0800496 case ShaderType::Fragment:
Martin Radev4c4c8e72016-08-04 12:25:34 +0300497 {
Jiawei Shao3d404882017-10-16 13:30:48 +0800498 mState.mInputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
Martin Radev4c4c8e72016-08-04 12:25:34 +0300499 // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
Jiawei Shao3d404882017-10-16 13:30:48 +0800500 std::sort(mState.mInputVaryings.begin(), mState.mInputVaryings.end(), CompareShaderVar);
Martin Radev4c4c8e72016-08-04 12:25:34 +0300501 mState.mActiveOutputVariables =
Jamie Madillacb4b812016-11-07 13:50:29 -0500502 GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
Martin Radev4c4c8e72016-08-04 12:25:34 +0300503 break;
504 }
Jiawei Shao385b3e02018-03-21 09:43:28 +0800505 case ShaderType::Geometry:
Jiawei Shao89be29a2017-11-06 14:36:45 +0800506 {
507 mState.mInputVaryings = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
508 mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
509
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800510 if (sh::HasValidGeometryShaderInputPrimitiveType(compilerHandle))
511 {
Jamie Madill493f9572018-05-24 19:52:15 -0400512 mState.mGeometryShaderInputPrimitiveType = FromGLenum<PrimitiveMode>(
513 sh::GetGeometryShaderInputPrimitiveType(compilerHandle));
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800514 }
515 if (sh::HasValidGeometryShaderOutputPrimitiveType(compilerHandle))
516 {
Jamie Madill493f9572018-05-24 19:52:15 -0400517 mState.mGeometryShaderOutputPrimitiveType = FromGLenum<PrimitiveMode>(
518 sh::GetGeometryShaderOutputPrimitiveType(compilerHandle));
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800519 }
520 if (sh::HasValidGeometryShaderMaxVertices(compilerHandle))
521 {
522 mState.mGeometryShaderMaxVertices =
523 sh::GetGeometryShaderMaxVertices(compilerHandle);
524 }
Jiawei Shao89be29a2017-11-06 14:36:45 +0800525 mState.mGeometryShaderInvocations = sh::GetGeometryShaderInvocations(compilerHandle);
Jiawei Shao89be29a2017-11-06 14:36:45 +0800526 break;
527 }
Martin Radev4c4c8e72016-08-04 12:25:34 +0300528 default:
529 UNREACHABLE();
Jamie Madill006cbc52015-09-23 16:47:54 -0400530 }
531
Jamie Madill15243d92016-04-26 13:41:35 -0400532 ASSERT(!mState.mTranslatedSource.empty());
Jamie Madill006cbc52015-09-23 16:47:54 -0400533
jchen10a155bac2018-08-16 15:26:39 +0800534 bool success = mImplementation->postTranslateCompile(&mShCompilerInstance, &mInfoLog);
Jamie Madill34ca4f52017-06-13 11:49:39 -0400535 mState.mCompileStatus = success ? CompileStatus::COMPILED : CompileStatus::NOT_COMPILED;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000536}
537
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000538void Shader::addRef()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000539{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000540 mRefCount++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000541}
542
Jamie Madill6c1f6712017-02-14 19:08:04 -0500543void Shader::release(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000544{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000545 mRefCount--;
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000546
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000547 if (mRefCount == 0 && mDeleteStatus)
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000548 {
Jamie Madill6c1f6712017-02-14 19:08:04 -0500549 mResourceManager->deleteShader(context, mHandle);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000550 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000551}
552
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000553unsigned int Shader::getRefCount() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000554{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000555 return mRefCount;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000556}
557
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000558bool Shader::isFlaggedForDeletion() const
559{
560 return mDeleteStatus;
561}
562
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000563void Shader::flagForDeletion()
564{
565 mDeleteStatus = true;
566}
567
jchen103fd614d2018-08-13 12:21:58 +0800568bool Shader::isCompiled()
Jamie Madill80a6fc02015-08-21 16:53:16 -0400569{
jchen103fd614d2018-08-13 12:21:58 +0800570 resolveCompile();
Jamie Madill34ca4f52017-06-13 11:49:39 -0400571 return mState.mCompileStatus == CompileStatus::COMPILED;
Jamie Madillbd044ed2017-06-05 12:59:21 -0400572}
573
jchen10a155bac2018-08-16 15:26:39 +0800574bool Shader::isCompleted()
575{
576 return (!mState.compilePending() || mCompileEvent->isReady());
577}
578
jchen103fd614d2018-08-13 12:21:58 +0800579int Shader::getShaderVersion()
Jamie Madillbd044ed2017-06-05 12:59:21 -0400580{
jchen103fd614d2018-08-13 12:21:58 +0800581 resolveCompile();
Jamie Madill15243d92016-04-26 13:41:35 -0400582 return mState.mShaderVersion;
Jamie Madill80a6fc02015-08-21 16:53:16 -0400583}
584
jchen103fd614d2018-08-13 12:21:58 +0800585const std::vector<sh::Varying> &Shader::getInputVaryings()
Jamie Madilld15250e2014-09-03 09:40:44 -0400586{
jchen103fd614d2018-08-13 12:21:58 +0800587 resolveCompile();
Jiawei Shao3d404882017-10-16 13:30:48 +0800588 return mState.getInputVaryings();
589}
590
jchen103fd614d2018-08-13 12:21:58 +0800591const std::vector<sh::Varying> &Shader::getOutputVaryings()
Jiawei Shao3d404882017-10-16 13:30:48 +0800592{
jchen103fd614d2018-08-13 12:21:58 +0800593 resolveCompile();
Jiawei Shao3d404882017-10-16 13:30:48 +0800594 return mState.getOutputVaryings();
Jamie Madilld15250e2014-09-03 09:40:44 -0400595}
596
jchen103fd614d2018-08-13 12:21:58 +0800597const std::vector<sh::Uniform> &Shader::getUniforms()
Jamie Madilld15250e2014-09-03 09:40:44 -0400598{
jchen103fd614d2018-08-13 12:21:58 +0800599 resolveCompile();
Jamie Madill15243d92016-04-26 13:41:35 -0400600 return mState.getUniforms();
Jamie Madilld15250e2014-09-03 09:40:44 -0400601}
602
jchen103fd614d2018-08-13 12:21:58 +0800603const std::vector<sh::InterfaceBlock> &Shader::getUniformBlocks()
Jamie Madilld15250e2014-09-03 09:40:44 -0400604{
jchen103fd614d2018-08-13 12:21:58 +0800605 resolveCompile();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800606 return mState.getUniformBlocks();
607}
608
jchen103fd614d2018-08-13 12:21:58 +0800609const std::vector<sh::InterfaceBlock> &Shader::getShaderStorageBlocks()
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800610{
jchen103fd614d2018-08-13 12:21:58 +0800611 resolveCompile();
Jiajia Qin9b11ea42017-07-11 16:50:08 +0800612 return mState.getShaderStorageBlocks();
Jamie Madilld15250e2014-09-03 09:40:44 -0400613}
614
jchen103fd614d2018-08-13 12:21:58 +0800615const std::vector<sh::Attribute> &Shader::getActiveAttributes()
Jamie Madilld15250e2014-09-03 09:40:44 -0400616{
jchen103fd614d2018-08-13 12:21:58 +0800617 resolveCompile();
Jamie Madill15243d92016-04-26 13:41:35 -0400618 return mState.getActiveAttributes();
Jamie Madilld15250e2014-09-03 09:40:44 -0400619}
620
jchen103fd614d2018-08-13 12:21:58 +0800621const std::vector<sh::Attribute> &Shader::getAllAttributes()
Olli Etuahoebd6e2d2018-03-23 17:07:55 +0200622{
jchen103fd614d2018-08-13 12:21:58 +0800623 resolveCompile();
Olli Etuahoebd6e2d2018-03-23 17:07:55 +0200624 return mState.getAllAttributes();
625}
626
jchen103fd614d2018-08-13 12:21:58 +0800627const std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables()
Jamie Madilld15250e2014-09-03 09:40:44 -0400628{
jchen103fd614d2018-08-13 12:21:58 +0800629 resolveCompile();
Jamie Madill15243d92016-04-26 13:41:35 -0400630 return mState.getActiveOutputVariables();
Jamie Madilld15250e2014-09-03 09:40:44 -0400631}
632
jchen103fd614d2018-08-13 12:21:58 +0800633std::string Shader::getTransformFeedbackVaryingMappedName(const std::string &tfVaryingName)
Olli Etuaho855d9642017-05-17 14:05:06 +0300634{
Jiawei Shao3d404882017-10-16 13:30:48 +0800635 // TODO(jiawei.shao@intel.com): support transform feedback on geometry shader.
Jiawei Shao385b3e02018-03-21 09:43:28 +0800636 ASSERT(mState.getShaderType() == ShaderType::Vertex);
jchen103fd614d2018-08-13 12:21:58 +0800637 const auto &varyings = getOutputVaryings();
Olli Etuaho855d9642017-05-17 14:05:06 +0300638 auto bracketPos = tfVaryingName.find("[");
639 if (bracketPos != std::string::npos)
640 {
641 auto tfVaryingBaseName = tfVaryingName.substr(0, bracketPos);
642 for (const auto &varying : varyings)
643 {
644 if (varying.name == tfVaryingBaseName)
645 {
646 std::string mappedNameWithArrayIndex =
647 varying.mappedName + tfVaryingName.substr(bracketPos);
648 return mappedNameWithArrayIndex;
649 }
650 }
651 }
652 else
653 {
654 for (const auto &varying : varyings)
655 {
656 if (varying.name == tfVaryingName)
657 {
658 return varying.mappedName;
659 }
jchen108225e732017-11-14 16:29:03 +0800660 else if (varying.isStruct())
661 {
662 const auto *field = FindShaderVarField(varying, tfVaryingName);
663 ASSERT(field != nullptr && !field->isStruct() && !field->isArray());
664 return varying.mappedName + "." + field->mappedName;
665 }
Olli Etuaho855d9642017-05-17 14:05:06 +0300666 }
667 }
668 UNREACHABLE();
669 return std::string();
670}
671
jchen103fd614d2018-08-13 12:21:58 +0800672const sh::WorkGroupSize &Shader::getWorkGroupSize()
Jamie Madillbd044ed2017-06-05 12:59:21 -0400673{
jchen103fd614d2018-08-13 12:21:58 +0800674 resolveCompile();
Jamie Madillbd044ed2017-06-05 12:59:21 -0400675 return mState.mLocalSize;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000676}
Jamie Madillbd044ed2017-06-05 12:59:21 -0400677
jchen103fd614d2018-08-13 12:21:58 +0800678int Shader::getNumViews()
Martin Radev7cf61662017-07-26 17:10:53 +0300679{
jchen103fd614d2018-08-13 12:21:58 +0800680 resolveCompile();
Martin Radev7cf61662017-07-26 17:10:53 +0300681 return mState.mNumViews;
682}
683
jchen103fd614d2018-08-13 12:21:58 +0800684Optional<PrimitiveMode> Shader::getGeometryShaderInputPrimitiveType()
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800685{
jchen103fd614d2018-08-13 12:21:58 +0800686 resolveCompile();
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800687 return mState.mGeometryShaderInputPrimitiveType;
688}
689
jchen103fd614d2018-08-13 12:21:58 +0800690Optional<PrimitiveMode> Shader::getGeometryShaderOutputPrimitiveType()
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800691{
jchen103fd614d2018-08-13 12:21:58 +0800692 resolveCompile();
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800693 return mState.mGeometryShaderOutputPrimitiveType;
694}
695
jchen103fd614d2018-08-13 12:21:58 +0800696int Shader::getGeometryShaderInvocations()
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800697{
jchen103fd614d2018-08-13 12:21:58 +0800698 resolveCompile();
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800699 return mState.mGeometryShaderInvocations;
700}
701
jchen103fd614d2018-08-13 12:21:58 +0800702Optional<GLint> Shader::getGeometryShaderMaxVertices()
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800703{
jchen103fd614d2018-08-13 12:21:58 +0800704 resolveCompile();
Jiawei Shao4ed05da2018-02-02 14:26:15 +0800705 return mState.mGeometryShaderMaxVertices;
706}
707
Jamie Madill32447362017-06-28 14:53:52 -0400708const std::string &Shader::getCompilerResourcesString() const
709{
jchen10a155bac2018-08-16 15:26:39 +0800710 return mCompilerResourcesString;
Jamie Madill32447362017-06-28 14:53:52 -0400711}
712
Jamie Madillbd044ed2017-06-05 12:59:21 -0400713} // namespace gl