blob: c9da1a3895121cd158fbf0b9002e131631f59ce3 [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002//
shannon.woods@transgaming.come16e6512013-02-28 23:19:02 +00003// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00004// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// Program.cpp: Implements the gl::Program class. Implements GL program objects
9// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
10
shannon.woods@transgaming.comd2811d62013-02-28 23:11:19 +000011#include "libGLESv2/Program.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000012#include "libGLESv2/ProgramBinary.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000013#include "libGLESv2/ResourceManager.h"
daniel@transgaming.com87891f72011-06-01 15:28:35 +000014
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000015namespace gl
16{
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000017const char * const g_fakepath = "C:\\fakepath";
18
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +000019AttributeBindings::AttributeBindings()
20{
21}
22
23AttributeBindings::~AttributeBindings()
24{
apatrick@chromium.org9a30b092012-06-06 20:21:55 +000025}
26
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000027InfoLog::InfoLog() : mInfoLog(NULL)
28{
29}
30
31InfoLog::~InfoLog()
32{
33 delete[] mInfoLog;
34}
35
36
37int InfoLog::getLength() const
38{
39 if (!mInfoLog)
40 {
41 return 0;
42 }
43 else
44 {
45 return strlen(mInfoLog) + 1;
46 }
47}
48
49void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog)
50{
51 int index = 0;
52
53 if (bufSize > 0)
54 {
55 if (mInfoLog)
56 {
57 index = std::min(bufSize - 1, (int)strlen(mInfoLog));
58 memcpy(infoLog, mInfoLog, index);
59 }
60
61 infoLog[index] = '\0';
62 }
63
64 if (length)
65 {
66 *length = index;
67 }
68}
69
70// append a santized message to the program info log.
71// The D3D compiler includes a fake file path in some of the warning or error
72// messages, so lets remove all occurrences of this fake file path from the log.
73void InfoLog::appendSanitized(const char *message)
74{
75 std::string msg(message);
76
77 size_t found;
78 do
79 {
80 found = msg.find(g_fakepath);
81 if (found != std::string::npos)
82 {
83 msg.erase(found, strlen(g_fakepath));
84 }
85 }
86 while (found != std::string::npos);
87
shannon.woods@transgaming.come16e6512013-02-28 23:19:02 +000088 append("%s", msg.c_str());
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000089}
90
91void InfoLog::append(const char *format, ...)
92{
93 if (!format)
94 {
95 return;
96 }
97
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000098 va_list vararg;
99 va_start(vararg, format);
Jamie Madilld4505052014-02-24 15:26:49 -0500100 size_t infoLength = vsnprintf(NULL, 0, format, vararg);
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000101 va_end(vararg);
102
Jamie Madilld4505052014-02-24 15:26:49 -0500103 char *logPointer = NULL;
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000104
105 if (!mInfoLog)
106 {
shannon.woods@transgaming.come16e6512013-02-28 23:19:02 +0000107 mInfoLog = new char[infoLength + 2];
Jamie Madilld4505052014-02-24 15:26:49 -0500108 logPointer = mInfoLog;
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000109 }
110 else
111 {
Jamie Madilld4505052014-02-24 15:26:49 -0500112 size_t currentlogLength = strlen(mInfoLog);
113 char *newLog = new char[currentlogLength + infoLength + 2];
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000114 strcpy(newLog, mInfoLog);
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000115
116 delete[] mInfoLog;
117 mInfoLog = newLog;
Jamie Madilld4505052014-02-24 15:26:49 -0500118
119 logPointer = mInfoLog + currentlogLength;
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000120 }
Jamie Madilld4505052014-02-24 15:26:49 -0500121
122 va_start(vararg, format);
123 vsnprintf(logPointer, infoLength, format, vararg);
124 va_end(vararg);
125
126 logPointer[infoLength] = 0;
127 strcpy(logPointer + infoLength, "\n");
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000128}
129
130void InfoLog::reset()
131{
132 if (mInfoLog)
133 {
134 delete [] mInfoLog;
135 mInfoLog = NULL;
136 }
137}
138
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000139Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000140{
141 mFragmentShader = NULL;
142 mVertexShader = NULL;
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000143 mProgramBinary.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144 mDeleteStatus = false;
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000145 mLinked = false;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000146 mRefCount = 0;
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000147 mRenderer = renderer;
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +0000148
149 resetUniformBlockBindings();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150}
151
152Program::~Program()
153{
154 unlink(true);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000155
156 if (mVertexShader != NULL)
157 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000158 mVertexShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000159 }
160
161 if (mFragmentShader != NULL)
162 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000163 mFragmentShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000164 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000165}
166
167bool Program::attachShader(Shader *shader)
168{
169 if (shader->getType() == GL_VERTEX_SHADER)
170 {
171 if (mVertexShader)
172 {
173 return false;
174 }
175
176 mVertexShader = (VertexShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000177 mVertexShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178 }
179 else if (shader->getType() == GL_FRAGMENT_SHADER)
180 {
181 if (mFragmentShader)
182 {
183 return false;
184 }
185
186 mFragmentShader = (FragmentShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000187 mFragmentShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188 }
189 else UNREACHABLE();
190
191 return true;
192}
193
194bool Program::detachShader(Shader *shader)
195{
196 if (shader->getType() == GL_VERTEX_SHADER)
197 {
198 if (mVertexShader != shader)
199 {
200 return false;
201 }
202
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000203 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204 mVertexShader = NULL;
205 }
206 else if (shader->getType() == GL_FRAGMENT_SHADER)
207 {
208 if (mFragmentShader != shader)
209 {
210 return false;
211 }
212
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000213 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000214 mFragmentShader = NULL;
215 }
216 else UNREACHABLE();
217
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000218 return true;
219}
220
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000221int Program::getAttachedShadersCount() const
222{
223 return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
224}
225
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000226void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
227{
228 if (index < MAX_VERTEX_ATTRIBS)
229 {
230 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
231 {
232 mAttributeBinding[i].erase(name);
233 }
234
235 mAttributeBinding[index].insert(name);
236 }
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000237}
238
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000239void Program::bindAttributeLocation(GLuint index, const char *name)
240{
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000241 mAttributeBindings.bindAttributeLocation(index, name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242}
243
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
245// compiling them into binaries, determining the attribute mappings, and collecting
246// a list of uniforms
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000247bool Program::link()
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000248{
249 unlink(false);
250
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000251 mInfoLog.reset();
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +0000252 resetUniformBlockBindings();
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000253
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000254 mProgramBinary.set(new ProgramBinary(mRenderer));
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000255 mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader);
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000256
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000257 return mLinked;
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000258}
259
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000260int AttributeBindings::getAttributeBinding(const std::string &name) const
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000261{
262 for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
263 {
264 if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
265 {
266 return location;
267 }
268 }
269
270 return -1;
271}
272
daniel@transgaming.comaa5e59b2011-10-04 18:43:12 +0000273// Returns the program object to an unlinked state, before re-linking, or at destruction
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274void Program::unlink(bool destroy)
275{
276 if (destroy) // Object being destructed
277 {
278 if (mFragmentShader)
279 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000280 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281 mFragmentShader = NULL;
282 }
283
284 if (mVertexShader)
285 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000286 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287 mVertexShader = NULL;
288 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289 }
290
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000291 mProgramBinary.set(NULL);
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000292 mLinked = false;
293}
294
295bool Program::isLinked()
296{
297 return mLinked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000298}
299
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000300ProgramBinary* Program::getProgramBinary()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000302 return mProgramBinary.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303}
304
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000305bool Program::setProgramBinary(const void *binary, GLsizei length)
apatrick@chromium.org3ce8dbc2012-06-08 17:52:30 +0000306{
307 unlink(false);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000308
309 mInfoLog.reset();
310
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000311 mProgramBinary.set(new ProgramBinary(mRenderer));
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000312 mLinked = mProgramBinary->load(mInfoLog, binary, length);
313 if (!mLinked)
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000314 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000315 mProgramBinary.set(NULL);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000316 }
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000317
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000318 return mLinked;
apatrick@chromium.org3ce8dbc2012-06-08 17:52:30 +0000319}
320
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000321void Program::release()
322{
323 mRefCount--;
324
325 if (mRefCount == 0 && mDeleteStatus)
326 {
327 mResourceManager->deleteProgram(mHandle);
328 }
329}
330
331void Program::addRef()
332{
333 mRefCount++;
334}
335
336unsigned int Program::getRefCount() const
337{
338 return mRefCount;
339}
340
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000341GLint Program::getProgramBinaryLength() const
342{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000343 ProgramBinary *programBinary = mProgramBinary.get();
344 if (programBinary)
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000345 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000346 return programBinary->getLength();
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000347 }
348 else
349 {
350 return 0;
351 }
352}
353
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000354int Program::getInfoLogLength() const
355{
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000356 return mInfoLog.getLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000357}
358
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000359void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
360{
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000361 return mInfoLog.getLog(bufSize, length, infoLog);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000362}
363
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000364void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
365{
366 int total = 0;
367
368 if (mVertexShader)
369 {
370 if (total < maxCount)
371 {
372 shaders[total] = mVertexShader->getHandle();
373 }
374
375 total++;
376 }
377
378 if (mFragmentShader)
379 {
380 if (total < maxCount)
381 {
382 shaders[total] = mFragmentShader->getHandle();
383 }
384
385 total++;
386 }
387
388 if (count)
389 {
390 *count = total;
391 }
392}
393
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000394void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
395{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000396 ProgramBinary *programBinary = getProgramBinary();
397 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000398 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000399 programBinary->getActiveAttribute(index, bufsize, length, size, type, name);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000400 }
401 else
402 {
403 if (bufsize > 0)
404 {
405 name[0] = '\0';
406 }
407
408 if (length)
409 {
410 *length = 0;
411 }
412
413 *type = GL_NONE;
414 *size = 1;
415 }
416}
417
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000418GLint Program::getActiveAttributeCount()
419{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000420 ProgramBinary *programBinary = getProgramBinary();
421 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000422 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000423 return programBinary->getActiveAttributeCount();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000424 }
425 else
426 {
427 return 0;
428 }
429}
430
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000431GLint Program::getActiveAttributeMaxLength()
432{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000433 ProgramBinary *programBinary = getProgramBinary();
434 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000435 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000436 return programBinary->getActiveAttributeMaxLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000437 }
438 else
439 {
440 return 0;
441 }
442}
443
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000444void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
445{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000446 ProgramBinary *programBinary = getProgramBinary();
447 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000448 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000449 return programBinary->getActiveUniform(index, bufsize, length, size, type, name);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000450 }
451 else
452 {
453 if (bufsize > 0)
454 {
455 name[0] = '\0';
456 }
457
458 if (length)
459 {
460 *length = 0;
461 }
462
463 *size = 0;
464 *type = GL_NONE;
465 }
466}
467
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000468GLint Program::getActiveUniformCount()
469{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000470 ProgramBinary *programBinary = getProgramBinary();
471 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000472 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000473 return programBinary->getActiveUniformCount();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000474 }
475 else
476 {
477 return 0;
478 }
479}
480
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000481GLint Program::getActiveUniformMaxLength()
482{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000483 ProgramBinary *programBinary = getProgramBinary();
484 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000485 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000486 return programBinary->getActiveUniformMaxLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000487 }
488 else
489 {
490 return 0;
491 }
492}
493
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000494void Program::flagForDeletion()
495{
496 mDeleteStatus = true;
497}
498
499bool Program::isFlaggedForDeletion() const
500{
501 return mDeleteStatus;
502}
daniel@transgaming.com86a7a132010-04-29 03:32:32 +0000503
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000504void Program::validate()
505{
506 mInfoLog.reset();
507
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000508 ProgramBinary *programBinary = getProgramBinary();
509 if (isLinked() && programBinary)
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000510 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000511 programBinary->validate(mInfoLog);
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000512 }
513 else
514 {
515 mInfoLog.append("Program has not been successfully linked.");
516 }
517}
518
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000519bool Program::isValidated() const
520{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000521 ProgramBinary *programBinary = mProgramBinary.get();
522 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000523 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000524 return programBinary->isValidated();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000525 }
526 else
527 {
528 return false;
529 }
530}
531
shannonwoods@chromium.orge684b582013-05-30 00:07:42 +0000532GLint Program::getActiveUniformBlockCount()
533{
534 ProgramBinary *programBinary = getProgramBinary();
535 if (programBinary)
536 {
537 return static_cast<GLint>(programBinary->getActiveUniformBlockCount());
538 }
539 else
540 {
541 return 0;
542 }
543}
544
545GLint Program::getActiveUniformBlockMaxLength()
546{
547 ProgramBinary *programBinary = getProgramBinary();
548 if (programBinary)
549 {
550 return static_cast<GLint>(programBinary->getActiveUniformBlockMaxLength());
551 }
552 else
553 {
554 return 0;
555 }
556}
557
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +0000558void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
559{
560 mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
561}
562
563GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
564{
565 return mUniformBlockBindings[uniformBlockIndex];
566}
567
568void Program::resetUniformBlockBindings()
569{
570 for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++)
571 {
572 mUniformBlockBindings[blockId] = 0;
573 }
574}
575
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000576}