blob: c7fd51db4bc6256aff04433189a2b4ad47a942a2 [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
13#include <sstream>
14
Jamie Madill91445bc2015-09-23 16:47:53 -040015#include "common/utilities.h"
16#include "GLSLANG/ShaderLang.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040017#include "libANGLE/Caps.h"
Jamie Madill006cbc52015-09-23 16:47:54 -040018#include "libANGLE/Compiler.h"
Jamie Madill91445bc2015-09-23 16:47:53 -040019#include "libANGLE/Constants.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040020#include "libANGLE/renderer/GLImplFactory.h"
Jamie Madill91445bc2015-09-23 16:47:53 -040021#include "libANGLE/renderer/ShaderImpl.h"
22#include "libANGLE/ResourceManager.h"
Bryan Bernhart619c8332016-11-09 11:11:41 -080023#include "libANGLE/Context.h"
Jamie Madill91445bc2015-09-23 16:47:53 -040024
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025namespace gl
26{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000027
Jamie Madill006cbc52015-09-23 16:47:54 -040028namespace
29{
30template <typename VarT>
31std::vector<VarT> GetActiveShaderVariables(const std::vector<VarT> *variableList)
32{
33 ASSERT(variableList);
34 std::vector<VarT> result;
35 for (size_t varIndex = 0; varIndex < variableList->size(); varIndex++)
36 {
37 const VarT &var = variableList->at(varIndex);
38 if (var.staticUse)
39 {
40 result.push_back(var);
41 }
42 }
43 return result;
44}
45
46template <typename VarT>
47const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableList)
48{
49 ASSERT(variableList);
50 return *variableList;
51}
52
Jamie Madill9fc36822015-11-18 13:08:07 -050053} // anonymous namespace
54
Jamie Madill006cbc52015-09-23 16:47:54 -040055// true if varying x has a higher priority in packing than y
Jamie Madill55c25d02015-11-18 13:08:08 -050056bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
Jamie Madill006cbc52015-09-23 16:47:54 -040057{
58 if (x.type == y.type)
59 {
60 return x.arraySize > y.arraySize;
61 }
62
63 // Special case for handling structs: we sort these to the end of the list
64 if (x.type == GL_STRUCT_ANGLEX)
65 {
66 return false;
67 }
68
69 if (y.type == GL_STRUCT_ANGLEX)
70 {
71 return true;
72 }
73
74 return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
75}
76
Jamie Madill15243d92016-04-26 13:41:35 -040077ShaderState::ShaderState(GLenum shaderType) : mLabel(), mShaderType(shaderType), mShaderVersion(100)
Jamie Madill91445bc2015-09-23 16:47:53 -040078{
Martin Radev4c4c8e72016-08-04 12:25:34 +030079 mLocalSize.fill(-1);
Jamie Madill91445bc2015-09-23 16:47:53 -040080}
81
Jamie Madill15243d92016-04-26 13:41:35 -040082ShaderState::~ShaderState()
Jamie Madill91445bc2015-09-23 16:47:53 -040083{
84}
85
Geoff Lang4ddf5af2016-12-01 14:30:44 -050086Shader::Shader(ShaderProgramManager *manager,
Jamie Madill7aea7e02016-05-10 10:39:45 -040087 rx::GLImplFactory *implFactory,
Jamie Madill006cbc52015-09-23 16:47:54 -040088 const gl::Limitations &rendererLimitations,
89 GLenum type,
90 GLuint handle)
Jamie Madill15243d92016-04-26 13:41:35 -040091 : mState(type),
92 mImplementation(implFactory->createShader(mState)),
Jamie Madill006cbc52015-09-23 16:47:54 -040093 mRendererLimitations(rendererLimitations),
Brandon Jonesf05cdee2014-08-27 15:24:07 -070094 mHandle(handle),
Corentin Wallezbc99bb62015-05-14 17:42:20 -040095 mType(type),
Brandon Jonesf05cdee2014-08-27 15:24:07 -070096 mRefCount(0),
97 mDeleteStatus(false),
Corentin Wallezbc99bb62015-05-14 17:42:20 -040098 mCompiled(false),
99 mResourceManager(manager)
Jamie Madille294bb82014-07-17 14:16:26 -0400100{
Jamie Madill91445bc2015-09-23 16:47:53 -0400101 ASSERT(mImplementation);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000102}
103
104Shader::~Shader()
105{
Jamie Madill91445bc2015-09-23 16:47:53 -0400106 SafeDelete(mImplementation);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107}
108
Geoff Lang70d0f492015-12-10 17:45:46 -0500109void Shader::setLabel(const std::string &label)
110{
Jamie Madill15243d92016-04-26 13:41:35 -0400111 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500112}
113
114const std::string &Shader::getLabel() const
115{
Jamie Madill15243d92016-04-26 13:41:35 -0400116 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500117}
118
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000119GLuint Shader::getHandle() const
120{
121 return mHandle;
122}
123
shannon.woods%transgaming.com@gtempaccount.com5f339332013-04-13 03:29:02 +0000124void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125{
Geoff Lang536d7262013-08-26 17:04:20 -0400126 std::ostringstream stream;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127
128 for (int i = 0; i < count; i++)
129 {
Geoff Langf60fab62014-11-24 11:21:20 -0500130 if (length == nullptr || length[i] < 0)
131 {
Jamie Madille7cfb3d2014-12-03 10:58:56 -0500132 stream.write(string[i], strlen(string[i]));
Geoff Langf60fab62014-11-24 11:21:20 -0500133 }
134 else
135 {
136 stream.write(string[i], length[i]);
137 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138 }
139
Jamie Madill15243d92016-04-26 13:41:35 -0400140 mState.mSource = stream.str();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141}
142
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000143int Shader::getInfoLogLength() const
144{
Jamie Madill006cbc52015-09-23 16:47:54 -0400145 if (mInfoLog.empty())
Jamie Madill91445bc2015-09-23 16:47:53 -0400146 {
147 return 0;
148 }
149
Jamie Madill006cbc52015-09-23 16:47:54 -0400150 return (static_cast<int>(mInfoLog.length()) + 1);
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000151}
152
Geoff Lang536d7262013-08-26 17:04:20 -0400153void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000154{
155 int index = 0;
156
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000157 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000158 {
Jamie Madill006cbc52015-09-23 16:47:54 -0400159 index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
160 memcpy(infoLog, mInfoLog.c_str(), index);
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000161
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000162 infoLog[index] = '\0';
163 }
164
165 if (length)
166 {
167 *length = index;
168 }
169}
170
171int Shader::getSourceLength() const
172{
Jamie Madill15243d92016-04-26 13:41:35 -0400173 return mState.mSource.empty() ? 0 : (static_cast<int>(mState.mSource.length()) + 1);
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000174}
175
zmo@google.coma574f782011-10-03 21:45:23 +0000176int Shader::getTranslatedSourceLength() const
177{
Jamie Madill15243d92016-04-26 13:41:35 -0400178 if (mState.mTranslatedSource.empty())
Jamie Madill91445bc2015-09-23 16:47:53 -0400179 {
180 return 0;
181 }
182
Jamie Madill15243d92016-04-26 13:41:35 -0400183 return (static_cast<int>(mState.mTranslatedSource.length()) + 1);
zmo@google.coma574f782011-10-03 21:45:23 +0000184}
185
Jamie Madill847638a2015-11-20 13:01:41 -0500186int Shader::getTranslatedSourceWithDebugInfoLength() const
187{
188 const std::string &debugInfo = mImplementation->getDebugInfo();
189 if (debugInfo.empty())
190 {
191 return 0;
192 }
193
194 return (static_cast<int>(debugInfo.length()) + 1);
195}
196
Brandon Jonesf05cdee2014-08-27 15:24:07 -0700197void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000198{
199 int index = 0;
200
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000201 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000202 {
Geoff Lang536d7262013-08-26 17:04:20 -0400203 index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
204 memcpy(buffer, source.c_str(), index);
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000205
zmo@google.coma574f782011-10-03 21:45:23 +0000206 buffer[index] = '\0';
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000207 }
208
209 if (length)
210 {
211 *length = index;
212 }
213}
214
Geoff Lang536d7262013-08-26 17:04:20 -0400215void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
zmo@google.coma574f782011-10-03 21:45:23 +0000216{
Jamie Madill15243d92016-04-26 13:41:35 -0400217 getSourceImpl(mState.mSource, bufSize, length, buffer);
zmo@google.coma574f782011-10-03 21:45:23 +0000218}
219
Geoff Lang536d7262013-08-26 17:04:20 -0400220void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const
zmo@google.coma574f782011-10-03 21:45:23 +0000221{
Jamie Madill15243d92016-04-26 13:41:35 -0400222 getSourceImpl(mState.mTranslatedSource, bufSize, length, buffer);
zmo@google.coma574f782011-10-03 21:45:23 +0000223}
224
Tibor den Ouden97049c62014-10-06 21:39:16 +0200225void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const
226{
Jamie Madill847638a2015-11-20 13:01:41 -0500227 const std::string &debugInfo = mImplementation->getDebugInfo();
Tibor den Ouden97049c62014-10-06 21:39:16 +0200228 getSourceImpl(debugInfo, bufSize, length, buffer);
229}
230
Bryan Bernhart619c8332016-11-09 11:11:41 -0800231void Shader::compile(const Context *context)
Jamie Madillbf9cce22014-07-18 10:33:09 -0400232{
Jamie Madill15243d92016-04-26 13:41:35 -0400233 mState.mTranslatedSource.clear();
Jamie Madill006cbc52015-09-23 16:47:54 -0400234 mInfoLog.clear();
Jamie Madill15243d92016-04-26 13:41:35 -0400235 mState.mShaderVersion = 100;
236 mState.mVaryings.clear();
237 mState.mUniforms.clear();
238 mState.mInterfaceBlocks.clear();
239 mState.mActiveAttributes.clear();
240 mState.mActiveOutputVariables.clear();
Jamie Madill91445bc2015-09-23 16:47:53 -0400241
Bryan Bernhart619c8332016-11-09 11:11:41 -0800242 Compiler *compiler = context->getCompiler();
Jamie Madill15243d92016-04-26 13:41:35 -0400243 ShHandle compilerHandle = compiler->getCompilerHandle(mState.mShaderType);
Jamie Madill006cbc52015-09-23 16:47:54 -0400244
245 std::stringstream sourceStream;
246
Jamie Madilld2c52e32015-10-14 17:07:05 -0400247 std::string sourcePath;
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800248 ShCompileOptions additionalOptions =
Jamie Madilld2c52e32015-10-14 17:07:05 -0400249 mImplementation->prepareSourceAndReturnOptions(&sourceStream, &sourcePath);
Qiankun Miao7ebb97f2016-09-08 18:01:50 +0800250 ShCompileOptions compileOptions = (SH_OBJECT_CODE | SH_VARIABLES | additionalOptions);
Jamie Madill006cbc52015-09-23 16:47:54 -0400251
Bryan Bernhart619c8332016-11-09 11:11:41 -0800252 // Add default options to WebGL shaders to prevent unexpected behavior during compilation.
253 if (context->getExtensions().webglCompatibility)
254 {
Frank Henigman875bbba2017-02-08 16:38:17 -0500255 compileOptions |= SH_INIT_GL_POSITION;
Bryan Bernhart619c8332016-11-09 11:11:41 -0800256 compileOptions |= SH_LIMIT_CALL_STACK_DEPTH;
257 compileOptions |= SH_LIMIT_EXPRESSION_COMPLEXITY;
258 compileOptions |= SH_ENFORCE_PACKING_RESTRICTIONS;
259 }
260
Jamie Madill006cbc52015-09-23 16:47:54 -0400261 // Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes
262 // in fragment shaders. Shader compilation will fail. To provide a better error message we can
263 // instruct the compiler to pre-validate.
264 if (mRendererLimitations.shadersRequireIndexedLoopValidation)
265 {
266 compileOptions |= SH_VALIDATE_LOOP_INDEXING;
267 }
268
269 std::string sourceString = sourceStream.str();
Jamie Madilld2c52e32015-10-14 17:07:05 -0400270 std::vector<const char *> sourceCStrings;
271
272 if (!sourcePath.empty())
273 {
274 sourceCStrings.push_back(sourcePath.c_str());
275 }
276
277 sourceCStrings.push_back(sourceString.c_str());
278
279 bool result =
Jamie Madillacb4b812016-11-07 13:50:29 -0500280 sh::Compile(compilerHandle, &sourceCStrings[0], sourceCStrings.size(), compileOptions);
Jamie Madill006cbc52015-09-23 16:47:54 -0400281
282 if (!result)
283 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500284 mInfoLog = sh::GetInfoLog(compilerHandle);
Yuly Novikovd73f8522017-01-13 17:48:57 -0500285 WARN() << std::endl << mInfoLog;
Jamie Madill006cbc52015-09-23 16:47:54 -0400286 mCompiled = false;
287 return;
288 }
289
Jamie Madillacb4b812016-11-07 13:50:29 -0500290 mState.mTranslatedSource = sh::GetObjectCode(compilerHandle);
Jamie Madill006cbc52015-09-23 16:47:54 -0400291
292#ifndef NDEBUG
293 // Prefix translated shader with commented out un-translated shader.
294 // Useful in diagnostics tools which capture the shader source.
295 std::ostringstream shaderStream;
296 shaderStream << "// GLSL\n";
297 shaderStream << "//\n";
298
299 size_t curPos = 0;
300 while (curPos != std::string::npos)
301 {
Jamie Madill15243d92016-04-26 13:41:35 -0400302 size_t nextLine = mState.mSource.find("\n", curPos);
Jamie Madill006cbc52015-09-23 16:47:54 -0400303 size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1);
304
Jamie Madill15243d92016-04-26 13:41:35 -0400305 shaderStream << "// " << mState.mSource.substr(curPos, len);
Jamie Madill006cbc52015-09-23 16:47:54 -0400306
307 curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
308 }
309 shaderStream << "\n\n";
Jamie Madill15243d92016-04-26 13:41:35 -0400310 shaderStream << mState.mTranslatedSource;
311 mState.mTranslatedSource = shaderStream.str();
Jamie Madill006cbc52015-09-23 16:47:54 -0400312#endif
313
314 // Gather the shader information
Jamie Madillacb4b812016-11-07 13:50:29 -0500315 mState.mShaderVersion = sh::GetShaderVersion(compilerHandle);
Jamie Madill006cbc52015-09-23 16:47:54 -0400316
Jamie Madillacb4b812016-11-07 13:50:29 -0500317 mState.mVaryings = GetShaderVariables(sh::GetVaryings(compilerHandle));
318 mState.mUniforms = GetShaderVariables(sh::GetUniforms(compilerHandle));
319 mState.mInterfaceBlocks = GetShaderVariables(sh::GetInterfaceBlocks(compilerHandle));
Jamie Madill006cbc52015-09-23 16:47:54 -0400320
Martin Radev4c4c8e72016-08-04 12:25:34 +0300321 switch (mState.mShaderType)
Jamie Madill006cbc52015-09-23 16:47:54 -0400322 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300323 case GL_COMPUTE_SHADER:
324 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500325 mState.mLocalSize = sh::GetComputeShaderLocalGroupSize(compilerHandle);
Martin Radev4c4c8e72016-08-04 12:25:34 +0300326 break;
327 }
328 case GL_VERTEX_SHADER:
329 {
Jamie Madillacb4b812016-11-07 13:50:29 -0500330 mState.mActiveAttributes = GetActiveShaderVariables(sh::GetAttributes(compilerHandle));
Martin Radev4c4c8e72016-08-04 12:25:34 +0300331 break;
332 }
333 case GL_FRAGMENT_SHADER:
334 {
335 // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
336 std::sort(mState.mVaryings.begin(), mState.mVaryings.end(), CompareShaderVar);
337 mState.mActiveOutputVariables =
Jamie Madillacb4b812016-11-07 13:50:29 -0500338 GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
Martin Radev4c4c8e72016-08-04 12:25:34 +0300339 break;
340 }
341 default:
342 UNREACHABLE();
Jamie Madill006cbc52015-09-23 16:47:54 -0400343 }
344
Jamie Madill15243d92016-04-26 13:41:35 -0400345 ASSERT(!mState.mTranslatedSource.empty());
Jamie Madill006cbc52015-09-23 16:47:54 -0400346
347 mCompiled = mImplementation->postTranslateCompile(compiler, &mInfoLog);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000348}
349
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000350void Shader::addRef()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000352 mRefCount++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353}
354
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000355void Shader::release()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000357 mRefCount--;
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000358
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000359 if (mRefCount == 0 && mDeleteStatus)
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000360 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000361 mResourceManager->deleteShader(mHandle);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000362 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363}
364
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000365unsigned int Shader::getRefCount() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000366{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000367 return mRefCount;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000368}
369
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000370bool Shader::isFlaggedForDeletion() const
371{
372 return mDeleteStatus;
373}
374
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000375void Shader::flagForDeletion()
376{
377 mDeleteStatus = true;
378}
379
Jamie Madill80a6fc02015-08-21 16:53:16 -0400380int Shader::getShaderVersion() const
381{
Jamie Madill15243d92016-04-26 13:41:35 -0400382 return mState.mShaderVersion;
Jamie Madill80a6fc02015-08-21 16:53:16 -0400383}
384
Jamie Madill4cff2472015-08-21 16:53:18 -0400385const std::vector<sh::Varying> &Shader::getVaryings() const
Jamie Madilld15250e2014-09-03 09:40:44 -0400386{
Jamie Madill15243d92016-04-26 13:41:35 -0400387 return mState.getVaryings();
Jamie Madilld15250e2014-09-03 09:40:44 -0400388}
389
390const std::vector<sh::Uniform> &Shader::getUniforms() const
391{
Jamie Madill15243d92016-04-26 13:41:35 -0400392 return mState.getUniforms();
Jamie Madilld15250e2014-09-03 09:40:44 -0400393}
394
395const std::vector<sh::InterfaceBlock> &Shader::getInterfaceBlocks() const
396{
Jamie Madill15243d92016-04-26 13:41:35 -0400397 return mState.getInterfaceBlocks();
Jamie Madilld15250e2014-09-03 09:40:44 -0400398}
399
400const std::vector<sh::Attribute> &Shader::getActiveAttributes() const
401{
Jamie Madill15243d92016-04-26 13:41:35 -0400402 return mState.getActiveAttributes();
Jamie Madilld15250e2014-09-03 09:40:44 -0400403}
404
Jamie Madilla0a9e122015-09-02 15:54:30 -0400405const std::vector<sh::OutputVariable> &Shader::getActiveOutputVariables() const
Jamie Madilld15250e2014-09-03 09:40:44 -0400406{
Jamie Madill15243d92016-04-26 13:41:35 -0400407 return mState.getActiveOutputVariables();
Jamie Madilld15250e2014-09-03 09:40:44 -0400408}
409
Jamie Madill437d2662014-12-05 14:23:35 -0500410int Shader::getSemanticIndex(const std::string &attributeName) const
411{
412 if (!attributeName.empty())
413 {
Jamie Madill15243d92016-04-26 13:41:35 -0400414 const auto &activeAttributes = mState.getActiveAttributes();
Jamie Madill437d2662014-12-05 14:23:35 -0500415
416 int semanticIndex = 0;
417 for (size_t attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
418 {
419 const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
420
421 if (attribute.name == attributeName)
422 {
423 return semanticIndex;
424 }
425
426 semanticIndex += gl::VariableRegisterCount(attribute.type);
427 }
428 }
429
430 return -1;
431}
432
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000433}