1 // SwiftShader Software Renderer
3 // Copyright(c) 2005-2013 TransGaming Inc.
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
6 // transcribed, stored in a retrieval system, translated into any human or computer
7 // language by any means, or disclosed to third parties without the explicit written
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9 // or implied, including but not limited to any patent rights, are granted to you.
12 // Shader.cpp: Implements the Shader class and its derived classes
13 // VertexShader and FragmentShader. Implements GL shader objects and related
19 #include "utilities.h"
25 bool Shader::compilerInitialized = false;
27 Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
35 mDeleteStatus = false;
44 GLuint Shader::getName() const
49 void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
54 for(int i = 0; i < count; i++)
56 if(length && length[i] >= 0)
58 totalLength += length[i];
62 totalLength += (int)strlen(string[i]);
66 mSource = new char[totalLength + 1];
69 for(int i = 0; i < count; i++)
73 if(length && length[i] >= 0)
75 stringLength = length[i];
79 stringLength = (int)strlen(string[i]);
82 strncpy(code, string[i], stringLength);
86 mSource[totalLength] = '\0';
89 int Shader::getInfoLogLength() const
97 return strlen(mInfoLog) + 1;
101 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
109 index = std::min(bufSize - 1, (int)strlen(mInfoLog));
110 memcpy(infoLog, mInfoLog, index);
113 infoLog[index] = '\0';
122 int Shader::getSourceLength() const
130 return strlen(mSource) + 1;
134 void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
142 index = std::min(bufSize - 1, (int)strlen(mSource));
143 memcpy(source, mSource, index);
146 source[index] = '\0';
155 TranslatorASM *Shader::createCompiler(GLenum shaderType)
157 if(!compilerInitialized)
159 InitCompilerGlobals();
160 compilerInitialized = true;
163 TranslatorASM *assembler = new TranslatorASM(this, shaderType);
165 ShBuiltInResources resources;
166 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
167 resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
168 resources.MaxVaryingVectors = MAX_VARYING_VECTORS;
169 resources.MaxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
170 resources.MaxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
171 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
172 resources.MaxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
173 resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
174 resources.OES_standard_derivatives = 1;
175 resources.OES_fragment_precision_high = 1;
176 resources.MaxCallStackDepth = 16;
177 assembler->Init(resources);
188 activeUniforms.clear();
189 activeAttributes.clear();
192 void Shader::compile()
197 TranslatorASM *compiler = createCompiler(getType());
199 // Ensure we don't pass a NULL source to the compiler
206 bool success = compiler->compile(&source, 1, SH_OBJECT_CODE);
210 static int serial = 1;
212 sprintf(buffer, "shader-input-%d-%d.txt", getName(), serial);
213 FILE *file = fopen(buffer, "wt");
214 fprintf(file, mSource);
216 getShader()->print("shader-output-%d-%d.txt", getName(), serial);
224 int infoLogLen = compiler->getInfoSink().info.size() + 1;
225 mInfoLog = new char[infoLogLen];
226 strcpy(mInfoLog, compiler->getInfoSink().info.c_str());
227 TRACE("\n%s", mInfoLog);
233 bool Shader::isCompiled()
235 return getShader() != 0;
238 void Shader::addRef()
243 void Shader::release()
247 if(mRefCount == 0 && mDeleteStatus)
249 mResourceManager->deleteShader(mHandle);
253 unsigned int Shader::getRefCount() const
258 bool Shader::isFlaggedForDeletion() const
260 return mDeleteStatus;
263 void Shader::flagForDeletion()
265 mDeleteStatus = true;
268 void Shader::releaseCompiler()
270 FreeCompilerGlobals();
271 compilerInitialized = false;
274 GLenum Shader::parseType(const std::string &type)
280 else if(type == "float2")
282 return GL_FLOAT_VEC2;
284 else if(type == "float3")
286 return GL_FLOAT_VEC3;
288 else if(type == "float4")
290 return GL_FLOAT_VEC4;
292 else if(type == "float2x2")
294 return GL_FLOAT_MAT2;
296 else if(type == "float3x3")
298 return GL_FLOAT_MAT3;
300 else if(type == "float4x4")
302 return GL_FLOAT_MAT4;
309 // true if varying x has a higher priority in packing than y
310 bool Shader::compareVarying(const glsl::Varying &x, const glsl::Varying &y)
314 return x.size() > y.size();
319 case GL_FLOAT_MAT4: return true;
323 case GL_FLOAT_MAT4: return false;
324 case GL_FLOAT_MAT2: return true;
325 case GL_FLOAT_VEC4: return true;
326 case GL_FLOAT_MAT3: return true;
327 case GL_FLOAT_VEC3: return true;
328 case GL_FLOAT_VEC2: return true;
329 case GL_FLOAT: return true;
330 default: UNREACHABLE();
336 case GL_FLOAT_MAT4: return false;
337 case GL_FLOAT_MAT2: return false;
338 case GL_FLOAT_VEC4: return true;
339 case GL_FLOAT_MAT3: return true;
340 case GL_FLOAT_VEC3: return true;
341 case GL_FLOAT_VEC2: return true;
342 case GL_FLOAT: return true;
343 default: UNREACHABLE();
349 case GL_FLOAT_MAT4: return false;
350 case GL_FLOAT_MAT2: return false;
351 case GL_FLOAT_VEC4: return false;
352 case GL_FLOAT_MAT3: return true;
353 case GL_FLOAT_VEC3: return true;
354 case GL_FLOAT_VEC2: return true;
355 case GL_FLOAT: return true;
356 default: UNREACHABLE();
362 case GL_FLOAT_MAT4: return false;
363 case GL_FLOAT_MAT2: return false;
364 case GL_FLOAT_VEC4: return false;
365 case GL_FLOAT_MAT3: return false;
366 case GL_FLOAT_VEC3: return true;
367 case GL_FLOAT_VEC2: return true;
368 case GL_FLOAT: return true;
369 default: UNREACHABLE();
375 case GL_FLOAT_MAT4: return false;
376 case GL_FLOAT_MAT2: return false;
377 case GL_FLOAT_VEC4: return false;
378 case GL_FLOAT_MAT3: return false;
379 case GL_FLOAT_VEC3: return false;
380 case GL_FLOAT_VEC2: return true;
381 case GL_FLOAT: return true;
382 default: UNREACHABLE();
385 case GL_FLOAT: return false;
386 default: UNREACHABLE();
392 VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
397 VertexShader::~VertexShader()
402 GLenum VertexShader::getType()
404 return GL_VERTEX_SHADER;
407 int VertexShader::getSemanticIndex(const std::string &attributeName)
409 if(!attributeName.empty())
411 for(glsl::ActiveAttributes::iterator attribute = activeAttributes.begin(); attribute != activeAttributes.end(); attribute++)
413 if(attribute->name == attributeName)
415 return attribute->registerIndex;
423 sw::Shader *VertexShader::getShader() const
428 sw::VertexShader *VertexShader::getVertexShader() const
433 void VertexShader::createShader()
436 vertexShader = new sw::VertexShader();
439 void VertexShader::deleteShader()
442 vertexShader = nullptr;
445 FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
450 FragmentShader::~FragmentShader()
455 GLenum FragmentShader::getType()
457 return GL_FRAGMENT_SHADER;
460 sw::Shader *FragmentShader::getShader() const
465 sw::PixelShader *FragmentShader::getPixelShader() const
470 void FragmentShader::createShader()
473 pixelShader = new sw::PixelShader();
476 void FragmentShader::deleteShader()
479 pixelShader = nullptr;