2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
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.
11 #include "libGLESv2/Shader.h"
15 #include "GLSLANG/Shaderlang.h"
16 #include "libGLESv2/main.h"
17 #include "libGLESv2/utilities.h"
21 void *Shader::mFragmentCompiler = NULL;
22 void *Shader::mVertexCompiler = NULL;
24 Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
30 // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
31 if (!mFragmentCompiler)
33 int result = ShInitialize();
37 ShBuiltInResources resources;
38 ShInitBuiltInResources(&resources);
39 Context *context = getContext();
41 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
42 resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
43 resources.MaxVaryingVectors = context->getMaximumVaryingVectors();
44 resources.MaxVertexTextureImageUnits = context->getMaximumVertexTextureImageUnits();
45 resources.MaxCombinedTextureImageUnits = context->getMaximumCombinedTextureImageUnits();
46 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
47 resources.MaxFragmentUniformVectors = context->getMaximumFragmentUniformVectors();
48 resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
49 resources.OES_standard_derivatives = 1;
51 mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources);
52 mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources);
57 mDeleteStatus = false;
67 GLuint Shader::getHandle() const
72 void Shader::setSource(GLsizei count, const char **string, const GLint *length)
77 for (int i = 0; i < count; i++)
79 if (length && length[i] >= 0)
81 totalLength += length[i];
85 totalLength += (int)strlen(string[i]);
89 mSource = new char[totalLength + 1];
92 for (int i = 0; i < count; i++)
96 if (length && length[i] >= 0)
98 stringLength = length[i];
102 stringLength = (int)strlen(string[i]);
105 strncpy(code, string[i], stringLength);
106 code += stringLength;
109 mSource[totalLength] = '\0';
112 int Shader::getInfoLogLength() const
120 return strlen(mInfoLog) + 1;
124 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
130 while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
132 infoLog[index] = mInfoLog[index];
139 infoLog[index] = '\0';
148 int Shader::getSourceLength() const
156 return strlen(mSource) + 1;
160 void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
166 while (index < bufSize - 1 && index < (int)strlen(mSource))
168 source[index] = mSource[index];
175 source[index] = '\0';
184 bool Shader::isCompiled()
186 return mHlsl != NULL;
189 const char *Shader::getHLSL()
194 void Shader::addRef()
199 void Shader::release()
203 if (mRefCount == 0 && mDeleteStatus)
205 mResourceManager->deleteShader(mHandle);
209 unsigned int Shader::getRefCount() const
214 bool Shader::isFlaggedForDeletion() const
216 return mDeleteStatus;
219 void Shader::flagForDeletion()
221 mDeleteStatus = true;
224 void Shader::releaseCompiler()
226 ShDestruct(mFragmentCompiler);
227 ShDestruct(mVertexCompiler);
229 mFragmentCompiler = NULL;
230 mVertexCompiler = NULL;
235 void Shader::parseVaryings()
239 const char *input = strstr(mHlsl, "// Varyings") + 12;
243 char varyingType[256];
244 char varyingName[256];
246 int matches = sscanf(input, "static %255s %255s", varyingType, varyingName);
253 char *array = strstr(varyingName, "[");
258 size = atoi(array + 1);
262 varyings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL));
264 input = strstr(input, ";") + 2;
267 mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL;
268 mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
269 mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
270 mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
274 void Shader::compileToHLSL(void *compiler)
276 if (isCompiled() || !mSource)
284 int compileOptions = SH_OBJECT_CODE;
285 std::string sourcePath;
288 sourcePath = getTempPath();
289 writeFile(sourcePath.c_str(), mSource, strlen(mSource));
290 compileOptions |= SH_LINE_DIRECTIVES;
294 if (sourcePath.empty())
296 result = ShCompile(compiler, &mSource, 1, compileOptions);
300 const char* sourceStrings[2] =
306 result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH);
312 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
313 mHlsl = new char[objCodeLen];
314 ShGetObjectCode(compiler, mHlsl);
319 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
320 mInfoLog = new char[infoLogLen];
321 ShGetInfoLog(compiler, mInfoLog);
323 TRACE("\n%s", mInfoLog);
327 GLenum Shader::parseType(const std::string &type)
333 else if (type == "float2")
335 return GL_FLOAT_VEC2;
337 else if (type == "float3")
339 return GL_FLOAT_VEC3;
341 else if (type == "float4")
343 return GL_FLOAT_VEC4;
345 else if (type == "float2x2")
347 return GL_FLOAT_MAT2;
349 else if (type == "float3x3")
351 return GL_FLOAT_MAT3;
353 else if (type == "float4x4")
355 return GL_FLOAT_MAT4;
362 // true if varying x has a higher priority in packing than y
363 bool Shader::compareVarying(const Varying &x, const Varying &y)
367 return x.size > y.size;
372 case GL_FLOAT_MAT4: return true;
376 case GL_FLOAT_MAT4: return false;
377 case GL_FLOAT_MAT2: return true;
378 case GL_FLOAT_VEC4: return true;
379 case GL_FLOAT_MAT3: return true;
380 case GL_FLOAT_VEC3: return true;
381 case GL_FLOAT_VEC2: return true;
382 case GL_FLOAT: return true;
383 default: UNREACHABLE();
389 case GL_FLOAT_MAT4: return false;
390 case GL_FLOAT_MAT2: return false;
391 case GL_FLOAT_VEC4: return true;
392 case GL_FLOAT_MAT3: return true;
393 case GL_FLOAT_VEC3: return true;
394 case GL_FLOAT_VEC2: return true;
395 case GL_FLOAT: return true;
396 default: UNREACHABLE();
402 case GL_FLOAT_MAT4: return false;
403 case GL_FLOAT_MAT2: return false;
404 case GL_FLOAT_VEC4: return false;
405 case GL_FLOAT_MAT3: return true;
406 case GL_FLOAT_VEC3: return true;
407 case GL_FLOAT_VEC2: return true;
408 case GL_FLOAT: return true;
409 default: UNREACHABLE();
415 case GL_FLOAT_MAT4: return false;
416 case GL_FLOAT_MAT2: return false;
417 case GL_FLOAT_VEC4: return false;
418 case GL_FLOAT_MAT3: return false;
419 case GL_FLOAT_VEC3: return true;
420 case GL_FLOAT_VEC2: return true;
421 case GL_FLOAT: return true;
422 default: UNREACHABLE();
428 case GL_FLOAT_MAT4: return false;
429 case GL_FLOAT_MAT2: return false;
430 case GL_FLOAT_VEC4: return false;
431 case GL_FLOAT_MAT3: return false;
432 case GL_FLOAT_VEC3: return false;
433 case GL_FLOAT_VEC2: return true;
434 case GL_FLOAT: return true;
435 default: UNREACHABLE();
438 case GL_FLOAT: return false;
439 default: UNREACHABLE();
445 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
449 VertexShader::~VertexShader()
453 GLenum VertexShader::getType()
455 return GL_VERTEX_SHADER;
458 void VertexShader::compile()
460 compileToHLSL(mVertexCompiler);
465 int VertexShader::getSemanticIndex(const std::string &attributeName)
467 if (!attributeName.empty())
469 int semanticIndex = 0;
470 for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++)
472 if (attribute->name == attributeName)
474 return semanticIndex;
477 semanticIndex += VariableRowCount(attribute->type);
484 void VertexShader::parseAttributes()
488 const char *input = strstr(mHlsl, "// Attributes") + 14;
492 char attributeType[256];
493 char attributeName[256];
495 int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName);
502 mAttributes.push_back(Attribute(parseType(attributeType), attributeName));
504 input = strstr(input, ";") + 2;
509 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
513 FragmentShader::~FragmentShader()
517 GLenum FragmentShader::getType()
519 return GL_FRAGMENT_SHADER;
522 void FragmentShader::compile()
524 compileToHLSL(mFragmentCompiler);
526 varyings.sort(compareVarying);